Snapshot idea/138.1503 from git://git.jetbrains.org/idea/community.git

Change-Id: Ie01af1d8710ec0ff51d90301bda1a18b0b5c0faf
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 67bfbb2..c12c1c9 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -288,6 +288,13 @@
             <option name="TAB_SIZE" value="8" />
           </indentOptions>
         </codeStyleSettings>
+        <codeStyleSettings language="jet">
+          <indentOptions>
+            <option name="INDENT_SIZE" value="2"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="2"/>
+          </indentOptions>
+        </codeStyleSettings>
         <codeStyleSettings language="ruby">
           <option name="KEEP_LINE_BREAKS" value="false" />
           <option name="PARENT_SETTINGS_INSTALLED" value="true" />
diff --git a/.idea/libraries/Kryo.xml b/.idea/libraries/Kryo.xml
new file mode 100644
index 0000000..b11f03b
--- /dev/null
+++ b/.idea/libraries/Kryo.xml
@@ -0,0 +1,14 @@
+<component name="libraryTable">
+  <library name="Kryo">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/lib/minlog-1.2.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/kryo-2.22.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/reflectasm-1.07.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/objenesis-1.2.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/lib/src/kryo-src.zip!/src" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index ca7b52d..101efac 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -65,6 +65,7 @@
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" group="plugins/GAE" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" group="plugins/GAE" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
+      <module fileurl="file://$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" group="community/plugins/gradle" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" group="plugins/Groovy" />
@@ -118,6 +119,7 @@
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/python/main_idea_python_plugin.iml" filepath="$PROJECT_DIR$/python/main_idea_python_plugin.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
+      <module fileurl="file://$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" filepath="$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" group="python/educational" />
       <module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
@@ -144,6 +146,8 @@
       <module fileurl="file://$PROJECT_DIR$/python/build/python-community-build.iml" filepath="$PROJECT_DIR$/python/build/python-community-build.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" filepath="$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/testSrc/python-community-tests.iml" filepath="$PROJECT_DIR$/python/testSrc/python-community-tests.iml" group="python" />
+      <module fileurl="file://$PROJECT_DIR$/python/edu/build/python-edu-build.iml" filepath="$PROJECT_DIR$/python/edu/build/python-edu-build.iml" group="python/educational" />
+      <module fileurl="file://$PROJECT_DIR$/python/edu/python-educational.iml" filepath="$PROJECT_DIR$/python/edu/python-educational.iml" group="python/educational" />
       <module fileurl="file://$PROJECT_DIR$/python/python-helpers.iml" filepath="$PROJECT_DIR$/python/python-helpers.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/ide/python-ide-community.iml" filepath="$PROJECT_DIR$/python/ide/python-ide-community.iml" group="python" />
       <module fileurl="file://$PROJECT_DIR$/python/openapi/python-openapi.iml" filepath="$PROJECT_DIR$/python/openapi/python-openapi.iml" group="python" />
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
index 298e1c6..1973649 100644
--- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
+++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
@@ -19,16 +19,29 @@
 import com.intellij.lang.Language;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.lang.regexp.psi.RegExpGroup;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Collection;
+
+
 public class RegExpFile extends PsiFileBase {
 
-    public RegExpFile(FileViewProvider viewProvider, final Language language) {
-        super(viewProvider, language);
-    }
+  public RegExpFile(FileViewProvider viewProvider, final Language language) {
+    super(viewProvider, language);
+  }
 
-    @NotNull
-    public FileType getFileType() {
-        return RegExpFileType.INSTANCE;
-    }
+  @NotNull
+  public FileType getFileType() {
+    return RegExpFileType.INSTANCE;
+  }
+
+  /**
+   * @return Regexp groups this file has
+   */
+  @NotNull
+  public Collection<RegExpGroup> getGroups() {
+    return PsiTreeUtil.findChildrenOfType(this, RegExpGroup.class);
+  }
 }
diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe
index 5c5f103..29c5d33 100644
--- a/bin/win/runnerw.exe
+++ b/bin/win/runnerw.exe
Binary files differ
diff --git a/build/conf/nsis/DeleteSettings.ini b/build/conf/nsis/DeleteSettings.ini
index 2c93ebf..c43b912 100644
--- a/build/conf/nsis/DeleteSettings.ini
+++ b/build/conf/nsis/DeleteSettings.ini
@@ -1,26 +1,40 @@
 [Settings]
-NumFields=3
+NumFields=5
 
 [Field 1]
 Type=label
-Left=0
+Left=5
 Right=-1
 Top=0
-Bottom=40
+Bottom=10
 
 [Field 2]
-Type=checkbox
+Type=label
 Left=5
 Right=-1
-Top=40
-Bottom=50
-State=0
+Top=15
+Bottom=35
 
 [Field 3]
+Type=GroupBox
+Left=0
+Right=-1
+Top=40
+Bottom=90
+
+[Field 4]
 Type=checkbox
 Left=5
 Right=-1
-Top=60
-Bottom=70
+Top=55
+Bottom=65
+State=0
+
+[Field 5]
+Type=checkbox
+Left=5
+Right=-1
+Top=70
+Bottom=80
 State=0
 
diff --git a/build/conf/nsis/UninstallOldVersions.ini b/build/conf/nsis/UninstallOldVersions.ini
index 0a8f760..f8444c3 100644
--- a/build/conf/nsis/UninstallOldVersions.ini
+++ b/build/conf/nsis/UninstallOldVersions.ini
@@ -1,5 +1,5 @@
 [Settings]
-NumFields=10
+NumFields=13
 
 [Field 1]
 Type=label
@@ -7,94 +7,112 @@
 Left=5
 Right=-1
 Top=0
-Bottom=15
+Bottom=10
 
 [Field 2]
 Type=checkbox
-Text=Uninstall old version
-Left=12
-Right=200
-Top=25
-Bottom=35
-State=0
-Flags=NOTIFY
-
-[Field 3]
-Type=checkbox
-Text=Quick uninstallation
-Left=12
-Right=200
+Text=Uninstall silently (settings and configuration from old versions will not be deleted)
+Left=5
+Right=-1
 Top=123
 Bottom=133
 State=0
-Flags=DISABLED
+
+[Field 3]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=12
+Bottom=22
+State=0
 
 [Field 4]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=39
-Bottom=49
+Left=12
+Right=-1
+Top=22
+Bottom=32
 State=0
-Flags=DISABLED
 
 [Field 5]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=51
-Bottom=61
+Left=12
+Right=-1
+Top=32
+Bottom=42
 State=0
-Flags=DISABLED
 
 [Field 6]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=63
-Bottom=73
+Left=12
+Right=-1
+Top=42
+Bottom=52
 State=0
-Flags=DISABLED
 
 [Field 7]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=75
-Bottom=85
+Left=12
+Right=-1
+Top=52
+Bottom=62
 State=0
-Flags=DISABLED
 
 [Field 8]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=87
-Bottom=97
+Left=12
+Right=-1
+Top=62
+Bottom=72
 State=0
-Flags=DISABLED
 
 [Field 9]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=99
-Bottom=109
+Left=12
+Right=-1
+Top=72
+Bottom=82
 State=0
-Flags=DISABLED
 
 [Field 10]
 Type=checkbox
 Text=An old installation
-Left=20
-Right=300
-Top=111
-Bottom=121
+Left=12
+Right=-1
+Top=82
+Bottom=92
 State=0
-Flags=DISABLED
\ No newline at end of file
+
+[Field 11]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=92
+Bottom=102
+State=0
+
+[Field 12]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=102
+Bottom=112
+State=0
+
+[Field 13]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=112
+Bottom=122
+State=0
diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi
index 5f31dc3..e9f4b49 100644
--- a/build/conf/nsis/idea.nsi
+++ b/build/conf/nsis/idea.nsi
@@ -342,7 +342,7 @@
 
 !insertmacro MUI_PAGE_WELCOME
 
-Page custom uninstallOldVersionDialog leaveUninstallOldVersionDialog
+Page custom uninstallOldVersionDialog
 
 Var control_fields
 Var max_fields
@@ -367,7 +367,7 @@
 !insertmacro MUI_PAGE_FINISH
 
 !define MUI_UNINSTALLER
-!insertmacro MUI_UNPAGE_CONFIRM
+;!insertmacro MUI_UNPAGE_CONFIRM
 UninstPage custom un.ConfirmDeleteSettings
 !insertmacro MUI_UNPAGE_INSTFILES
 
@@ -473,10 +473,10 @@
   CopyFiles "$3\bin\${PRODUCT_EXE_FILE}_copy" "$3\bin\${PRODUCT_EXE_FILE}"
   Delete "$3\bin\${PRODUCT_EXE_FILE}_copy"
   IfErrors 0 +3
-  MessageBox MB_YESNOCANCEL|MB_ICONQUESTION|MB_TOPMOST "$(application_running)" IDYES remove_previous_installation IDNO complete
+  MessageBox MB_OKCANCEL|MB_ICONQUESTION|MB_TOPMOST "$(application_running)" IDOK remove_previous_installation IDCANCEL complete
   goto complete
   ; uninstallation mode
-  !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 3" "State"
+  !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 2" "State"
   ${If} $9 == "1"
     ExecWait '"$3\bin\Uninstall.exe" /S'
   ${else}
@@ -518,8 +518,8 @@
 
 
 Function uninstallOldVersionDialog
-  StrCpy $control_fields 3
-  StrCpy $max_fields 10
+  StrCpy $control_fields 2
+  StrCpy $max_fields 13
   StrCpy $0 "HKLM"
   StrCpy $4 0
   ReserveFile "UninstallOldVersions.ini"
@@ -562,10 +562,11 @@
     StrCpy $2 ""
   !insertmacro MUI_HEADER_TEXT "$(uninstall_previous_installations_title)" "$(uninstall_previous_installations)"
   !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 1" "Text" "$(uninstall_previous_installations_prompt)"
+  !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 3" "Flags" "FOCUS"
   !insertmacro INSTALLOPTIONS_DISPLAY "UninstallOldVersions.ini"
   ;uninstall chosen installation(s)
 
-  StrCmp $2 "OK" loop finish
+  ;no disabled controls. StrCmp $2 "OK" loop finish
 loop:
   !insertmacro INSTALLOPTIONS_READ $0 "UninstallOldVersions.ini" "Field $8" "State"
   !insertmacro INSTALLOPTIONS_READ $3 "UninstallOldVersions.ini" "Field $8" "Text"
@@ -579,65 +580,6 @@
 FunctionEnd
 
 
-Function leaveUninstallOldVersionDialog
-  Push $1
-  Push $4
-  !insertmacro INSTALLOPTIONS_READ $2 "UninstallOldVersions.ini" "Settings" "State"
-  StrCmp $2 2 enable_disable
-  Goto done
-
-enable_disable:
-  !insertmacro INSTALLOPTIONS_READ $0 "UninstallOldVersions.ini" "Field 2" "State"
-  StrCmp $0 1 enable disable
-enable:
-  StrCpy $1 ""
-  Goto setFlag
-disable:
-  Call setState
-  StrCpy $1 "DISABLED"
-
-setFlag:
-  Push $1
-  Call setFlags
-done:
-  Pop $4
-  Pop $1
-  StrCmp $2 0 skip_abort
-  Pop $2
-  Abort
-skip_abort:
-  StrCpy $2 "OK"
-FunctionEnd
-
-Function setFlags
-  Pop $1
-  !insertmacro INSTALLOPTIONS_READ $max_fields "UninstallOldVersions.ini" "Settings" "NumFields"
-  StrCpy $4 3
-  ; change flags of fields in according of master checkbox
-loop:
-  !insertmacro INSTALLOPTIONS_READ $1 "UninstallOldVersions.ini" "Field $4" "HWND"
-  EnableWindow $1 $0
-  !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $4" "Flags" "$1"
-  IntOp $4 $4 + 1
-  ${If} $4 <= $max_fields
-    Goto loop
-  ${EndIf}
-FunctionEnd
-
-Function setState
-  !insertmacro INSTALLOPTIONS_READ $max_fields "UninstallOldVersions.ini" "Settings" "NumFields"
-  StrCpy $4 3
-  ; change state of fields in according of master checkbox
-loop:
-  !insertmacro INSTALLOPTIONS_READ $1 "UninstallOldVersions.ini" "Field $4" "HWND"
-  SendMessage $1 ${BM_SETCHECK} 0 "0"
-  !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $4" "State" 0
-  IntOp $4 $4 + 1
-  ${If} $4 <= $max_fields
-    Goto loop
-  ${EndIf}
-FunctionEnd
-
 Function getInstallationPath
   Push $1
   Push $2
@@ -1054,8 +996,10 @@
 Function un.ConfirmDeleteSettings
   !insertmacro MUI_HEADER_TEXT "$(uninstall_options)" "$(uninstall_options_prompt)"
   !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 1" "Text" "$(prompt_delete_settings)"
-  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" "$(confirm_delete_caches)"
-  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(confirm_delete_settings)"
+  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" $INSTDIR
+  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(text_delete_settings)"
+  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 4" "Text" "$(confirm_delete_caches)"
+  !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 5" "Text" "$(confirm_delete_settings)"
   !insertmacro INSTALLOPTIONS_DISPLAY "DeleteSettings.ini"
 FunctionEnd
 
@@ -1133,7 +1077,7 @@
   ; Uninstaller is in the \bin directory, we need upper level dir
   StrCpy $INSTDIR $INSTDIR\..
 
-  !insertmacro INSTALLOPTIONS_READ $R2 "DeleteSettings.ini" "Field 2" "State"
+  !insertmacro INSTALLOPTIONS_READ $R2 "DeleteSettings.ini" "Field 4" "State"
   DetailPrint "Data: $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\"
   StrCmp $R2 1 "" skip_delete_caches
    ;find the path to caches (system) folder
@@ -1147,7 +1091,7 @@
 ;   RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\system
 skip_delete_caches:
 
-  !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 3" "State"
+  !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 5" "State"
   StrCmp $R3 1 "" skip_delete_settings
     ;find the path to settings (config) folder
     StrCpy $0 "config"
diff --git a/build/conf/nsis/idea_en.nsi b/build/conf/nsis/idea_en.nsi
index 65d9171..1cb4408 100644
--- a/build/conf/nsis/idea_en.nsi
+++ b/build/conf/nsis/idea_en.nsi
@@ -7,15 +7,16 @@
 
 ; Uninstall options page
 LangString uninstall_options ${LANG_ENGLISH} "Uninstall ${MUI_PRODUCT}"
-LangString uninstall_options_prompt ${LANG_ENGLISH} "Remove ${MUI_PRODUCT} from your computer"
-LangString prompt_delete_settings ${LANG_ENGLISH} "Please confirm if you would like to delete the caches and settings of ${MUI_PRODUCT}."
+LangString uninstall_options_prompt ${LANG_ENGLISH} ""
+LangString prompt_delete_settings ${LANG_ENGLISH} "${MUI_PRODUCT} will be uninstalled from the following folder:"
+LangString text_delete_settings ${LANG_ENGLISH} "Please confirm if you would like to delete the caches and settings:"
 LangString confirm_delete_caches ${LANG_ENGLISH} "Delete ${MUI_PRODUCT} ${MUI_VERSION_MAJOR} caches and local history"
 LangString confirm_delete_settings ${LANG_ENGLISH} "Delete ${MUI_PRODUCT} ${MUI_VERSION_MAJOR} settings and installed plugins"
 
 ; Installation message boxes
 LangString current_version_already_installed ${LANG_ENGLISH} "Current version of ${MUI_PRODUCT} is already installed. Do you wish to continue?"
 LangString uninstall_previous_installations_title ${LANG_ENGLISH} "Uninstall old versions"
-LangString uninstall_previous_installations ${LANG_ENGLISH} "Installation found old versions of ${MUI_PRODUCT}. You can see list of the installations below."
-LangString uninstall_previous_installations_prompt ${LANG_ENGLISH} "Please select the version$2 of ${MUI_PRODUCT} which you would like to uninstall and mode of uninstallation."
+LangString uninstall_previous_installations ${LANG_ENGLISH} ""
+LangString uninstall_previous_installations_prompt ${LANG_ENGLISH} "Select the ${MUI_PRODUCT} version$2 that you want to uninstall."
 LangString empty_or_upgrade_folder ${LANG_ENGLISH} "Please select an empty folder or a folder where ${MUI_PRODUCT} ${UPGRADE_VERSION} is installed as the target for installing ${MUI_PRODUCT}."
-LangString application_running ${LANG_ENGLISH} "Installation detects that $3 is running. Can you stop the application and then continue uninstallation please?"
+LangString application_running ${LANG_ENGLISH} "$3 is running. Close the application and retry the installation."
diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant
index e7aaf1a..d9e4138 100644
--- a/build/scripts/common_tests.gant
+++ b/build/scripts/common_tests.gant
@@ -51,6 +51,7 @@
       pass("idea.test.group")
       pass("idea.test.patterns")
       pass("idea.fast.only")
+      pass("idea.coverage.enabled.build")
       pass("teamcity.build.tempDir")
       pass("teamcity.tests.recentlyFailedTests.file")
       jvmarg(value: "-Didea.platform.prefix=Idea")
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 870b2c5..f91ac85 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -336,6 +336,10 @@
     }
 
     layoutPlugin("gradle") {
+      jar("gradle-jps-plugin.jar") {
+        module("gradle-jps-plugin")
+      }
+
       jar("gradle-tooling-extension-api.jar") {
         module("gradle-tooling-extension-api")
       }
@@ -344,6 +348,13 @@
         module("gradle-tooling-extension-impl")
       }
       fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") }
+      // add kryo lib
+      fileset(dir: "$home/lib/") {
+        include(name: "kryo-*.jar")
+        include(name: "reflectasm-*.jar")
+        include(name: "objenesis-*.jar")
+        include(name: "minlog-*.jar")
+      }
     }
 
     layoutPlugin("git4idea") {
@@ -753,6 +764,7 @@
 
 
       jar("maven-jps-plugin.jar") { module("maven-jps-plugin") }
+      jar("gradle-jps-plugin.jar") { module("gradle-jps-plugin") }
       fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "plexus-utils-*.jar")}
 
       jar("eclipse-jps-plugin.jar") {
@@ -805,8 +817,9 @@
       module("annotations")
     }
 
-    jar("intellij-core-analysis-api.jar") {
+    jar("intellij-core-analysis.jar") {
       analysisApiModules.each { module it; }
+      analysisImplModules.each { module it; }
     }
 
     fileset(dir: "$home/lib") {
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index eaeb82e..d495f95 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -50,7 +50,8 @@
   def name = lib.name
   if (name.startsWith("#")) {
     if (lib.getRoots(JpsOrderRootType.COMPILED).size() != 1) {
-      projectBuilder.warning("Non-single entry module library $name: $lib.classpath");
+      def urls = lib.getRoots(JpsOrderRootType.COMPILED).collect {it.url}
+      projectBuilder.warning("Non-single entry module library $name: $urls");
     }
     File file = lib.getFiles(JpsOrderRootType.COMPILED)[0]
     return file.name
@@ -213,6 +214,7 @@
 libraryLicense(name: "plexus-component-annotations", version: "1.5.5", libraryNames: ["plexus-component-annotations-1.5.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
 libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.5", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
 libraryLicense(name: "Gradle", version: "1.12", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
+libraryLicense(name: "gradle-tooling-api-2.0.jar", version: "2.0", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
 libraryLicense(name: "GradleJnaPosix", version: "1.0.3", license: "LGPL 2.1", url: "http://www.jruby.org/", licenseUrl: "http://www.gnu.org/licenses/lgpl-2.1.txt")
 libraryLicense(name: "Slf4j", version: "1.7.2", license: "MIT License", url: "http://slf4j.org/", licenseUrl: "http://slf4j.org/license.html")
 libraryLicense(name: "GradleGuava", version: "14.0.1", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant
index 14bd38a..b512a18 100644
--- a/build/scripts/tests.gant
+++ b/build/scripts/tests.gant
@@ -9,6 +9,7 @@
 def args = [
         "-Xmx450m",
         "-XX:MaxPermSize=430m",
+        "-XX:ReservedCodeCacheSize=96m"
 ]
 if (isMac) args << "-d32";
 
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index d64c75f..ae07104 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -53,11 +53,11 @@
   return "true" == p("component.version.eap")
 })
 
-binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m")
-binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m")
+binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=150m")
+binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=225m")
 binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
                                         "-Djsse.enableSNIExtension=false " +
-                                        "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
+                                        "-XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
 
 binding.setVariable("vmOptions", { "$common_vmoptions ${isEap() ? '-XX:+HeapDumpOnOutOfMemoryError' : ''}".trim() })
 binding.setVariable("vmOptions32", { "$mem32 ${vmOptions()}".trim() })
@@ -919,3 +919,16 @@
     "xml-psi-api",
     "xml-structure-view-api",
 ])
+binding.setVariable("analysisImplModules", [
+    "analysis-impl",
+    "core-impl",
+    "indexing-impl",
+    "java-analysis-impl",
+    "java-indexing-impl",
+    "java-psi-impl",
+    "projectModel-impl",
+    "structure-view-impl",
+    "xml-analysis-impl",
+    "xml-psi-impl",
+    "xml-structure-view-impl",
+])
diff --git a/colorSchemes/src/colorSchemes/Darcula.xml b/colorSchemes/src/colorSchemes/Darcula.xml
index ec6fcc3..9691e1d 100644
--- a/colorSchemes/src/colorSchemes/Darcula.xml
+++ b/colorSchemes/src/colorSchemes/Darcula.xml
@@ -702,9 +702,9 @@
     </option>
     <option name="IDENTIFIER_UNDER_CARET_ATTRIBUTES">
       <value>
-        <option name="EFFECT_COLOR" value="5d8730" />
-        <option name="EFFECT_TYPE" value="1" />
+        <option name="BACKGROUND" value="344134" />
         <option name="ERROR_STRIPE_COLOR" value="5d8e48" />
+        <option name="EFFECT_TYPE" value="1" />
       </value>
     </option>
     <option name="IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES">
@@ -1572,9 +1572,9 @@
     </option>
     <option name="WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES">
       <value>
-        <option name="EFFECT_COLOR" value="cc7832" />
-        <option name="EFFECT_TYPE" value="1" />
+        <option name="BACKGROUND" value="40332b" />
         <option name="ERROR_STRIPE_COLOR" value="cc7832" />
+        <option name="EFFECT_TYPE" value="1" />
       </value>
     </option>
     <option name="WRITE_SEARCH_RESULT_ATTRIBUTES">
diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml
index 08d3ca1..c6e3e4f 100644
--- a/java/compiler/impl/compiler-impl.iml
+++ b/java/compiler/impl/compiler-impl.iml
@@ -28,6 +28,7 @@
     <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
     <orderEntry type="module" module-name="jps-model-impl" />
     <orderEntry type="module" module-name="java-analysis-impl" />
+    <orderEntry type="module" module-name="xml" />
   </component>
   <component name="copyright">
     <Base>
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index 03ff006..01da3bc 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -128,8 +128,6 @@
   private static final String COMPILER_PROCESS_JDK_PROPERTY = "compiler.process.jdk";
   public static final String SYSTEM_ROOT = "compile-server";
   public static final String TEMP_DIR_NAME = "_temp_";
-  private static final int MAKE_TRIGGER_DELAY = 300 /*300 ms*/;
-  private static final int DOCUMENT_SAVE_TRIGGER_DELAY = 1500 /*1.5 sec*/;
   private final boolean IS_UNIT_TEST_MODE;
   private static final String IWS_EXTENSION = ".iws";
   private static final String IPR_EXTENSION = ".ipr";
@@ -161,7 +159,7 @@
   private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask() {
     @Override
     protected int getDelay() {
-      return Registry.intValue("compiler.automake.trigger.delay", MAKE_TRIGGER_DELAY);
+      return Registry.intValue("compiler.automake.trigger.delay");
     }
 
     @Override
@@ -173,7 +171,7 @@
   private final BuildManagerPeriodicTask myDocumentSaveTask = new BuildManagerPeriodicTask() {
     @Override
     protected int getDelay() {
-      return Registry.intValue("compiler.document.save.trigger.delay", DOCUMENT_SAVE_TRIGGER_DELAY);
+      return Registry.intValue("compiler.document.save.trigger.delay");
     }
 
     private final Semaphore mySemaphore = new Semaphore();
@@ -624,7 +622,7 @@
               data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
               myProjectDataMap.put(projectPath, data);
             }
-            if (isRebuild || (isAutomake && Registry.is("compiler.automake.force.fs.rescan", false))) {
+            if (isRebuild || (isAutomake && Registry.is("compiler.automake.force.fs.rescan"))) {
               data.dropChanges();
             }
             if (IS_UNIT_TEST_MODE) {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
index 5752c3f..3fcfc8d 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
@@ -26,10 +26,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.packaging.artifacts.Artifact;
-import com.intellij.packaging.artifacts.ArtifactManager;
-import com.intellij.packaging.artifacts.ArtifactProperties;
-import com.intellij.packaging.artifacts.ArtifactType;
+import com.intellij.packaging.artifacts.*;
 import com.intellij.packaging.elements.*;
 import com.intellij.packaging.impl.elements.*;
 import com.intellij.util.PathUtil;
@@ -599,5 +596,31 @@
   public static String suggestArtifactFileName(String artifactName) {
     return PathUtil.suggestFileName(artifactName, true, true);
   }
+
+  @Nullable
+  public static Artifact addArtifact(@NotNull ModifiableArtifactModel artifactModel,
+                                     @NotNull ArtifactType type,
+                                     @NotNull ArtifactTemplate artifactTemplate) {
+    final ArtifactTemplate.NewArtifactConfiguration configuration = artifactTemplate.createArtifact();
+    if (configuration == null) {
+      return null;
+    }
+
+    final String baseName = configuration.getArtifactName();
+    String name = baseName;
+    int i = 2;
+    while (artifactModel.findArtifact(name) != null) {
+      name = baseName + i;
+      i++;
+    }
+
+    ArtifactType actualType = configuration.getArtifactType();
+    if (actualType == null) {
+      actualType = type;
+    }
+    final ModifiableArtifact artifact = artifactModel.addArtifact(name, actualType, configuration.getRootElement());
+    artifactTemplate.setUpArtifact(artifact, configuration);
+    return artifact;
+  }
 }
 
diff --git a/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java b/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java
new file mode 100644
index 0000000..4733ca3
--- /dev/null
+++ b/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java
@@ -0,0 +1,39 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactManager;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+final class ArtifactWebServerRootsProvider extends PrefixlessWebServerRootsProvider {
+  @Nullable
+  @Override
+  public PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver) {
+    for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
+      VirtualFile root = artifact.getOutputFile();
+      if (root != null) {
+        VirtualFile file = root.findFileByRelativePath(path);
+        if (file != null) {
+          return new PathInfo(file, root);
+        }
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  @Override
+  public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
+    for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
+      VirtualFile root = artifact.getOutputFile();
+      if (root != null && VfsUtilCore.isAncestor(root, file, true)) {
+        return new PathInfo(file, root);
+      }
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java
index 88095a9..e5b8aee 100644
--- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java
+++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java
@@ -466,7 +466,7 @@
       public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
         classfileVersion[0] = version;
       }
-    }, 0);
+    }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
 
     return classfileVersion[0];
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
index 01d6fcc..6214a9e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,14 +17,12 @@
 
 import com.intellij.debugger.DebuggerBundle;
 import com.intellij.debugger.engine.JavaDebugProcess;
-import com.intellij.debugger.settings.DebuggerDataViewsConfigurable;
+import com.intellij.debugger.settings.JavaDebuggerSettings;
 import com.intellij.debugger.settings.NodeRendererSettings;
-import com.intellij.debugger.settings.UserRenderersConfigurable;
 import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.options.CompositeConfigurable;
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.TabbedConfigurable;
@@ -40,16 +38,9 @@
 
 import javax.swing.*;
 import javax.swing.border.EmptyBorder;
-import java.util.ArrayList;
 import java.util.List;
 
-/**
- * User: lex
- * Date: Sep 26, 2003
- * Time: 4:39:53 PM
- */
 public class CustomizeContextViewAction extends XDebuggerTreeActionBase {
-
   @Override
   public void actionPerformed(AnActionEvent e) {
     perform(null, "", e);
@@ -58,15 +49,11 @@
   @Override
   protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) {
     final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
-
     Disposable disposable = Disposer.newDisposable();
-    final CompositeConfigurable configurable = new TabbedConfigurable(disposable) {
+    SingleConfigurableEditor editor = new SingleConfigurableEditor(project, new TabbedConfigurable(disposable) {
       @Override
       protected List<Configurable> createConfigurables() {
-        ArrayList<Configurable> array = new ArrayList<Configurable>();
-        array.add(new DebuggerDataViewsConfigurable(project));
-        array.add(new UserRenderersConfigurable(project));
-        return array;
+        return JavaDebuggerSettings.createDataViewsConfigurable();
       }
 
       @Override
@@ -89,13 +76,12 @@
       protected void createConfigurableTabs() {
         for (Configurable configurable : getConfigurables()) {
           JComponent component = configurable.createComponent();
-          component.setBorder(new EmptyBorder(8,8,8,8));
+          assert component != null;
+          component.setBorder(new EmptyBorder(8, 8, 8, 8));
           myTabbedPane.addTab(configurable.getDisplayName(), component);
         }
       }
-    };
-
-    SingleConfigurableEditor editor = new SingleConfigurableEditor(project, configurable);
+    });
     Disposer.register(editor.getDisposable(), disposable);
     editor.show();
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
index 1db0ed6..4714ca4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
@@ -322,10 +322,15 @@
       myDebugProcessDispatcher.getMulticaster().processAttached(this);
 
       // breakpoints should be initialized after all processAttached listeners work
-      XDebugSession session = getSession().getXDebugSession();
-      if (session != null) {
-        session.initBreakpoints();
-      }
+      ApplicationManager.getApplication().runReadAction(new Runnable() {
+        @Override
+        public void run() {
+          XDebugSession session = getSession().getXDebugSession();
+          if (session != null) {
+            session.initBreakpoints();
+          }
+        }
+      });
 
       final String addressDisplayName = DebuggerBundle.getAddressDisplayName(getConnection());
       final String transportName = DebuggerBundle.getTransportName(getConnection());
@@ -459,13 +464,18 @@
 
         if (requestHit && requestor instanceof Breakpoint) {
           // if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy
-          XDebugSession session = getSession().getXDebugSession();
-          if (session != null) {
-            XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint();
-            if (breakpoint != null) {
-              ((XDebugSessionImpl)session).processDependencies(breakpoint);
+          ApplicationManager.getApplication().runReadAction(new Runnable() {
+            @Override
+            public void run() {
+              XDebugSession session = getSession().getXDebugSession();
+              if (session != null) {
+                XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint();
+                if (breakpoint != null) {
+                  ((XDebugSessionImpl)session).processDependencies(breakpoint);
+                }
+              }
             }
-          }
+          });
         }
 
         if(!requestHit || resumePreferred) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
index ad2c881..7589741 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
@@ -49,13 +49,17 @@
     if (javaBreakpoint != null) {
       final Breakpoint bpt = javaBreakpoint;
       BreakpointManager.addBreakpoint(bpt);
-      // must use invoke to stay in the current request,
-      // otherwise dependent breakpoints do not get enabled on not-suspending parents hit
-      myProcess.getManagerThread().invoke(new DebuggerCommandImpl() {
+      // use schedule not to block initBreakpoints
+      myProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
         @Override
         protected void action() throws Exception {
           bpt.createRequest(myProcess);
         }
+
+        @Override
+        public Priority getPriority() {
+          return Priority.HIGH;
+        }
       });
     }
   }
@@ -64,12 +68,17 @@
   public void unregisterBreakpoint(@NotNull final XBreakpoint breakpoint, boolean temporary) {
     final Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
     if (javaBreakpoint != null) {
-      // must use invoke to stay in the current request, see comment in registerBreakpoint
-      myProcess.getManagerThread().invoke(new DebuggerCommandImpl() {
+      // use schedule not to block initBreakpoints
+      myProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
         @Override
         protected void action() throws Exception {
           javaBreakpoint.delete();
         }
+
+        @Override
+        public Priority getPriority() {
+          return Priority.HIGH;
+        }
       });
     }
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
index 793438e..f2cb400 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
@@ -26,6 +26,7 @@
 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
 import com.intellij.debugger.settings.DebuggerSettings;
 import com.intellij.debugger.ui.impl.watch.MethodsTracker;
+import com.intellij.debugger.ui.impl.watch.NodeManagerImpl;
 import com.intellij.icons.AllIcons;
 import com.intellij.xdebugger.frame.XExecutionStack;
 import com.sun.jdi.ThreadReference;
@@ -43,6 +44,7 @@
 public class JavaExecutionStack extends XExecutionStack {
   private final ThreadReferenceProxyImpl myThreadProxy;
   private final DebugProcessImpl myDebugProcess;
+  private final NodeManagerImpl myNodeManager;
   private volatile JavaStackFrame myTopFrame;
   private boolean myTopFrameReady = false;
   private final MethodsTracker myTracker = new MethodsTracker();
@@ -51,6 +53,7 @@
     super(calcRepresentation(threadProxy), calcIcon(threadProxy, current));
     myThreadProxy = threadProxy;
     myDebugProcess = debugProcess;
+    myNodeManager = myDebugProcess.getXdebugProcess().getNodeManager();
     if (current) {
       myTopFrame = calcTopFrame();
     }
@@ -81,7 +84,7 @@
     try {
       StackFrameProxyImpl frame = myThreadProxy.frame(0);
       if (frame != null) {
-        return new JavaStackFrame(frame, myDebugProcess, myTracker);
+        return new JavaStackFrame(frame, myDebugProcess, myTracker, myNodeManager);
       }
     }
     catch (EvaluateException e) {
@@ -180,7 +183,7 @@
     @Override
     public void contextAction() throws Exception {
       if (myStackFramesIterator.hasNext()) {
-        JavaStackFrame frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker);
+        JavaStackFrame frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker, myNodeManager);
         if (DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) {
           if (++myAdded > mySkip) {
             myContainer.addStackFrames(Arrays.asList(frame), false);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
index bcd8257..db28c4b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
@@ -71,9 +71,12 @@
   private static final JavaFramesListRenderer FRAME_RENDERER = new JavaFramesListRenderer();
   private JavaDebuggerEvaluator myEvaluator = null;
 
-  public JavaStackFrame(@NotNull StackFrameProxyImpl stackFrameProxy, @NotNull DebugProcessImpl debugProcess, MethodsTracker tracker) {
+  public JavaStackFrame(@NotNull StackFrameProxyImpl stackFrameProxy,
+                        @NotNull DebugProcessImpl debugProcess,
+                        @NotNull MethodsTracker tracker,
+                        @NotNull NodeManagerImpl nodeManager) {
     myDebugProcess = debugProcess;
-    myNodeManager = debugProcess.getXdebugProcess().getNodeManager();
+    myNodeManager = nodeManager;
     myDescriptor = new StackFrameDescriptorImpl(stackFrameProxy, tracker);
     myDescriptor.setContext(null);
     myDescriptor.updateRepresentation(null, DescriptorLabelListener.DUMMY_LISTENER);
@@ -311,8 +314,7 @@
         final Collection<Value> argValues = frame.getArgumentValues();
         int index = 0;
         for (Value argValue : argValues) {
-          final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index++, argValue, null);
-          children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
+          children.add(createArgumentValue(index++, argValue, null, evaluationContext));
         }
         node.setMessage(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
         //myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
@@ -323,9 +325,7 @@
           try {
             final Map<DecompiledLocalVariable, Value> values = LocalVariablesUtil.fetchValues(frame.getStackFrame(), decompiled);
             for (DecompiledLocalVariable var : decompiled) {
-              final Value value = values.get(var);
-              final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, var.getSlot(), value, var.getName());
-              children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
+              children.add(createArgumentValue(var.getSlot(), values.get(var), var.getName(), evaluationContext));
             }
           }
           catch (Exception ex) {
@@ -339,6 +339,13 @@
     }
   }
 
+  private JavaValue createArgumentValue(int index, Value value, String name, EvaluationContextImpl evaluationContext) {
+    ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index, value, name);
+    // setContext is required to calculate correct name
+    descriptor.setContext(evaluationContext);
+    return JavaValue.create(descriptor, evaluationContext, myNodeManager);
+  }
+
   protected void superBuildVariables(final EvaluationContextImpl evaluationContext, XValueChildrenList children) throws EvaluateException {
     final StackFrameProxyImpl frame = getStackFrameProxy();
     for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
@@ -354,6 +361,6 @@
   @Nullable
   @Override
   public Object getEqualityObject() {
-    return getStackFrameProxy().hashCode();
+    return myDescriptor.getMethod();
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
index be1b8fa..6a555a8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
@@ -30,8 +30,7 @@
 
   @Override
   public boolean canMark(@NotNull JavaValue value) {
-    Value obj = value.getDescriptor().getValue();
-    return obj instanceof ObjectReference;
+    return value.getDescriptor().canMark();
   }
 
   @Override
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
index 576f781..c1f1f87 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.debugger.engine;
 
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
 import com.intellij.openapi.diagnostic.Logger;
 import com.sun.jdi.InternalException;
@@ -296,7 +297,7 @@
     }
   }
 
-  private void processVote(SuspendContextImpl suspendContext) {
+  private void processVote(final SuspendContextImpl suspendContext) {
     LOG.assertTrue(suspendContext.myVotesToVote > 0);
     suspendContext.myVotesToVote--;
 
@@ -305,7 +306,18 @@
     }
     if(suspendContext.myVotesToVote == 0) {
       if(suspendContext.myIsVotedForResume) {
-        resume(suspendContext);
+        // resume in a separate request to allow other requests be processed (e.g. dependent bpts enable)
+        myDebugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
+          @Override
+          protected void action() throws Exception {
+            resume(suspendContext);
+          }
+
+          @Override
+          public Priority getPriority() {
+            return Priority.HIGH;
+          }
+        });
       }
       else {
         if (LOG.isDebugEnabled()) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
index 69cbb14..2569559 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
@@ -30,7 +30,10 @@
 import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
 import com.intellij.debugger.impl.DebuggerUtilsEx;
 import com.intellij.openapi.diagnostic.Logger;
-import com.sun.jdi.*;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.Method;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -127,14 +130,16 @@
         _refType = ((ClassType)referenceType).superclass();
       }
       Method jdiMethod = DebuggerUtils.findMethod(_refType, myMethodName, signature);
-      if (jdiMethod == null || jdiMethod.argumentTypes().size() != args.size()) {
+      if (signature == null) {
+        // we know nothing about expected method's signature, so trying to match my method name and parameter count
         // dummy matching, may be improved with types matching later
-        List<Method> methods = _refType.methodsByName(myMethodName);
-        for (Method method : methods) {
-          List<Type> types = method.argumentTypes();
-          if (types.size() == args.size()) {
-            jdiMethod = method;
-            break;
+        // IMPORTANT! using argumentTypeNames() instead of argumentTypes() to avoid type resolution inside JDI, which may be time-consuming
+        if (jdiMethod == null || jdiMethod.argumentTypeNames().size() != args.size()) {
+          for (Method method : _refType.methodsByName(myMethodName)) {
+            if (method.argumentTypeNames().size() == args.size()) {
+              jdiMethod = method;
+              break;
+            }
           }
         }
       }
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
index f5404cd..79c1db3 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
@@ -28,6 +28,7 @@
 import com.intellij.execution.configurations.ModuleRunProfile;
 import com.intellij.execution.configurations.RemoteConnection;
 import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.process.KillableColoredProcessHandler;
 import com.intellij.execution.process.ProcessAdapter;
 import com.intellij.execution.process.ProcessEvent;
 import com.intellij.execution.process.ProcessHandler;
@@ -286,7 +287,8 @@
           final DebugProcessImpl debugProcess = getDebugProcess(event.getProcessHandler());
           if (debugProcess != null) {
             // if current thread is a "debugger manager thread", stop will execute synchronously
-            debugProcess.stop(willBeDestroyed);
+            // it is KillableColoredProcessHandler responsibility to terminate VM
+            debugProcess.stop(willBeDestroyed && !(event.getProcessHandler() instanceof KillableColoredProcessHandler));
 
             // wait at most 10 seconds: the problem is that debugProcess.stop() can hang if there are troubles in the debuggee
             // if processWillTerminate() is called from AWT thread debugProcess.waitFor() will block it and the whole app will hang
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
index 7b76b97..02f4ee4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
@@ -110,7 +110,9 @@
     else if (parent instanceof PsiInstanceOfExpression
              || parent instanceof PsiBinaryExpression
              || parent instanceof PsiPolyadicExpression
-             || parent instanceof PsiPrefixExpression) {
+             || parent instanceof PsiPrefixExpression
+             || parent instanceof PsiConditionalExpression
+      ) {
       if (allowMethodCalls || !DebuggerUtils.hasSideEffects(parent)) {
         expression = parent;
       }
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
index e570b64..a4484cc 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
@@ -25,14 +25,10 @@
 import com.intellij.debugger.ui.DebuggerExpressionTextField;
 import com.intellij.debugger.ui.JavaDebuggerSupport;
 import com.intellij.debugger.ui.tree.render.*;
-import com.intellij.openapi.Disposable;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.UnnamedConfigurable;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -41,7 +37,7 @@
 import com.intellij.util.Function;
 import com.intellij.util.ui.AbstractTableCellEditor;
 import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.table.AbstractTableModel;
@@ -52,57 +48,33 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * @author Eugene Zhuravlev
- *         Date: Feb 24, 2005
- */
-public class CompoundRendererConfigurable implements UnnamedConfigurable {
+class CompoundRendererConfigurable extends JPanel {
   private CompoundReferenceRenderer myRenderer;
   private CompoundReferenceRenderer myOriginalRenderer;
   private Project myProject;
-  private ClassNameEditorWithBrowseButton myClassNameField;
-  private JRadioButton myRbDefaultLabel;
-  private JRadioButton myRbExpressionLabel;
-  private JRadioButton myRbDefaultChildrenRenderer;
-  private JRadioButton myRbExpressionChildrenRenderer;
-  private JRadioButton myRbListChildrenRenderer;
-  private DebuggerExpressionTextField myLabelEditor;
-  private DebuggerExpressionTextField myChildrenEditor;
-  private DebuggerExpressionTextField myChildrenExpandedEditor;
+  private final ClassNameEditorWithBrowseButton myClassNameField;
+  private final JRadioButton myRbDefaultLabel;
+  private final JRadioButton myRbExpressionLabel;
+  private final JRadioButton myRbDefaultChildrenRenderer;
+  private final JRadioButton myRbExpressionChildrenRenderer;
+  private final JRadioButton myRbListChildrenRenderer;
+  private final DebuggerExpressionTextField myLabelEditor;
+  private final DebuggerExpressionTextField myChildrenEditor;
+  private final DebuggerExpressionTextField myChildrenExpandedEditor;
   private DebuggerExpressionTextField myListChildrenEditor;
-  private JComponent myChildrenListEditor;
-  private JLabel myExpandedLabel;
-  private JPanel myMainPanel;
+  private final JLabel myExpandedLabel;
   private JBTable myTable;
   @NonNls private static final String EMPTY_PANEL_ID = "EMPTY";
   @NonNls private static final String DATA_PANEL_ID = "DATA";
   private static final int NAME_TABLE_COLUMN = 0;
   private static final int EXPRESSION_TABLE_COLUMN = 1;
 
-  public CompoundRendererConfigurable(@Nullable Project project) {
-    myProject = project;
-  }
+  public CompoundRendererConfigurable() {
+    super(new CardLayout());
 
-  public void setRenderer(NodeRenderer renderer) {
-    if (renderer instanceof CompoundReferenceRenderer) {
-      myRenderer = (CompoundReferenceRenderer)renderer;
-      myOriginalRenderer = (CompoundReferenceRenderer)renderer.clone();
-    }
-    else {
-      myRenderer = myOriginalRenderer = null;
-    }
-    reset();
-  }
-
-  public CompoundReferenceRenderer getRenderer() {
-    return myRenderer;
-  }
-
-  public JComponent createComponent() {
     if (myProject == null) {
       myProject = JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables();
     }
-    final JPanel panel = new JPanel(new GridBagLayout());
 
     myRbDefaultLabel = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.default.renderer"));
     myRbExpressionLabel = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.expression"));
@@ -121,10 +93,11 @@
     myLabelEditor = new DebuggerExpressionTextField(myProject, null, "ClassLabelExpression");
     myChildrenEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
     myChildrenExpandedEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
-    myChildrenListEditor = createChildrenListEditor();
+    JComponent myChildrenListEditor = createChildrenListEditor();
 
     final ItemListener updateListener = new ItemListener() {
-      public void itemStateChanged(ItemEvent e) {
+      @Override
+      public void itemStateChanged(@NotNull ItemEvent e) {
         updateEnabledState();
       }
     };
@@ -133,7 +106,8 @@
     myRbExpressionChildrenRenderer.addItemListener(updateListener);
 
     myClassNameField = new ClassNameEditorWithBrowseButton(new ActionListener() {
-      public void actionPerformed(ActionEvent e) {
+      @Override
+      public void actionPerformed(@NotNull ActionEvent e) {
         PsiClass psiClass = DebuggerUtils.getInstance()
           .chooseClassDialog(DebuggerBundle.message("title.compound.renderer.configurable.choose.renderer.reference.type"), myProject);
         if (psiClass != null) {
@@ -143,20 +117,14 @@
         }
       }
     }, myProject);
-    final EditorTextField textField = myClassNameField.getEditorTextField();
-    final FocusAdapter updateContextListener = new FocusAdapter() {
-      public void focusLost(FocusEvent e) {
-        updateContext(myClassNameField.getText());
-      }
-    };
-    textField.addFocusListener(updateContextListener);
-    Disposer.register(myClassNameField, new Disposable() {
+    myClassNameField.getEditorTextField().addFocusListener(new FocusAdapter() {
       @Override
-      public void dispose() {
-        textField.removeFocusListener(updateContextListener);
+      public void focusLost(@NotNull FocusEvent e) {
+        updateContext(myClassNameField.getText());
       }
     });
 
+    JPanel panel = new JPanel(new GridBagLayout());
     panel.add(new JLabel(DebuggerBundle.message("label.compound.renderer.configurable.apply.to")),
               new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
                                      new Insets(0, 0, 0, 0), 0, 0));
@@ -197,15 +165,28 @@
     panel.add(myChildrenListEditor,
               new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                                      new Insets(4, 30, 0, 0), 0, 0));
+    add(new JPanel(), EMPTY_PANEL_ID);
+    add(panel, DATA_PANEL_ID);
+  }
 
-    myMainPanel = new JPanel(new CardLayout());
-    myMainPanel.add(new JPanel(), EMPTY_PANEL_ID);
-    myMainPanel.add(panel, DATA_PANEL_ID);
-    return myMainPanel;
+  public void setRenderer(NodeRenderer renderer) {
+    if (renderer instanceof CompoundReferenceRenderer) {
+      myRenderer = (CompoundReferenceRenderer)renderer;
+      myOriginalRenderer = (CompoundReferenceRenderer)renderer.clone();
+    }
+    else {
+      myRenderer = myOriginalRenderer = null;
+    }
+    reset();
+  }
+
+  public CompoundReferenceRenderer getRenderer() {
+    return myRenderer;
   }
 
   private void updateContext(final String qName) {
     ApplicationManager.getApplication().runReadAction(new Runnable() {
+      @Override
       public void run() {
         final Project project = myProject;
         final PsiClass psiClass = project != null ? DebuggerUtils.findClass(qName, project, GlobalSearchScope.allScope(project)) : null;
@@ -214,6 +195,7 @@
         myChildrenExpandedEditor.setContext(psiClass);
         myListChildrenEditor.setContext(psiClass);
 
+        assert project != null;
         PsiType type = DebuggerUtils.getType(qName, project);
         myLabelEditor.setThisType(type);
         myChildrenEditor.setThisType(type);
@@ -251,17 +233,21 @@
 
     final TableColumn exprColumn = myTable.getColumnModel().getColumn(EXPRESSION_TABLE_COLUMN);
     exprColumn.setCellEditor(new AbstractTableCellEditor() {
+      @Override
       public Object getCellEditorValue() {
         return myListChildrenEditor.getText();
       }
 
+      @Override
       public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
         myListChildrenEditor.setText((TextWithImports)value);
         return myListChildrenEditor;
       }
     });
     exprColumn.setCellRenderer(new DefaultTableCellRenderer() {
-      public Component getTableCellRendererComponent(JTable table,
+      @NotNull
+      @Override
+      public Component getTableCellRendererComponent(@NotNull JTable table,
                                                      Object value,
                                                      boolean isSelected,
                                                      boolean hasFocus,
@@ -309,7 +295,7 @@
     return !DebuggerUtilsEx.externalizableEqual(cloned, myOriginalRenderer);
   }
 
-  public void apply() throws ConfigurationException {
+  public void apply() {
     if (myRenderer == null) {
       return;
     }
@@ -342,7 +328,7 @@
 
   public void reset() {
     final TextWithImports emptyExpressionFragment = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
-    ((CardLayout)myMainPanel.getLayout()).show(myMainPanel, myRenderer == null ? EMPTY_PANEL_ID : DATA_PANEL_ID);
+    ((CardLayout)getLayout()).show(this, myRenderer == null ? EMPTY_PANEL_ID : DATA_PANEL_ID);
     if (myRenderer == null) {
       return;
     }
@@ -390,27 +376,11 @@
     updateContext(className);
   }
 
-  public void disposeUIResources() {
-    myRenderer = null;
-    myOriginalRenderer = null;
-    myLabelEditor.dispose();
-    myChildrenEditor.dispose();
-    myChildrenExpandedEditor.dispose();
-    myListChildrenEditor.dispose();
-    Disposer.dispose(myClassNameField);
-    myLabelEditor = null;
-    myChildrenEditor = null;
-    myChildrenExpandedEditor = null;
-    myListChildrenEditor = null;
-    myClassNameField = null;
-    myProject = null;
-  }
-
   private MyTableModel getTableModel() {
     return (MyTableModel)myTable.getModel();
   }
 
-  private final class MyTableModel extends AbstractTableModel {
+  private static final class MyTableModel extends AbstractTableModel {
     private final List<Row> myData = new ArrayList<Row>();
 
     public MyTableModel() {
@@ -423,18 +393,23 @@
       }
     }
 
+    @Override
     public int getColumnCount() {
       return 2;
     }
 
+    @Override
     public int getRowCount() {
       return myData.size();
     }
 
+    @Override
     public boolean isCellEditable(int rowIndex, int columnIndex) {
       return true;
     }
 
+    @NotNull
+    @Override
     public Class getColumnClass(int columnIndex) {
       switch (columnIndex) {
         case NAME_TABLE_COLUMN:
@@ -446,6 +421,7 @@
       }
     }
 
+    @Override
     public Object getValueAt(int rowIndex, int columnIndex) {
       if (rowIndex >= getRowCount()) {
         return null;
@@ -461,6 +437,7 @@
       }
     }
 
+    @Override
     public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
       if (rowIndex >= getRowCount()) {
         return;
@@ -476,6 +453,8 @@
       }
     }
 
+    @NotNull
+    @Override
     public String getColumnName(int columnIndex) {
       switch (columnIndex) {
         case NAME_TABLE_COLUMN:
@@ -513,7 +492,7 @@
       return pairs;
     }
 
-    private final class Row {
+    private static final class Row {
       public String name;
       public TextWithImports value;
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
index 490f99b..b0748cf 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,24 +16,23 @@
 package com.intellij.debugger.settings;
 
 import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.ConfigurableUi;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.ui.StateRestoringCheckBox;
 import com.intellij.ui.components.panels.VerticalBox;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
 
-public class DebuggerLaunchingConfigurable implements Configurable {
+class DebuggerLaunchingConfigurable implements ConfigurableUi<DebuggerSettings> {
   private JRadioButton myRbSocket;
   private JRadioButton myRbShmem;
   private StateRestoringCheckBox myCbForceClassicVM;
   private JCheckBox myCbDisableJIT;
 
   @Override
-  public void reset() {
-    final DebuggerSettings settings = DebuggerSettings.getInstance();
+  public void reset(@NotNull DebuggerSettings settings) {
     if (!SystemInfo.isWindows) {
       myRbSocket.setSelected(true);
       myRbShmem.setEnabled(false);
@@ -52,8 +51,8 @@
   }
 
   @Override
-  public void apply() {
-    getSettingsTo(DebuggerSettings.getInstance());
+  public void apply(@NotNull DebuggerSettings settings) {
+    getSettingsTo(settings);
   }
 
   private void getSettingsTo(DebuggerSettings settings) {
@@ -68,25 +67,15 @@
   }
 
   @Override
-  public boolean isModified() {
-    final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
-    final DebuggerSettings debuggerSettings = currentSettings.clone();
+  public boolean isModified(@NotNull DebuggerSettings currentSettings) {
+    DebuggerSettings debuggerSettings = currentSettings.clone();
     getSettingsTo(debuggerSettings);
     return !debuggerSettings.equals(currentSettings);
   }
 
+  @NotNull
   @Override
-  public String getDisplayName() {
-    return OptionsBundle.message("options.java.display.name");
-  }
-
-  @Override
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.launching";
-  }
-
-  @Override
-  public JComponent createComponent() {
+  public JComponent getComponent() {
     myCbForceClassicVM = new StateRestoringCheckBox(DebuggerBundle.message("label.debugger.launching.configurable.force.classic.vm"));
     myCbDisableJIT = new JCheckBox(DebuggerBundle.message("label.debugger.launching.configurable.disable.jit"));
     myRbSocket = new JRadioButton(DebuggerBundle.message("label.debugger.launching.configurable.socket"));
@@ -110,12 +99,6 @@
 
     JPanel result = new JPanel(new BorderLayout());
     result.add(panel, BorderLayout.NORTH);
-
     return result;
   }
-
-
-  @Override
-  public void disposeUIResources() {
-  }
 }
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
index cec458c..cf7e367 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,10 +17,7 @@
 
 import com.intellij.debugger.DebuggerBundle;
 import com.intellij.debugger.ui.JavaDebuggerSupport;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.OptionsBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.options.ConfigurableUi;
 import com.intellij.ui.classFilter.ClassFilterEditor;
 import org.jetbrains.annotations.NotNull;
 
@@ -29,18 +26,16 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
-public class DebuggerSteppingConfigurable implements SearchableConfigurable, Configurable.NoScroll {
+class DebuggerSteppingConfigurable implements ConfigurableUi<DebuggerSettings> {
   private JCheckBox myCbStepInfoFiltersEnabled;
   private JCheckBox myCbSkipSyntheticMethods;
   private JCheckBox myCbSkipConstructors;
   private JCheckBox myCbSkipClassLoaders;
   private ClassFilterEditor mySteppingFilterEditor;
   private JCheckBox myCbSkipSimpleGetters;
-  private Project myProject;
 
   @Override
-  public void reset() {
-    final DebuggerSettings settings = DebuggerSettings.getInstance();
+  public void reset(@NotNull DebuggerSettings settings) {
     myCbSkipSimpleGetters.setSelected(settings.SKIP_GETTERS);
     myCbSkipSyntheticMethods.setSelected(settings.SKIP_SYNTHETIC_METHODS);
     myCbSkipConstructors.setSelected(settings.SKIP_CONSTRUCTORS);
@@ -50,13 +45,11 @@
 
     mySteppingFilterEditor.setFilters(settings.getSteppingFilters());
     mySteppingFilterEditor.setEnabled(settings.TRACING_FILTERS_ENABLED);
-
-
   }
 
   @Override
-  public void apply() {
-    getSettingsTo(DebuggerSettings.getInstance());
+  public void apply(@NotNull DebuggerSettings settings) {
+    getSettingsTo(settings);
   }
 
   private void getSettingsTo(DebuggerSettings settings) {
@@ -71,39 +64,16 @@
   }
 
   @Override
-  public boolean isModified() {
-    final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
-    final DebuggerSettings debuggerSettings = currentSettings.clone();
+  public boolean isModified(@NotNull DebuggerSettings currentSettings) {
+    DebuggerSettings debuggerSettings = currentSettings.clone();
     getSettingsTo(debuggerSettings);
     return !debuggerSettings.equals(currentSettings);
   }
 
   @Override
-  public String getDisplayName() {
-    return OptionsBundle.message("options.java.display.name");
-  }
-
-  @Override
   @NotNull
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.stepping";
-  }
-
-  @Override
-  @NotNull
-  public String getId() {
-    return getHelpTopic();
-  }
-
-  @Override
-  public Runnable enableSearch(String option) {
-    return null;
-  }
-
-  @Override
-  public JComponent createComponent() {
+  public JComponent getComponent() {
     final JPanel panel = new JPanel(new GridBagLayout());
-    myProject = JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables();
     myCbSkipSyntheticMethods = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.synthetic.methods"));
     myCbSkipConstructors = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.constructors"));
     myCbSkipClassLoaders = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.classLoaders"));
@@ -115,7 +85,7 @@
     panel.add(myCbSkipSimpleGetters, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0),0, 0));
     panel.add(myCbStepInfoFiltersEnabled, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(8, 0, 0, 0),0, 0));
 
-    mySteppingFilterEditor = new ClassFilterEditor(myProject, null, "reference.viewBreakpoints.classFilters.newPattern");
+    mySteppingFilterEditor = new ClassFilterEditor(JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables(), null, "reference.viewBreakpoints.classFilters.newPattern");
     panel.add(mySteppingFilterEditor, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 0, 0),0, 0));
 
     myCbStepInfoFiltersEnabled.addActionListener(new ActionListener() {
@@ -126,11 +96,4 @@
     });
     return panel;
   }
-
-  @Override
-  public void disposeUIResources() {
-    mySteppingFilterEditor = null;
-    myProject = null;
-  }
-
-}
+}
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
index 7151cb9..e6f271b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
@@ -15,41 +15,78 @@
  */
 package com.intellij.debugger.settings;
 
+import com.intellij.debugger.DebuggerBundle;
 import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
 import com.intellij.xdebugger.settings.XDebuggerSettings;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static java.util.Collections.singletonList;
+
 /**
  * We cannot now transform DebuggerSettings to XDebuggerSettings: getState/loadState is not called for EP,
  * but we cannot use standard implementation to save our state, due to backward compatibility we must use own state spec.
- *
+ * <p/>
  * But we must implement createConfigurable as part of XDebuggerSettings otherwise java general settings will be before xdebugger general setting,
  * because JavaDebuggerSettingsPanelProvider has higher priority than XDebuggerSettingsPanelProviderImpl.
  */
-class JavaDebuggerSettings extends XDebuggerSettings<Element> {
+public class JavaDebuggerSettings extends XDebuggerSettings<Element> {
   protected JavaDebuggerSettings() {
     super("java");
   }
 
-  @Nullable
+  @NotNull
   @Override
-  public Configurable createConfigurable(@NotNull Category category) {
+  public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+    Getter<DebuggerSettings> settingsGetter = new Getter<DebuggerSettings>() {
+      @Override
+      public DebuggerSettings get() {
+        return DebuggerSettings.getInstance();
+      }
+    };
+
     switch (category) {
-      case ROOT:
-        return new DebuggerLaunchingConfigurable();
+      case GENERAL:
+        return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.launching", OptionsBundle.message("options.java.display.name"),
+                                                       DebuggerLaunchingConfigurable.class, settingsGetter));
       case DATA_VIEWS:
-        return new DebuggerDataViewsConfigurable(null);
+        return createDataViewsConfigurable();
       case STEPPING:
-        return new DebuggerSteppingConfigurable();
+        return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.stepping", OptionsBundle.message("options.java.display.name"),
+                                                       DebuggerSteppingConfigurable.class, settingsGetter));
+      case HOTSWAP:
+        return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.hotswap", OptionsBundle.message("options.java.display.name"),
+                                                       JavaHotSwapConfigurableUi.class, settingsGetter));
     }
-    return null;
+    return Collections.emptyList();
+  }
+
+  @SuppressWarnings("SpellCheckingInspection")
+  @NotNull
+  public static List<Configurable> createDataViewsConfigurable() {
+    return Arrays.<Configurable>asList(new DebuggerDataViewsConfigurable(null),
+                                       SimpleConfigurable.create("reference.idesettings.debugger.typerenderers", DebuggerBundle.message("user.renderers.configurable.display.name"),
+                                                                 UserRenderersConfigurable.class, new Getter<NodeRendererSettings>() {
+                                           @Override
+                                           public NodeRendererSettings get() {
+                                             return NodeRendererSettings.getInstance();
+                                           }
+                                         }));
   }
 
   @Override
-  public void generalApplied(@NotNull XDebuggerSettings.Category category) {
-    if (category == XDebuggerSettings.Category.DATA_VIEWS) {
+  public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+    if (category == DebuggerSettingsCategory.DATA_VIEWS) {
       NodeRendererSettings.getInstance().fireRenderersChanged();
     }
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java
similarity index 83%
rename from java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java
rename to java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java
index a70be30..82a33a8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,14 +16,14 @@
 package com.intellij.debugger.settings;
 
 import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ConfigurableUi;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.border.Border;
 import java.awt.*;
 
-public class DebuggerHotswapConfigurable implements SearchableConfigurable {
+class JavaHotSwapConfigurableUi implements ConfigurableUi<DebuggerSettings> {
   private JCheckBox myHotswapInBackground;
   private JCheckBox myCbCompileBeforeHotswap;
   private JCheckBox myCbHangWarningEnabled;
@@ -31,8 +31,8 @@
   private JRadioButton myRbNever;
   private JRadioButton myRbAsk;
 
-  public void reset() {
-    final DebuggerSettings settings = DebuggerSettings.getInstance();
+  @Override
+  public void reset(@NotNull DebuggerSettings settings) {
     myHotswapInBackground.setSelected(settings.HOTSWAP_IN_BACKGROUND);
     myCbCompileBeforeHotswap.setSelected(settings.COMPILE_BEFORE_HOTSWAP);
     myCbHangWarningEnabled.setSelected(settings.HOTSWAP_HANG_WARNING_ENABLED);
@@ -48,8 +48,9 @@
     }
   }
 
-  public void apply() {
-    getSettingsTo(DebuggerSettings.getInstance());
+  @Override
+  public void apply(@NotNull DebuggerSettings settings) {
+    getSettingsTo(settings);
   }
 
   private void getSettingsTo(DebuggerSettings settings) {
@@ -68,31 +69,16 @@
     }
   }
 
-  public boolean isModified() {
-    final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
+  @Override
+  public boolean isModified(@NotNull DebuggerSettings currentSettings) {
     final DebuggerSettings debuggerSettings = currentSettings.clone();
     getSettingsTo(debuggerSettings);
     return !debuggerSettings.equals(currentSettings);
   }
 
-  public String getDisplayName() {
-    return DebuggerBundle.message("debugger.hotswap.configurable.display.name");
-  }
-
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.hotswap";
-  }
-
   @NotNull
-  public String getId() {
-    return getHelpTopic();
-  }
-
-  public Runnable enableSearch(String option) {
-    return null;
-  }
-
-  public JComponent createComponent() {
+  @Override
+  public JComponent getComponent() {
     final JPanel panel = new JPanel(new GridBagLayout());
 
     myCbCompileBeforeHotswap = new JCheckBox(DebuggerBundle.message("label.debugger.hotswap.configurable.compile.before.hotswap"));
@@ -130,9 +116,4 @@
 
     return panel;
   }
-
-
-  public void disposeUIResources() {
-  }
-
-}
+}
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
index 3ab2028..3a8505c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,17 +20,12 @@
 import com.intellij.debugger.ui.tree.render.NodeRenderer;
 import com.intellij.ide.util.ElementsChooser;
 import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.options.ConfigurableUi;
 import com.intellij.ui.DocumentAdapter;
 import com.intellij.util.IconUtil;
 import com.intellij.util.PlatformIcons;
 import com.intellij.util.containers.InternalIterator;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
@@ -40,56 +35,25 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * @author Eugene Zhuravlev
- *         Date: Feb 19, 2005
- */
-public class UserRenderersConfigurable implements SearchableConfigurable, Configurable.NoScroll {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.settings.UserRenderersConfigurable");
+public final class UserRenderersConfigurable extends JPanel implements ConfigurableUi<NodeRendererSettings> {
   private static final Icon ADD_ICON = IconUtil.getAddIcon();
   private static final Icon REMOVE_ICON = IconUtil.getRemoveIcon();
   private static final Icon COPY_ICON = PlatformIcons.COPY_ICON;
   private static final Icon UP_ICON = IconUtil.getMoveUpIcon();
   private static final Icon DOWN_ICON = IconUtil.getMoveDownIcon();
 
-  private JPanel myNameFieldPanel;
-  private JTextField myNameField;
+  private final JPanel myNameFieldPanel;
+  private final JTextField myNameField;
   private ElementsChooser<NodeRenderer> myRendererChooser;
   private NodeRenderer myCurrentRenderer = null;
-  private final CompoundRendererConfigurable myRendererDataConfigurable;
+  private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable();
 
-  public UserRenderersConfigurable(@Nullable Project project) {
-    myRendererDataConfigurable = new CompoundRendererConfigurable(project);
-  }
+  public UserRenderersConfigurable() {
+    super(new BorderLayout(4, 0));
 
-  public String getDisplayName() {
-    return DebuggerBundle.message("user.renderers.configurable.display.name");
-  }
-
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.typerenderers"; 
-  }
-
-  @NotNull
-  public String getId() {
-    return getHelpTopic();
-  }
-
-  public Runnable enableSearch(String option) {
-    return null;
-  }
-
-  public JComponent createComponent() {
-    final JPanel panel = new JPanel(new BorderLayout(4, 0));
-
-    final JComponent renderersList = createRenderersList();
-    final JComponent toolbar = createToolbar();
-    final JComponent rendererDataPanel = myRendererDataConfigurable.createComponent();
-
-    final JPanel left = new JPanel(new BorderLayout());
-
-    left.add(toolbar, BorderLayout.NORTH);
-    left.add(renderersList, BorderLayout.CENTER);
+    JPanel left = new JPanel(new BorderLayout());
+    left.add(createToolbar(), BorderLayout.NORTH);
+    left.add(createRenderersList(), BorderLayout.CENTER);
 
     myNameField = new JTextField();
     myNameFieldPanel = new JPanel(new BorderLayout());
@@ -98,11 +62,11 @@
     myNameFieldPanel.setVisible(false);
 
     final JPanel center = new JPanel(new BorderLayout(0, 4));
-
     center.add(myNameFieldPanel, BorderLayout.NORTH);
-    center.add(rendererDataPanel, BorderLayout.CENTER);
+    center.add(myRendererDataConfigurable, BorderLayout.CENTER);
 
     myNameField.getDocument().addDocumentListener(new DocumentAdapter() {
+      @Override
       protected void textChanged(DocumentEvent e) {
         if (myCurrentRenderer != null) {
           myCurrentRenderer.setName(myNameField.getText());
@@ -111,10 +75,14 @@
       }
     });
 
-    panel.add(left, BorderLayout.WEST);
-    panel.add(center, BorderLayout.CENTER);
+    add(left, BorderLayout.WEST);
+    add(center, BorderLayout.CENTER);
+  }
 
-    return panel;
+  @Override
+  @NotNull
+  public JComponent getComponent() {
+    return this;
   }
 
   private JComponent createRenderersList() {
@@ -122,12 +90,14 @@
     myRendererChooser.getEmptyText().setText(DebuggerBundle.message("text.user.renderers.configurable.no.renderers"));
 
     myRendererChooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener<NodeRenderer>() {
+      @Override
       public void elementMarkChanged(final NodeRenderer element, final boolean isMarked) {
         element.setEnabled(isMarked);
       }
     });
     myRendererChooser.addListSelectionListener(new ListSelectionListener() {
-      public void valueChanged(ListSelectionEvent e) {
+      @Override
+      public void valueChanged(@NotNull ListSelectionEvent e) {
         if (!e.getValueIsAdjusting()) {
           updateCurrentRenderer(myRendererChooser.getSelectedElements());
         }
@@ -138,7 +108,7 @@
 
   private void updateCurrentRenderer(List<NodeRenderer> selectedElements) {
     if (selectedElements.size() != 1) {
-      // multiselection
+      // multi selection
       setCurrentRenderer(null);
     }
     else {
@@ -150,13 +120,8 @@
     if (myCurrentRenderer == renderer) {
       return;
     }
-    try {
-      if (myRendererDataConfigurable.isModified()) {
-        myRendererDataConfigurable.apply();
-      }
-    }
-    catch (ConfigurationException e) {
-      LOG.error(e);
+    if (myRendererDataConfigurable.isModified()) {
+      myRendererDataConfigurable.apply();
     }
     myCurrentRenderer = renderer;
     if (renderer != null) {
@@ -181,11 +146,12 @@
     return toolbar.getComponent();
   }
 
-  public void apply() throws ConfigurationException {
+  @Override
+  public void apply(@NotNull NodeRendererSettings settings) {
     myRendererDataConfigurable.apply();
-    flushTo(NodeRendererSettings.getInstance().getCustomRenderers());
+    flushTo(settings.getCustomRenderers());
 
-    NodeRendererSettings.getInstance().fireRenderersChanged();
+    settings.fireRenderersChanged();
   }
 
   private void flushTo(final RendererConfiguration rendererConfiguration) {
@@ -197,11 +163,11 @@
     rendererConfiguration.setRenderers(renderers);
   }
 
-  public boolean isModified() {
+  @Override
+  public boolean isModified(@NotNull NodeRendererSettings settings) {
     if (myRendererDataConfigurable.isModified()) {
       return true;
     }
-    final NodeRendererSettings settings = NodeRendererSettings.getInstance();
     final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
     if (myRendererChooser.getElementCount() != rendererConfiguration.getRendererCount()) {
       return true;
@@ -211,11 +177,13 @@
     return !uiConfiguration.equals(rendererConfiguration);
   }
 
-  public void reset() {
+  @Override
+  public void reset(@NotNull NodeRendererSettings settings) {
     myRendererChooser.removeAllElements();
-    final RendererConfiguration rendererConfiguration = NodeRendererSettings.getInstance().getCustomRenderers();
+    final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
     final ArrayList<NodeRenderer> elementsToSelect = new ArrayList<NodeRenderer>(1);
     rendererConfiguration.iterateRenderers(new InternalIterator<NodeRenderer>() {
+      @Override
       public boolean visit(final NodeRenderer renderer) {
         final NodeRenderer clonedRenderer = (NodeRenderer)renderer.clone();
         myRendererChooser.addElement(clonedRenderer, clonedRenderer.isEnabled());
@@ -230,21 +198,18 @@
     myRendererDataConfigurable.reset();
   }
 
-  public void disposeUIResources() {
-    myRendererChooser.removeAllElements();
-    myRendererDataConfigurable.disposeUIResources();
-  }
-
   private class AddAction extends AnAction {
     public AddAction() {
       super(DebuggerBundle.message("button.add"), DebuggerBundle.message("user.renderers.configurable.button.description.add"), ADD_ICON);
     }
 
+    @Override
     public void actionPerformed(AnActionEvent e) {
       final NodeRenderer renderer = (NodeRenderer)NodeRendererSettings.getInstance().createRenderer(CompoundNodeRenderer.UNIQUE_ID);
       renderer.setEnabled(true);
       myRendererChooser.addElement(renderer, renderer.isEnabled());
       SwingUtilities.invokeLater(new Runnable() {
+        @Override
         public void run() {
           myNameField.requestFocus();
         }
@@ -257,16 +222,18 @@
       super(DebuggerBundle.message("button.remove"), DebuggerBundle.message("user.renderers.configurable.button.description.remove"), REMOVE_ICON);
     }
 
+    @Override
     public void actionPerformed(AnActionEvent e) {
       for (NodeRenderer selectedElement : myRendererChooser.getSelectedElements()) {
         myRendererChooser.removeElement(selectedElement);
       }
     }
 
+    @Override
     public void update(AnActionEvent e) {
       super.update(e);
-      final Presentation presentation = e.getPresentation();
-      presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+
+      e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
     }
   }
 
@@ -275,18 +242,18 @@
       super(DebuggerBundle.message("button.copy"), DebuggerBundle.message("user.renderers.configurable.button.description.copy"), COPY_ICON);
     }
 
+    @Override
     public void actionPerformed(AnActionEvent e) {
       final NodeRenderer selectedElement = myRendererChooser.getSelectedElement();
       if (selectedElement != null) {
-        final NodeRenderer cloned = (NodeRenderer)selectedElement.clone();
-        myRendererChooser.addElement(cloned, true);
+        myRendererChooser.addElement((NodeRenderer)selectedElement.clone(), true);
       }
     }
 
+    @Override
     public void update(AnActionEvent e) {
       super.update(e);
-      final Presentation presentation = e.getPresentation();
-      presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+      e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
     }
   }
 
@@ -300,6 +267,7 @@
       myMoveUp = up;
     }
 
+    @Override
     public void actionPerformed(AnActionEvent e) {
       final int selectedRow = myRendererChooser.getSelectedElementRow();
       if (selectedRow < 0) {
@@ -315,10 +283,10 @@
       myRendererChooser.moveElement(myRendererChooser.getElementAt(selectedRow), newRow);
     }
 
+    @Override
     public void update(AnActionEvent e) {
       super.update(e);
-      final Presentation presentation = e.getPresentation();
-      presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+      e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
     }
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
index 3809431..1333635 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
@@ -214,7 +214,7 @@
   public void toFront(DebuggerSession session) {
     DebuggerSessionTab sessionTab = getSessionTab(session);
     if (sessionTab != null) {
-      sessionTab.toFront();
+      sessionTab.toFront(true);
     }
   }
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
index 27f63e0..20d95f8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
@@ -18,9 +18,6 @@
 import com.intellij.debugger.DebuggerManagerEx;
 import com.intellij.debugger.actions.*;
 import com.intellij.debugger.impl.DebuggerContextImpl;
-import com.intellij.debugger.settings.DebuggerHotswapConfigurable;
-import com.intellij.debugger.settings.NodeRendererSettings;
-import com.intellij.debugger.settings.UserRenderersConfigurable;
 import com.intellij.debugger.ui.breakpoints.Breakpoint;
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.Disposable;
@@ -28,7 +25,6 @@
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
-import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ProjectManager;
 import com.intellij.xdebugger.AbstractDebuggerSession;
@@ -42,13 +38,11 @@
 import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
 import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
 import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
-import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
 import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
-import java.util.ArrayList;
 import java.util.Collection;
 
 /**
@@ -68,7 +62,6 @@
   private final ShowExecutionPointActionHandler myShowExecutionPointActionHandler = new ShowExecutionPointActionHandler();
   //private final EvaluateActionHandler myEvaluateActionHandler = new EvaluateActionHandler();
   private final QuickEvaluateActionHandler myQuickEvaluateHandler = new QuickEvaluateActionHandler();
-  private final JavaDebuggerSettingsPanelProvider myDebuggerSettingsPanelProvider = new JavaDebuggerSettingsPanelProvider();
   private final DebuggerActionHandler mySmartStepIntoHandler = new JvmSmartStepIntoActionHandler();
   private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler();
   private final JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler();
@@ -118,13 +111,13 @@
   @Override
   @NotNull
   public DebuggerActionHandler getRunToCursorHandler() {
-    return myRunToCursorActionHandler;
+    return DISABLED;
   }
 
   @Override
   @NotNull
   public DebuggerActionHandler getForceRunToCursorHandler() {
-    return myForceRunToCursorActionHandler;
+    return DISABLED;
   }
 
   @Override
@@ -216,12 +209,6 @@
     return X_EDIT;
   }
 
-  @Override
-  @NotNull
-  public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
-    return myDebuggerSettingsPanelProvider;
-  }
-
   private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider<Breakpoint> {
     //private final List<MyBreakpointManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
 
@@ -335,27 +322,6 @@
     //}
   }
 
-  final static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider {
-    @Override
-    public int getPriority() {
-      return 1;
-    }
-
-    @NotNull
-    @Override
-    public Collection<? extends Configurable> getConfigurables() {
-      final ArrayList<Configurable> configurables = new ArrayList<Configurable>();
-      configurables.add(new UserRenderersConfigurable(null));
-      configurables.add(new DebuggerHotswapConfigurable());
-      return configurables;
-    }
-
-    @Override
-    public void apply() {
-      NodeRendererSettings.getInstance().fireRenderersChanged();
-    }
-  }
-
   public static Project getContextProjectForEditorFieldsInDebuggerConfigurables() {
     //todo[nik] improve
     Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
index f065745..98c772d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
@@ -63,6 +63,6 @@
   @Nullable
   @Override
   public Icon getIcon() {
-    return AllIcons.Nodes.Package;
+    return AllIcons.Actions.GroupByPackage;
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
index ebbef2c..414960b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
@@ -51,7 +51,7 @@
 
   public void createRequest(DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!shouldCreateRequest(debugProcess)) {
       return;
     }
     super.processClassPrepare(debugProcess, null);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
index 6879407..328dc5f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
@@ -33,6 +33,7 @@
 import com.intellij.debugger.settings.DebuggerSettings;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
@@ -46,6 +47,7 @@
 import com.intellij.xdebugger.breakpoints.SuspendPolicy;
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.XDebuggerHistoryManager;
 import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
 import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
@@ -95,7 +97,20 @@
    * Request for creating all needed JPDA requests in the specified VM
    * @param debuggerProcess the requesting process
    */
-  public abstract void createRequest(DebugProcessImpl debuggerProcess);
+  public abstract void createRequest(DebugProcessImpl debugProcess);
+
+  protected boolean shouldCreateRequest(final DebugProcessImpl debugProcess) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+      @Override
+      public Boolean compute() {
+        JavaDebugProcess process = debugProcess.getXdebugProcess();
+        return process != null
+               && debugProcess.isAttached()
+               && ((XDebugSessionImpl)process.getSession()).isBreakpointActive(myXBreakpoint)
+               && debugProcess.getRequestsManager().findRequests(Breakpoint.this).isEmpty();
+      }
+    });
+  }
 
   /**
    * Request for creating all needed JPDA requests in the specified VM
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
index d6cbf14..cc37374 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
@@ -17,10 +17,7 @@
 
 import com.intellij.CommonBundle;
 import com.intellij.debugger.*;
-import com.intellij.debugger.engine.DebugProcess;
-import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
-import com.intellij.debugger.engine.JVMNameUtil;
+import com.intellij.debugger.engine.*;
 import com.intellij.debugger.engine.events.DebuggerCommandImpl;
 import com.intellij.debugger.engine.requests.RequestManagerImpl;
 import com.intellij.debugger.impl.DebuggerContextImpl;
@@ -300,10 +297,7 @@
   public void createRequest(@NotNull DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     // check is this breakpoint is enabled, vm reference is valid and there're no requests created yet
-    if (!isEnabled() ||
-        !debugProcess.isAttached() ||
-        isMuted(debugProcess) ||
-        !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!shouldCreateRequest(debugProcess)) {
       return;
     }
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
index 88ddf48..e4f404e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
@@ -118,7 +118,7 @@
 
   public void createRequest(final DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!shouldCreateRequest(debugProcess)) {
       return;
     }
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
index a537db1..4e1d3e2 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
@@ -63,7 +63,7 @@
     Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
     if (javaBreakpoint != null) {
       PsiClass aClass = javaBreakpoint.getPsiClass();
-      if (aClass != null && aClass.getContainingFile() != null) {
+      if (aClass != null && aClass.getContainingFile() != null && aClass.getTextOffset() >= 0) {
         return XDebuggerUtil.getInstance().createPositionByOffset(aClass.getContainingFile().getVirtualFile(), aClass.getTextOffset());
       }
     }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
index 5b5233a..4d43a2b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
@@ -123,4 +123,9 @@
 
     return new RunToCursorBreakpoint(project, pos, restoreBreakpoints);
   }
+
+  @Override
+  protected boolean shouldCreateRequest(DebugProcessImpl debugProcess) {
+    return debugProcess.isAttached() && debugProcess.getRequestsManager().findRequests(this).isEmpty();
+  }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
index c106f65..e8b947c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
@@ -129,7 +129,7 @@
 
   public void createRequest(DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!shouldCreateRequest(debugProcess)) {
       return;
     }
     try {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
index abda696..f4da39f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
@@ -484,7 +484,7 @@
   }
 
   public boolean canSetValue() {
-    return !myIsSynthetic && isLvalue();
+    return myValueReady && !myIsSynthetic && isLvalue();
   }
 
   public String getValueLabel() {
@@ -534,4 +534,10 @@
     }
   }
 
+  public boolean canMark() {
+    if (!myValueReady) {
+      return false;
+    }
+    return getValue() instanceof ObjectReference;
+  }
 }
diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
index 04af179..27958a9 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
@@ -85,7 +85,7 @@
   public void resetEditorFrom(final ApplicationConfiguration configuration) {
     myCommonProgramParameters.reset(configuration);
     myModuleSelector.reset(configuration);
-    getMainClassField().setText(configuration.MAIN_CLASS_NAME.replaceAll("\\$", "\\."));
+    getMainClassField().setText(configuration.MAIN_CLASS_NAME != null ? configuration.MAIN_CLASS_NAME.replaceAll("\\$", "\\.") : "");
     myAlternativeJREPanel.init(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED);
 
     updateShowSwingInspector(configuration);
diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
index 2370ad3..578d5fb 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
@@ -21,6 +21,7 @@
 import com.intellij.execution.configurations.*;
 import com.intellij.execution.filters.TextConsoleBuilderFactory;
 import com.intellij.execution.junit.RefactoringListeners;
+import com.intellij.execution.process.KillableColoredProcessHandler;
 import com.intellij.execution.process.OSProcessHandler;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.execution.util.JavaParametersUtil;
@@ -33,6 +34,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.DefaultJDOMExternalizer;
 import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
@@ -285,12 +287,17 @@
     @NotNull
     @Override
     protected OSProcessHandler startProcess() throws ExecutionException {
-      final OSProcessHandler handler = super.startProcess();
+      OSProcessHandler handler = SystemInfo.isWindows ? super.startProcess() : KillableColoredProcessHandler.create(createCommandLine());
       RunnerSettings runnerSettings = getRunnerSettings();
       JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
       return handler;
     }
 
+    @Override
+    protected boolean ansiColoringEnabled() {
+      return true;
+    }
+
     protected ApplicationConfiguration getConfiguration() {
       return myConfiguration;
     }
diff --git a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
index d472761..3190e19 100644
--- a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
+++ b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
@@ -224,9 +224,10 @@
             threadStates = ThreadDumpParser.parse(stdout);
             if (threadStates == null || threadStates.isEmpty()) {
               try {
+                //noinspection BusyWait
                 Thread.sleep(50);
               }
-              catch (InterruptedException e1) {
+              catch (InterruptedException ignored) {
                 //
               }
               threadStates = null;
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
index fbe8636..7627d93 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
@@ -46,6 +46,7 @@
 
   protected void init(@NotNull ModulesProvider modulesProvider) {
     myWizardContext.setNewWizard(true);
+    myWizardContext.setModulesProvider(modulesProvider);
     ProjectTypeStep projectTypeStep = new ProjectTypeStep(myWizardContext, this, modulesProvider);
     Disposer.register(getDisposable(), projectTypeStep);
     mySequence.addCommonStep(projectTypeStep);
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
index 2ed47fd..8fca04c 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
@@ -126,6 +126,7 @@
   private final Map<String, ModuleWizardStep> myCustomSteps = new HashMap<String, ModuleWizardStep>();
   private final MultiMap<TemplatesGroup,ProjectTemplate> myTemplatesMap;
   private String myCurrentCard;
+  private TemplatesGroup myLastSelectedGroup;
 
   public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) {
     myContext = context;
@@ -369,7 +370,8 @@
   // new TemplatesGroup selected
   public void projectTypeChanged() {
     TemplatesGroup group = getSelectedGroup();
-    if (group == null) return;
+    if (group == null || group == myLastSelectedGroup) return;
+    myLastSelectedGroup = group;
     PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_GROUP, group.getId() );
     ModuleBuilder groupModuleBuilder = group.getModuleBuilder();
 
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
index 0366751..6c281b0 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
@@ -107,6 +107,8 @@
     final FrameworkSupportNode node = mySettingsMap.get(providerId);
     if (node != null && enable != node.isChecked()) {
       node.setChecked(enable);
+      // ensure configurable to be created and registered to disposer
+      node.getConfigurable();
     }
   }
 
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
index d76fa74..da18f37 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -19,12 +19,12 @@
 import com.intellij.ide.highlighter.ProjectFileType;
 import com.intellij.ide.util.BrowseFilesListener;
 import com.intellij.openapi.application.ApplicationInfo;
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.DocumentAdapter;
 import com.intellij.ui.FieldPanel;
@@ -138,52 +138,40 @@
     return component;
   }
 
-  private String getProjectFilePath(boolean isDefault) {
-    if (isDefault) {
-      return getPath() + "/" + getNameValue() + ProjectFileType.DOT_DEFAULT_EXTENSION;
-    }
-    else {
-      return getPath() + "/" + Project.DIRECTORY_STORE_FOLDER;
-    }
-  }
-
-  public boolean validateNameAndPath(WizardContext context, boolean defaultFormat) throws
-                                                                                    ConfigurationException {
-    final String name = getNameValue();
-    if (name.length() == 0) {
-      final ApplicationInfo info = ApplicationManager.getApplication().getComponent(ApplicationInfo.class);
-      throw new ConfigurationException(
-        IdeBundle.message("prompt.new.project.file.name", info.getVersionName(), context.getPresentationName()));
+  public boolean validateNameAndPath(WizardContext context, boolean defaultFormat) throws ConfigurationException {
+    String name = getNameValue();
+    if (StringUtil.isEmptyOrSpaces(name)) {
+      ApplicationInfo info = ApplicationInfo.getInstance();
+      throw new ConfigurationException(IdeBundle.message("prompt.new.project.file.name", info.getVersionName(), context.getPresentationName()));
     }
 
-    final String projectFileDirectory = getPath();
-    if (projectFileDirectory.length() == 0) {
+    String projectDirectory = getPath();
+    if (StringUtil.isEmptyOrSpaces(projectDirectory)) {
       throw new ConfigurationException(IdeBundle.message("prompt.enter.project.file.location", context.getPresentationName()));
     }
-    if (myShouldBeAbsolute && !new File(projectFileDirectory).isAbsolute()) {
+    if (myShouldBeAbsolute && !new File(projectDirectory).isAbsolute()) {
       throw new ConfigurationException(StringUtil.capitalize(IdeBundle.message("file.location.should.be.absolute", context.getPresentationName())));
     }
-    final boolean shouldPromptCreation = isPathChangedByUser();
-    if (!ProjectWizardUtil
-      .createDirectoryIfNotExists(IdeBundle.message("directory.project.file.directory", context.getPresentationName()),
-                                  projectFileDirectory, shouldPromptCreation)) {
+
+    boolean shouldPromptCreation = isPathChangedByUser();
+    String message = IdeBundle.message("directory.project.file.directory", context.getPresentationName());
+    if (!ProjectWizardUtil.createDirectoryIfNotExists(message, projectDirectory, shouldPromptCreation)) {
       return false;
     }
 
-    final File file = new File(projectFileDirectory);
+    File file = new File(projectDirectory);
     if (file.exists() && !file.canWrite()) {
-      throw new ConfigurationException(String.format("Directory '%s' is not writable!\nPlease choose another project location.", projectFileDirectory));
+      throw new ConfigurationException(String.format("Directory '%s' is not writable!\nPlease choose another project location.", projectDirectory));
     }
 
     boolean shouldContinue = true;
-    final File projectFile = new File(getProjectFilePath(defaultFormat));
+    String fileName = defaultFormat ? name + ProjectFileType.DOT_DEFAULT_EXTENSION : Project.DIRECTORY_STORE_FOLDER;
+    File projectFile = new File(file, fileName);
     if (projectFile.exists()) {
-      int answer = Messages.showYesNoDialog(
-        IdeBundle.message("prompt.overwrite.project.file", projectFile.getAbsolutePath(), context.getPresentationName()),
-        IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
+      message = IdeBundle.message("prompt.overwrite.project.file", projectFile.getAbsolutePath(), context.getPresentationName());
+      int answer = Messages.showYesNoDialog(message, IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
       shouldContinue = (answer == Messages.YES);
     }
-
     return shouldContinue;
   }
 
@@ -204,14 +192,15 @@
   }
 
   public String getPath() {
-    return myTfPath.getText().trim().replace(File.separatorChar, '/');
+    String text = myTfPath.getText().trim();
+    return FileUtil.expandUserHome(FileUtil.toSystemIndependentName(text));
   }
 
   public void setPath(String path) {
     final boolean isPathChangedByUser = myIsPathChangedByUser;
     setPathNameSyncEnabled(false);
     try {
-      myTfPath.setText(path);
+      myTfPath.setText(FileUtil.getLocationRelativeToUserHome(FileUtil.toSystemDependentName(path)));
     }
     finally {
       myIsPathChangedByUser = isPathChangedByUser;
diff --git a/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java b/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
index 68e1741..0c41048 100644
--- a/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -32,6 +32,7 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.TabbedPaneWrapper;
 import com.intellij.ui.navigation.History;
@@ -151,11 +152,13 @@
     myHomeComponent.getTextField().setEditable(false);
 
     myHomeFieldLabel = new JLabel(getHomeFieldLabelValue());
-    myMainPanel.add(myHomeFieldLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 0, 2, 2), 0, 0));
-    myMainPanel.add(myHomeComponent, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 0), 0, 0));
+    final int leftInset = Registry.is("ide.new.project.settings") ? 10 : 0;
+    final int rightInset = Registry.is("ide.new.project.settings") ? 10 : 0;
+    myMainPanel.add(myHomeFieldLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, leftInset, 2, 2), 0, 0));
+    myMainPanel.add(myHomeComponent, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, rightInset), 0, 0));
 
     myAdditionalDataPanel = new JPanel(new BorderLayout());
-    myMainPanel.add(myAdditionalDataPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0));
+    myMainPanel.add(myAdditionalDataPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, leftInset, 0, rightInset), 0, 0));
 
     myMainPanel.add(myTabbedPane.getComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0));
   }
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
index cbfd826..73f9f7f 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -26,6 +26,7 @@
 import com.intellij.openapi.project.ProjectBundle;
 import com.intellij.openapi.roots.ContentEntry;
 import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -140,6 +141,7 @@
 
   @Override
   protected JPanel createBottomControl(Module module) {
+    if (Registry.is("ide.new.project.settings")) return null;
     final JPanel innerPanel = new JPanel(new GridBagLayout());
     innerPanel.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 6));
     return innerPanel;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
index 292c1f6..576d514 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.roots.ui.configuration.ProjectConfigurable">
   <grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
-    <margin top="14" left="4" bottom="4" right="4"/>
+    <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="20" y="20" width="907" height="282"/>
+      <xy x="20" y="20" width="907" height="288"/>
     </constraints>
     <properties/>
-    <border type="none"/>
+    <border type="none">
+      <size top="14" left="10" bottom="14" right="10"/>
+    </border>
     <children>
       <vspacer id="2fb9d">
         <constraints>
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
index 9c46d56..2bc8499 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -39,6 +39,7 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.pom.java.LanguageLevel;
@@ -49,6 +50,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.border.EmptyBorder;
 import javax.swing.event.DocumentEvent;
 import java.awt.*;
 import java.io.IOException;
@@ -108,7 +110,7 @@
 
   @Override
   public JComponent createOptionsPanel() {
-    myDetailsComponent = new DetailsComponent();
+    myDetailsComponent = new DetailsComponent(!Registry.is("ide.new.project.settings"), !Registry.is("ide.new.project.settings"));
     myDetailsComponent.setContent(myPanel);
     myDetailsComponent.setText(getBannerSlogan());
 
@@ -152,7 +154,7 @@
     myPanel.add(myWholePanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST,
                                                      GridBagConstraints.NONE, new Insets(4, 0, 0, 0), 0, 0));
 
-
+    myPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
     myProjectCompilerOutput.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
       @Override
       protected void textChanged(DocumentEvent e) {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
index d78731b..f241537 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -161,6 +161,9 @@
   @Override
   @Nullable
   protected ArrayList<AnAction> createActions(final boolean fromPopup) {
+    if (myProjectJdksModel == null) {
+      return null;
+    }
     final ArrayList<AnAction> actions = new ArrayList<AnAction>();
     DefaultActionGroup group = new DefaultActionGroup(ProjectBundle.message("add.new.jdk.text"), true);
     group.getTemplatePresentation().setIcon(IconUtil.getAddIcon());
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
index bf083f9..a5867d6 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
@@ -44,6 +44,7 @@
 import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
 import com.intellij.packaging.artifacts.Artifact;
 import com.intellij.ui.JBSplitter;
+import com.intellij.ui.OnePixelSplitter;
 import com.intellij.ui.components.panels.Wrapper;
 import com.intellij.ui.navigation.BackAction;
 import com.intellij.ui.navigation.ForwardAction;
@@ -174,12 +175,9 @@
   public JComponent createComponent() {
     myComponent = new MyPanel();
 
-    mySplitter = new JBSplitter(false, .15f);
+    mySplitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false, .15f) : new JBSplitter(false, .15f);
     mySplitter.setSplitterProportionKey("ProjectStructure.TopLevelElements");
     mySplitter.setHonorComponentsMinimumSize(true);
-    if (Registry.is("ide.new.project.settings")) {
-      mySplitter.setOnePixelMode();
-    }
 
     initSidePanel();
 
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
index 290f35e..355888b 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
@@ -20,7 +20,10 @@
 import com.intellij.openapi.ui.popup.ListItemDescriptor;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.*;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.SeparatorWithText;
 import com.intellij.ui.components.JBList;
 import com.intellij.ui.components.panels.NonOpaquePanel;
 import com.intellij.ui.navigation.History;
@@ -172,16 +175,14 @@
       protected JComponent createItemComponent() {
         myExtraPanel = new NonOpaquePanel(new BorderLayout());
         myCountLabel = new CountLabel();
-
+        final JComponent component = super.createItemComponent();
 
         if (Registry.is("ide.new.project.settings")) {
-          myTextLabel = new EngravedLabel();
-          myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
           myTextLabel.setForeground(Gray._240);
           myTextLabel.setOpaque(true);
-          return layoutComponent(myTextLabel);
         }
-        return super.createItemComponent();
+
+        return component;
       }
 
       @Override
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
index 69b4908..618f085 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -34,12 +34,12 @@
 import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.ModuleOutputSourceItem;
 import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.SourceItemsTree;
 import com.intellij.openapi.ui.FixedSizeButton;
-import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.packaging.artifacts.Artifact;
@@ -83,6 +83,7 @@
   private JPanel myErrorPanelPlace;
   private ThreeStateCheckBox myShowContentCheckBox;
   private FixedSizeButton myShowSpecificContentOptionsButton;
+  private JPanel myTopPanel;
   private final ActionGroup myShowSpecificContentOptionsGroup;
   private final Project myProject;
   private final ComplexElementSubstitutionParameters mySubstitutionParameters = new ComplexElementSubstitutionParameters();
@@ -106,6 +107,9 @@
     myPropertiesEditors = new ArtifactPropertiesEditors(myContext, myOriginalArtifact, myOriginalArtifact);
     Disposer.register(this, mySourceItemsTree);
     Disposer.register(this, myLayoutTreeComponent);
+    if (Registry.is("ide.new.project.settings")) {
+      myTopPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
+    }
     myBuildOnMakeCheckBox.setSelected(artifact.isBuildOnMake());
     final String outputPath = artifact.getOutputPath();
     myOutputDirectoryField.addBrowseFolderListener(CompilerBundle.message("dialog.title.output.directory.for.artifact"),
@@ -202,7 +206,7 @@
 
     myErrorPanelPlace.add(myValidationManager.getMainErrorPanel(), BorderLayout.CENTER);
 
-    Splitter splitter = new Splitter(false);
+    final JBSplitter splitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false) : new JBSplitter(false);
     final JPanel leftPanel = new JPanel(new BorderLayout());
     JPanel treePanel = myLayoutTreeComponent.getTreePanel();
     if (UIUtil.isUnderDarcula()) {
@@ -213,7 +217,7 @@
     leftPanel.add(treePanel, BorderLayout.CENTER);
     if (UIUtil.isUnderDarcula()) {
       CompoundBorder border =
-        new CompoundBorder(new CustomLineBorder(UIUtil.getBorderColor(), 0, 0, 0, 1), BorderFactory.createEmptyBorder(0, 0, 0, 0));
+        new CompoundBorder(new CustomLineBorder(0, 0, 0, 1), BorderFactory.createEmptyBorder(0, 0, 0, 0));
       leftPanel.setBorder(border);
     } else {
       leftPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 0));
@@ -241,7 +245,7 @@
     labelPanel.add(link);
     rightTopPanel.add(labelPanel, BorderLayout.CENTER);
     rightPanel.add(rightTopPanel, BorderLayout.NORTH);
-    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySourceItemsTree, UIUtil.isUnderDarcula());
+    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySourceItemsTree, UIUtil.isUnderDarcula() || Registry.is("ide.new.project.settings"));
     JPanel scrollPaneWrap = new JPanel(new BorderLayout());
     scrollPaneWrap.add(scrollPane, BorderLayout.CENTER);
     if (UIUtil.isUnderDarcula()) {
@@ -257,6 +261,13 @@
       rightPanel.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 3));
     }
     splitter.setSecondComponent(rightPanel);
+    if (Registry.is("ide.new.project.settings")) {
+      splitter.getDivider().setBackground(UIUtil.getPanelBackground());
+      treePanel.setBorder(new EmptyBorder(0, 0, 0, 0));
+      rightPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
+      scrollPaneWrap.setBorder(new EmptyBorder(0,0,0,0));
+      leftPanel.setBorder(new EmptyBorder(0,0,0,0));
+    }
 
 
     myShowContentCheckBox.addActionListener(new ActionListener() {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
index d3edac7..17c9895 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
@@ -8,7 +8,7 @@
     <properties/>
     <border type="none"/>
     <children>
-      <grid id="6e544" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+      <grid id="6e544" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
index 52b601e..5deea9c 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
@@ -286,25 +286,7 @@
   }
 
   private void addArtifact(@NotNull ArtifactType type, @NotNull ArtifactTemplate artifactTemplate) {
-    final ArtifactTemplate.NewArtifactConfiguration configuration = artifactTemplate.createArtifact();
-    if (configuration == null) {
-      return;
-    }
-
-    final String baseName = configuration.getArtifactName();
-    String name = baseName;
-    int i = 2;
-    while (myPackagingEditorContext.getArtifactModel().findArtifact(name) != null) {
-      name = baseName + i;
-      i++;
-    }
-
-    ArtifactType actualType = configuration.getArtifactType();
-    if (actualType == null) {
-      actualType = type;
-    }
-    final ModifiableArtifact artifact = myPackagingEditorContext.getOrCreateModifiableArtifactModel().addArtifact(name, actualType, configuration.getRootElement());
-    artifactTemplate.setUpArtifact(artifact, configuration);
+    Artifact artifact = ArtifactUtil.addArtifact(myPackagingEditorContext.getOrCreateModifiableArtifactModel(), type, artifactTemplate);
     selectNodeInTree(findNodeByObject(myRoot, artifact));
   }
 
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
index ff1fdd3..d8392ea 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -47,7 +47,6 @@
 import com.intellij.ui.treeStructure.WeightBasedComparator;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.tree.TreeUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -132,7 +131,7 @@
     emptyPanel.setPreferredSize(new Dimension(0, 0));
 
     myPropertiesPanelWrapper = new JPanel(new CardLayout());
-    myPropertiesPanel.setBorder(new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, 0, 0));
+    myPropertiesPanel.setBorder(new CustomLineBorder(1, 0, 0, 0));
     myPropertiesPanelWrapper.add(EMPTY_CARD, emptyPanel);
     myPropertiesPanelWrapper.add(PROPERTIES_CARD, myPropertiesPanel);
   }
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
index 5d884a6..e47e955 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
@@ -41,6 +41,7 @@
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.JarFileSystem;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -48,6 +49,7 @@
 import com.intellij.ui.AnActionButton;
 import com.intellij.ui.AnActionButtonRunnable;
 import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.border.CustomLineBorder;
 import com.intellij.ui.treeStructure.Tree;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IconUtil;
@@ -157,7 +159,9 @@
     ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myTree).disableUpDownActions()
       .setRemoveActionName(ProjectBundle.message("library.remove.action"))
       .disableRemoveAction();
-
+    if (Registry.is("ide.new.project.settings")) {
+      toolbarDecorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
+    }
     final List<AttachRootButtonDescriptor> popupItems = new ArrayList<AttachRootButtonDescriptor>();
     for (AttachRootButtonDescriptor descriptor : myDescriptor.createAttachButtons()) {
       Icon icon = descriptor.getToolbarIcon();
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
index b88f924..a3b1db0 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
@@ -38,7 +38,6 @@
 import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.packaging.artifacts.Artifact;
 import com.intellij.ui.TreeSpeedSearch;
@@ -302,7 +301,7 @@
     result.addAll(copyActions);
     result.add(Separator.getInstance());
 
-    if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
+    if (fromPopup || !Registry.is("ide.new.project.settings")) {
       result.add(new MyFindUsagesAction(myTree));
     }
 
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
index e5a008d..d5248a5 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -35,6 +35,7 @@
 import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
 import com.intellij.openapi.ui.DetailsComponent;
 import com.intellij.openapi.ui.NamedConfigurable;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
 import com.intellij.util.ui.tree.TreeUtil;
@@ -277,8 +278,10 @@
       actions.add(new MyNavigateAction());
     }
     actions.add(new MyRemoveAction());
-    actions.add(Separator.getInstance());
-    addCollapseExpandActions(actions);
+    if (fromPopup || !(Registry.is("ide.new.project.settings"))) {
+      actions.add(Separator.getInstance());
+      addCollapseExpandActions(actions);
+    }
     return actions;
   }
 
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
index d89fe37..216ad98 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -54,15 +54,7 @@
       if (configurable != null) {
         final Icon icon = configurable.getIcon(expanded);
         final boolean showSeparator = configurable instanceof FrameworkDetectionConfigurable;
-        int width = -1;
-        if (showSeparator && tree.isVisible()) {
-          final int treeWidth = tree.getVisibleRect().width;
-          if (treeWidth > 0) {
-            width = treeWidth;
-          }
-        }
-        final JComponent component = configureComponent(node.getDisplayName(), null, icon, icon, selected, showSeparator, null,
-                                                        width);
+        final JComponent component = configureComponent(node.getDisplayName(), null, icon, icon, selected, showSeparator, null, -1);
 
         myTextLabel.setOpaque(selected);
         return component;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
index 1c313c1..a2a7e6b 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
@@ -53,7 +53,6 @@
 import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.NullableComputable;
-import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
@@ -149,9 +148,9 @@
   @NotNull
   protected ArrayList<AnAction> createActions(final boolean fromPopup) {
     final ArrayList<AnAction> result = super.createActions(fromPopup);
-    result.add(Separator.getInstance());
-    result.add(new MyGroupAction());
-    if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
+    if (fromPopup || !Registry.is("ide.new.project.settings")) {
+      result.add(Separator.getInstance());
+      result.add(new MyGroupAction());
       addCollapseExpandActions(result);
     }
     return result;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 7f8d013..c23ebdd 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -1292,5 +1292,31 @@
       }
     }
   }
+
+  public static HighlightInfo checkInferredIntersections(PsiSubstitutor substitutor, TextRange ref) {
+    for (Map.Entry<PsiTypeParameter, PsiType> typeEntry : substitutor.getSubstitutionMap().entrySet()) {
+      final PsiType type = typeEntry.getValue();
+      if (type instanceof PsiIntersectionType) {
+        final PsiType[] conjuncts = ((PsiIntersectionType)type).getConjuncts();
+        for (int i = 0; i < conjuncts.length; i++) {
+          PsiClass conjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i]);
+          if (conjunct != null && !conjunct.isInterface()) {
+            for (int i1 = i + 1; i1 < conjuncts.length; i1++) {
+              PsiClass oppositeConjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i1]);
+              if (oppositeConjunct != null && !oppositeConjunct.isInterface()) {
+                if (!conjunct.isInheritor(oppositeConjunct, true) && !oppositeConjunct.isInheritor(conjunct, true)) {
+                  return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
+                    .descriptionAndTooltip("Type parameter " + typeEntry.getKey().getName() + " has incompatible upper bounds: " +
+                                           conjunct.getName() + " and " + oppositeConjunct.getName())
+                    .range(ref).create();
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
 }
 
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 602e3fe..a4ea708 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -696,14 +696,17 @@
         return true;
       }
 
-      if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
-        final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
-        effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
-        if (effectivelyFinal) {
-          effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
+      final List<PsiReferenceExpression> readBeforeWriteLocals = ControlFlowUtil.getReadBeforeWriteLocals(controlFlow);
+      for (PsiReferenceExpression expression : readBeforeWriteLocals) {
+        if (expression.resolve() == variable) {
+          return PsiUtil.isAccessedForReading(expression);
         }
-      } else {
-        effectivelyFinal = false;
+      }
+
+      final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
+      effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
+      if (effectivelyFinal) {
+        effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
       }
     }
     return effectivelyFinal;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index b567ce4..118c98e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -344,8 +344,12 @@
     if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
       TextRange fixRange = getFixRange(methodCall);
       highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
-      if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel)) {
-        highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
+      if (highlightInfo == null) {
+        if (!LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel)) {
+          highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
+        } else {
+          highlightInfo = GenericsHighlightUtil.checkInferredIntersections(substitutor, fixRange);
+        }
       }
     }
     else {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
index c1f127d..621ce3f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
@@ -141,7 +141,19 @@
             .inferTypeArguments(method.getTypeParameters(), parameters, expressions,
                                 ((MethodCandidateInfo)result).getSiteSubstitutor(), callExpr.getParent(),
                                 DefaultParameterTypeInferencePolicy.INSTANCE);
-          return substitutor.substitute(parameters[i].getType());
+          PsiType paramType;
+          if (i < parameters.length) {
+            paramType = parameters[i].getType();
+          }
+          else {
+            paramType = parameters[parameters.length - 1].getType();
+            if (!(paramType instanceof PsiEllipsisType)) {
+              return null;
+            }
+            paramType = ((PsiEllipsisType)paramType).getComponentType();
+          }
+
+          return substitutor.substitute(paramType);
         }
       }
     }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
index 44e493c..47ef448 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
@@ -208,7 +208,8 @@
 }
 
 abstract class Analysis<Res> {
-  private static final int STEPS_LIMIT = 30000;
+  public static final int STEPS_LIMIT = 30000;
+  public static final int EQUATION_SIZE_LIMIT = 30;
   final RichControlFlow richControlFlow;
   final Direction direction;
   final ControlFlowGraph controlFlow;
@@ -225,7 +226,7 @@
   Res earlyResult = null;
 
   abstract Res identity();
-  abstract Res combineResults(Res delta, List<Res> subResults);
+  abstract Res combineResults(Res delta, List<Res> subResults) throws AnalyzerException;
   abstract boolean isEarlyResult(Res res);
   abstract Equation<Key, Value> mkEquation(Res result);
   abstract void processState(State state) throws AnalyzerException;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
index f29dd7f..0239a66 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
@@ -15,112 +15,68 @@
  */
 package com.intellij.codeInspection.bytecodeAnalysis;
 
-import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.components.ApplicationComponent;
 import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.util.ThrowableComputable;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.io.*;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntObjectHashMap;
-import gnu.trove.TIntObjectIterator;
+import gnu.trove.TLongArrayList;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongObjectHashMap;
+import gnu.trove.TLongObjectIterator;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 import org.jetbrains.org.objectweb.asm.Type;
 
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
 
 import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG;
 
 /**
  * @author lambdamix
  */
-public class BytecodeAnalysisConverter implements ApplicationComponent {
+public abstract class BytecodeAnalysisConverter implements ApplicationComponent {
 
-  private static final String VERSION = "BytecodeAnalysisConverter.Enumerators";
+  public static final int SHIFT = 4096;
 
   public static BytecodeAnalysisConverter getInstance() {
     return ApplicationManager.getApplication().getComponent(BytecodeAnalysisConverter.class);
   }
 
-  private PersistentStringEnumerator myNamesEnumerator;
-  private PersistentEnumeratorDelegate<int[]> myCompoundKeyEnumerator;
-  private int version;
-
-  @Override
-  public void initComponent() {
-    version = PropertiesComponent.getInstance().getOrInitInt(VERSION, 0);
-    final File keysDir = new File(PathManager.getIndexRoot(), "bytecodekeys");
-    final File namesFile = new File(keysDir, "names");
-    final File compoundKeysFile = new File(keysDir, "compound");
-
-    try {
-      IOUtil.openCleanOrResetBroken(new ThrowableComputable<Void, IOException>() {
-        @Override
-        public Void compute() throws IOException {
-          myNamesEnumerator = new PersistentStringEnumerator(namesFile, true);
-          myCompoundKeyEnumerator = new IntArrayPersistentEnumerator(compoundKeysFile, new IntArrayKeyDescriptor());
-          return null;
-        }
-      }, new Runnable() {
-        @Override
-        public void run() {
-          LOG.info("Error during initialization of enumerators in bytecode analysis. Re-initializing.");
-          IOUtil.deleteAllFilesStartingWith(keysDir);
-          version ++;
-        }
-      });
-    }
-    catch (IOException e) {
-      LOG.error("Re-initialization of enumerators in bytecode analysis failed.", e);
-    }
-    // TODO: is it enough for rebuilding indices?
-    PropertiesComponent.getInstance().setValue(VERSION, String.valueOf(version));
-  }
-
-  @Override
-  public void disposeComponent() {
-    try {
-      myNamesEnumerator.close();
-      myCompoundKeyEnumerator.close();
-    }
-    catch (IOException e) {
-      LOG.debug(e);
-    }
-  }
-
   @NotNull
   @Override
   public String getComponentName() {
     return "BytecodeAnalysisConverter";
   }
 
-  IntIdEquation convert(Equation<Key, Value> equation) throws IOException {
+  public abstract int getVersion();
+
+  protected abstract int enumerateString(@NotNull String s) throws IOException;
+
+  protected abstract int enumerateCompoundKey(@NotNull int[] key) throws IOException;
+
+  IdEquation convert(Equation<Key, Value> equation) throws IOException {
     ProgressManager.checkCanceled();
 
     Result<Key, Value> rhs = equation.rhs;
-    IntIdResult result;
+    IdResult result;
     if (rhs instanceof Final) {
-      result = new IntIdFinal(((Final<Key, Value>)rhs).value);
+      result = new IdFinal(((Final<Key, Value>)rhs).value);
     } else {
       Pending<Key, Value> pending = (Pending<Key, Value>)rhs;
       Set<Product<Key, Value>> sumOrigin = pending.sum;
       IntIdComponent[] components = new IntIdComponent[sumOrigin.size()];
       int componentI = 0;
       for (Product<Key, Value> prod : sumOrigin) {
-        int[] intProd = new int[prod.ids.size()];
+        long[] intProd = new long[prod.ids.size()];
         int idI = 0;
         for (Key id : prod.ids) {
-          int rawId = mkAsmKey(id);
+          long rawId = mkAsmKey(id);
           if (rawId <= 0) {
             LOG.error("raw key should be positive. rawId = " + rawId);
           }
@@ -131,24 +87,51 @@
         components[componentI] = intIdComponent;
         componentI++;
       }
-      result = new IntIdPending(components);
+      result = new IdPending(components);
     }
 
-    int rawKey = mkAsmKey(equation.id);
+    long rawKey = mkAsmKey(equation.id);
     if (rawKey <= 0) {
       LOG.error("raw key should be positive. rawKey = " + rawKey);
     }
 
-    int key = equation.id.stable ? rawKey : -rawKey;
-    return new IntIdEquation(key, result);
+    long key = equation.id.stable ? rawKey : -rawKey;
+    return new IdEquation(key, result);
   }
 
-  public int mkAsmKey(@NotNull Key key) throws IOException {
-    return myCompoundKeyEnumerator.enumerate(new int[]{mkDirectionKey(key.direction), mkAsmSignatureKey(key.method)});
+  public long mkAsmKey(@NotNull Key key) throws IOException {
+    long baseKey = mkAsmSignatureKey(key.method);
+    long directionKey = mkDirectionKey(key.direction);
+    return baseKey * SHIFT + directionKey;
   }
 
-  private int mkDirectionKey(Direction dir) throws IOException {
-    return myCompoundKeyEnumerator.enumerate(new int[]{dir.directionId(), dir.paramId(), dir.valueId()});
+  private static int mkDirectionKey(Direction dir) throws IOException {
+    if (dir instanceof Out) {
+      return 0;
+    } else if (dir instanceof In) {
+      In in = (In)dir;
+      return 8 * in.paramId() + 1;
+    } else {
+      InOut inOut = (InOut)dir;
+      return 8 * inOut.paramId() + 2 + inOut.valueId();
+    }
+  }
+
+  @NotNull
+  private static Direction extractDirection(int directionKey) {
+    if (directionKey == 0) {
+      return new Out();
+    }
+    else {
+      int paramId = directionKey / 8;
+      int subDirection = directionKey % 8;
+      if (subDirection == 1) {
+        return new In(paramId);
+      }
+      else {
+        return new InOut(paramId, Value.values()[subDirection - 2]);
+      }
+    }
   }
 
   // class + short signature
@@ -156,33 +139,19 @@
     int[] sigKey = new int[2];
     sigKey[0] = mkAsmTypeKey(Type.getObjectType(method.internalClassName));
     sigKey[1] = mkAsmShortSignatureKey(method);
-    return myCompoundKeyEnumerator.enumerate(sigKey);
+    return enumerateCompoundKey(sigKey);
   }
 
   private int mkAsmShortSignatureKey(@NotNull Method method) throws IOException {
     Type[] argTypes = Type.getArgumentTypes(method.methodDesc);
     int arity = argTypes.length;
-    int[] sigKey = new int[3 + arity];
+    int[] sigKey = new int[2 + arity];
     sigKey[0] = mkAsmTypeKey(Type.getReturnType(method.methodDesc));
-    sigKey[1] = myNamesEnumerator.enumerate(method.methodName);
-    sigKey[2] = argTypes.length;
+    sigKey[1] = enumerateString(method.methodName);
     for (int i = 0; i < argTypes.length; i++) {
-      sigKey[3 + i] = mkAsmTypeKey(argTypes[i]);
+      sigKey[2 + i] = mkAsmTypeKey(argTypes[i]);
     }
-    return myCompoundKeyEnumerator.enumerate(sigKey);
-  }
-
-  @Nullable
-  private static Direction extractDirection(int[] directionKey) {
-    switch (directionKey[0]) {
-      case Direction.OUT_DIRECTION:
-        return new Out();
-      case Direction.IN_DIRECTION:
-        return new In(directionKey[1]);
-      case Direction.INOUT_DIRECTION:
-        return new InOut(directionKey[1], Value.values()[directionKey[2]]);
-    }
-    return null;
+    return enumerateCompoundKey(sigKey);
   }
 
   private int mkAsmTypeKey(Type type) throws IOException {
@@ -197,22 +166,22 @@
       packageName = "";
       simpleName = className;
     }
-    int[] classKey = new int[]{myNamesEnumerator.enumerate(packageName), myNamesEnumerator.enumerate(simpleName)};
-    return myCompoundKeyEnumerator.enumerate(classKey);
+    int[] classKey = new int[]{enumerateString(packageName), enumerateString(simpleName)};
+    return enumerateCompoundKey(classKey);
   }
 
-  public int mkPsiKey(@NotNull PsiMethod psiMethod, Direction direction) throws IOException {
+  public long mkPsiKey(@NotNull PsiMethod psiMethod, Direction direction) throws IOException {
     final PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class, false);
     if (psiClass == null) {
       LOG.debug("PsiClass was null for " + psiMethod.getName());
       return -1;
     }
-    int sigKey = mkPsiSignatureKey(psiMethod);
+    long sigKey = mkPsiSignatureKey(psiMethod);
     if (sigKey == -1) {
       return -1;
     }
-    return myCompoundKeyEnumerator.enumerate(new int[]{mkDirectionKey(direction), sigKey});
-
+    long directionKey = mkDirectionKey(direction);
+    return sigKey * SHIFT + directionKey;
   }
 
   private int mkPsiSignatureKey(@NotNull PsiMethod psiMethod) throws IOException {
@@ -228,21 +197,20 @@
 
     final int shift = isInnerClassConstructor ? 1 : 0;
     final int arity = parameters.length + shift;
-    int[] shortSigKey = new int[3 + arity];
+    int[] shortSigKey = new int[2 + arity];
     if (returnType == null) {
       shortSigKey[0] = mkPsiTypeKey(PsiType.VOID);
-      shortSigKey[1] = myNamesEnumerator.enumerate("<init>");
+      shortSigKey[1] = enumerateString("<init>");
     } else {
       shortSigKey[0] = mkPsiTypeKey(returnType);
-      shortSigKey[1] = myNamesEnumerator.enumerate(psiMethod.getName());
+      shortSigKey[1] = enumerateString(psiMethod.getName());
     }
-    shortSigKey[2] = arity;
     if (isInnerClassConstructor) {
-      shortSigKey[3] = mkPsiClassKey(outerClass, 0);
+      shortSigKey[2] = mkPsiClassKey(outerClass, 0);
     }
     for (int i = 0; i < parameters.length; i++) {
       PsiParameter parameter = parameters[i];
-      shortSigKey[3 + i + shift] = mkPsiTypeKey(parameter.getType());
+      shortSigKey[2 + i + shift] = mkPsiTypeKey(parameter.getType());
     }
     for (int aShortSigKey : shortSigKey) {
       if (aShortSigKey == -1) {
@@ -256,9 +224,28 @@
       return -1;
     }
     sigKey[0] = classKey;
-    sigKey[1] = myCompoundKeyEnumerator.enumerate(shortSigKey);
+    sigKey[1] = enumerateCompoundKey(shortSigKey);
 
-    return myCompoundKeyEnumerator.enumerate(sigKey);
+    return enumerateCompoundKey(sigKey);
+  }
+
+  public TLongArrayList mkInOutKeys(@NotNull PsiMethod psiMethod, long primaryKey) throws IOException {
+    PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
+    TLongArrayList keys = new TLongArrayList(parameters.length * 2 + 1);
+    for (int i = 0; i < parameters.length; i++) {
+      PsiParameter parameter = parameters[i];
+      PsiType parameterType = parameter.getType();
+      if (parameterType instanceof PsiPrimitiveType) {
+        if (PsiType.BOOLEAN.equals(parameterType)) {
+          keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.False)));
+          keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.True)));
+        }
+      } else {
+        keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.NotNull)));
+        keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.Null)));
+      }
+    }
+    return keys;
   }
 
 
@@ -279,17 +266,17 @@
       className = qname.substring(packageName.length() + 1).replace('.', '$');
     }
     int[] classKey = new int[2];
-    classKey[0] = myNamesEnumerator.enumerate(packageName);
+    classKey[0] = enumerateString(packageName);
     if (dimensions == 0) {
-      classKey[1] = myNamesEnumerator.enumerate(className);
+      classKey[1] = enumerateString(className);
     } else {
       StringBuilder sb = new StringBuilder(className);
       for (int j = 0; j < dimensions; j++) {
         sb.append("[]");
       }
-      classKey[1] = myNamesEnumerator.enumerate(sb.toString());
+      classKey[1] = enumerateString(sb.toString());
     }
-    return myCompoundKeyEnumerator.enumerate(classKey);
+    return enumerateCompoundKey(classKey);
   }
 
   private int mkPsiTypeKey(PsiType psiType) throws IOException {
@@ -316,77 +303,69 @@
       String packageName = "";
       String className = psiType.getPresentableText();
       int[] classKey = new int[2];
-      classKey[0] = myNamesEnumerator.enumerate(packageName);
+      classKey[0] = enumerateString(packageName);
       if (dimensions == 0) {
-        classKey[1] = myNamesEnumerator.enumerate(className);
+        classKey[1] = enumerateString(className);
       } else {
         StringBuilder sb = new StringBuilder(className);
         for (int j = 0; j < dimensions; j++) {
           sb.append("[]");
         }
-        classKey[1] = myNamesEnumerator.enumerate(sb.toString());
+        classKey[1] = enumerateString(sb.toString());
       }
-      return myCompoundKeyEnumerator.enumerate(classKey);
+      return enumerateCompoundKey(classKey);
     }
     return -1;
   }
 
-  public void addAnnotations(TIntObjectHashMap<Value> internalIdSolutions, Annotations annotations) {
+  public void addMethodAnnotations(TLongObjectHashMap<Value> internalIdSolutions, Annotations annotations, long methodKey, int arity) {
 
-    TIntObjectHashMap<List<String>> contractClauses = new TIntObjectHashMap<List<String>>();
-    TIntObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
+    List<String> clauses = new ArrayList<String>();
+    TLongObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
 
-    TIntHashSet notNulls = annotations.notNulls;
-    TIntObjectHashMap<String> contracts = annotations.contracts;
-
+    TLongHashSet notNulls = annotations.notNulls;
+    TLongObjectHashMap<String> contracts = annotations.contracts;
     for (int i = internalIdSolutions.size(); i-- > 0;) {
       solutionsIterator.advance();
-      int key = Math.abs(solutionsIterator.key());
+      long key = Math.abs(solutionsIterator.key());
       Value value = solutionsIterator.value();
       if (value == Value.Top || value == Value.Bot) {
         continue;
       }
-      try {
-        int[] compoundKey = myCompoundKeyEnumerator.valueOf(key);
-        Direction direction = extractDirection(myCompoundKeyEnumerator.valueOf(compoundKey[0]));
-        if (value == Value.NotNull && (direction instanceof In || direction instanceof Out)) {
-          notNulls.add(key);
-        }
-        else if (direction instanceof InOut) {
-          compoundKey = new int[]{mkDirectionKey(new Out()), compoundKey[1]};
-          try {
-            int baseKey = myCompoundKeyEnumerator.enumerate(compoundKey);
-            List<String> clauses = contractClauses.get(baseKey);
-            if (clauses == null) {
-              clauses = new ArrayList<String>();
-              contractClauses.put(baseKey, clauses);
-            }
-            int[] sig = myCompoundKeyEnumerator.valueOf(compoundKey[1]);
-            int[] shortSig = myCompoundKeyEnumerator.valueOf(sig[1]);
-            int arity = shortSig[2];
-            clauses.add(contractElement(arity, (InOut)direction, value));
-          }
-          catch (IOException e) {
-            LOG.debug(e);
-          }
-        }
+      Direction direction = extractDirection((int)(key % SHIFT));
+      if (value == Value.NotNull && direction instanceof Out && key == methodKey) {
+        notNulls.add(key);
       }
-      catch (IOException e) {
-        LOG.debug(e);
+      else if (direction instanceof InOut) {
+        long baseKey = key - (key % SHIFT);
+        if (baseKey == methodKey) {
+          clauses.add(contractElement(arity, (InOut)direction, value));
+        }
       }
     }
 
-    TIntObjectIterator<List<String>> buildersIterator = contractClauses.iterator();
-    for (int i = contractClauses.size(); i-- > 0;) {
-      buildersIterator.advance();
-      int key = buildersIterator.key();
-      if (!notNulls.contains(key)) {
-        List<String> clauses = buildersIterator.value();
-        Collections.sort(clauses);
-        StringBuilder sb = new StringBuilder("\"");
-        StringUtil.join(clauses, ";", sb);
-        sb.append('"');
-        contracts.put(key, sb.toString().intern());
+    if (!notNulls.contains(methodKey) && !clauses.isEmpty()) {
+      Collections.sort(clauses);
+      StringBuilder sb = new StringBuilder("\"");
+      StringUtil.join(clauses, ";", sb);
+      sb.append('"');
+      contracts.put(methodKey, sb.toString().intern());
+    }
+  }
+
+  public void addParameterAnnotations(TLongObjectHashMap<Value> internalIdSolutions, Annotations annotations) {
+    TLongObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
+    TLongHashSet notNulls = annotations.notNulls;
+    for (int i = internalIdSolutions.size(); i-- > 0;) {
+      solutionsIterator.advance();
+      long key = Math.abs(solutionsIterator.key());
+      Value value = solutionsIterator.value();
+      if (value == Value.Top || value == Value.Bot) {
+        continue;
+      }
+      Direction direction = extractDirection((int)(key % SHIFT));
+      if (value == Value.NotNull && (direction instanceof In || direction instanceof Out)) {
+        notNulls.add(key);
       }
     }
   }
@@ -418,68 +397,4 @@
     return sb.toString();
   }
 
-  public int getVersion() {
-    return version;
-  }
-
-  private static class IntArrayKeyDescriptor implements KeyDescriptor<int[]> {
-
-    @Override
-    public void save(@NotNull DataOutput out, int[] value) throws IOException {
-      DataInputOutputUtil.writeINT(out, value.length);
-      for (int i : value) {
-        DataInputOutputUtil.writeINT(out, i);
-      }
-    }
-
-    @Override
-    public int[] read(@NotNull DataInput in) throws IOException {
-      int[] value = new int[DataInputOutputUtil.readINT(in)];
-      for (int i = 0; i < value.length; i++) {
-        value[i] = DataInputOutputUtil.readINT(in);
-      }
-      return value;
-    }
-
-    @Override
-    public int getHashCode(int[] value) {
-      return Arrays.hashCode(value);
-    }
-
-    @Override
-    public boolean isEqual(int[] val1, int[] val2) {
-      return Arrays.equals(val1, val2);
-    }
-  }
-
-  private static class IntArrayPersistentEnumerator extends PersistentEnumeratorDelegate<int[]> {
-    private final CachingEnumerator<int[]> myCache;
-
-    public IntArrayPersistentEnumerator(File compoundKeysFile, IntArrayKeyDescriptor descriptor) throws IOException {
-      super(compoundKeysFile, descriptor, 1024 * 4);
-      myCache = new CachingEnumerator<int[]>(new DataEnumerator<int[]>() {
-        @Override
-        public int enumerate(@Nullable int[] value) throws IOException {
-          return IntArrayPersistentEnumerator.super.enumerate(value);
-        }
-
-        @Nullable
-        @Override
-        public int[] valueOf(int idx) throws IOException {
-          return IntArrayPersistentEnumerator.super.valueOf(idx);
-        }
-      }, descriptor);
-    }
-
-    @Override
-    public int enumerate(@Nullable int[] value) throws IOException {
-      return myCache.enumerate(value);
-    }
-
-    @Nullable
-    @Override
-    public int[] valueOf(int idx) throws IOException {
-      return myCache.valueOf(idx);
-    }
-  }
 }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java
new file mode 100644
index 0000000..067cc74
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInspection.bytecodeAnalysis;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.io.DataOutputStream;
+import java.util.Arrays;
+
+import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG;
+
+/**
+ * @author lambdamix
+ */
+public class BytecodeAnalysisConverterImpl extends BytecodeAnalysisConverter {
+  private static final int LOGIC_VERSION = 1;
+  private static final String ENUMERATORS_VERSION_KEY = "BytecodeAnalysisConverter.Enumerators";
+
+  private File myVersionFile;
+  private PersistentStringEnumerator myNamesEnumerator;
+  private PersistentEnumeratorDelegate<int[]> myCompoundKeyEnumerator;
+  private int version;
+
+  @Override
+  public void initComponent() {
+
+    // suffix as an indicator of version
+    final File keysDir = new File(PathManager.getIndexRoot(), "bytecodekeys");
+    final File namesFile = new File(keysDir, "names" + LOGIC_VERSION);
+    final File compoundKeysFile = new File(keysDir, "compound" + LOGIC_VERSION);
+    myVersionFile = new File(keysDir, "version" + LOGIC_VERSION);
+
+    version = PropertiesComponent.getInstance().getOrInitInt(ENUMERATORS_VERSION_KEY, 0);
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      version = _readVersion();
+    }
+
+    if (!namesFile.exists() || !compoundKeysFile.exists() || !myVersionFile.exists()) {
+      LOG.info("No enumerators detected, re-initialization of enumerators.");
+      IOUtil.deleteAllFilesStartingWith(keysDir);
+      version++;
+    }
+
+    try {
+      IOUtil.openCleanOrResetBroken(new ThrowableComputable<Void, IOException>() {
+        @Override
+        public Void compute() throws IOException {
+          myNamesEnumerator = new PersistentStringEnumerator(namesFile, true);
+          myCompoundKeyEnumerator = new IntArrayPersistentEnumerator(compoundKeysFile, new IntArrayKeyDescriptor());
+          return null;
+        }
+      }, new Runnable() {
+        @Override
+        public void run() {
+          LOG.info("Error during initialization of enumerators in bytecode analysis. Re-initializing.");
+          IOUtil.deleteAllFilesStartingWith(keysDir);
+          version++;
+        }
+      });
+    }
+    catch (IOException e) {
+      LOG.error("Re-initialization of enumerators in bytecode analysis failed.", e);
+    }
+    PropertiesComponent.getInstance().setValue(ENUMERATORS_VERSION_KEY, String.valueOf(version));
+    _saveVersion();
+  }
+
+  @Override
+  public void disposeComponent() {
+    try {
+      myNamesEnumerator.close();
+      myCompoundKeyEnumerator.close();
+    }
+    catch (IOException e) {
+      LOG.debug(e);
+    }
+  }
+
+  public int _readVersion() {
+    try {
+      final DataInputStream is = new DataInputStream(new FileInputStream(myVersionFile));
+      try {
+        return is.readInt();
+      }
+      finally {
+        is.close();
+      }
+    }
+    catch (FileNotFoundException ignored) {
+    }
+    catch (IOException ignored) {
+    }
+    return 0;
+  }
+
+  private void _saveVersion() {
+    try {
+      FileUtil.createIfDoesntExist(myVersionFile);
+      final DataOutputStream os = new DataOutputStream(new FileOutputStream(myVersionFile));
+      try {
+        os.writeInt(version);
+      }
+      finally {
+        os.close();
+      }
+    }
+    catch (IOException ignored) {
+    }
+  }
+
+  public int getVersion() {
+    return version;
+  }
+
+  @Override
+  protected int enumerateString(@NotNull String s) throws IOException {
+    return myNamesEnumerator.enumerate(s);
+  }
+
+  @Override
+  protected int enumerateCompoundKey(@NotNull int[] key) throws IOException {
+    return myCompoundKeyEnumerator.enumerate(key);
+  }
+
+  private static class IntArrayKeyDescriptor implements KeyDescriptor<int[]>, DifferentSerializableBytesImplyNonEqualityPolicy {
+
+    @Override
+    public void save(@NotNull DataOutput out, int[] value) throws IOException {
+      DataInputOutputUtil.writeINT(out, value.length);
+      for (int i : value) {
+        DataInputOutputUtil.writeINT(out, i);
+      }
+    }
+
+    @Override
+    public int[] read(@NotNull DataInput in) throws IOException {
+      int[] value = new int[DataInputOutputUtil.readINT(in)];
+      for (int i = 0; i < value.length; i++) {
+        value[i] = DataInputOutputUtil.readINT(in);
+      }
+      return value;
+    }
+
+    @Override
+    public int getHashCode(int[] value) {
+      return Arrays.hashCode(value);
+    }
+
+    @Override
+    public boolean isEqual(int[] val1, int[] val2) {
+      return Arrays.equals(val1, val2);
+    }
+  }
+
+  private static class IntArrayPersistentEnumerator extends PersistentEnumeratorDelegate<int[]> {
+    private final CachingEnumerator<int[]> myCache;
+
+    public IntArrayPersistentEnumerator(File compoundKeysFile, IntArrayKeyDescriptor descriptor) throws IOException {
+      super(compoundKeysFile, descriptor, 1024 * 4);
+      myCache = new CachingEnumerator<int[]>(new DataEnumerator<int[]>() {
+        @Override
+        public int enumerate(@Nullable int[] value) throws IOException {
+          return IntArrayPersistentEnumerator.super.enumerate(value);
+        }
+
+        @Nullable
+        @Override
+        public int[] valueOf(int idx) throws IOException {
+          return IntArrayPersistentEnumerator.super.valueOf(idx);
+        }
+      }, descriptor);
+    }
+
+    @Override
+    public int enumerate(@Nullable int[] value) throws IOException {
+      return myCache.enumerate(value);
+    }
+
+    @Nullable
+    @Override
+    public int[] valueOf(int idx) throws IOException {
+      return myCache.valueOf(idx);
+    }
+  }
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
index 6a4b327..297b2b6 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
@@ -19,31 +19,29 @@
 import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.util.SystemProperties;
 import com.intellij.util.indexing.*;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.DataInputOutputUtil;
-import com.intellij.util.io.EnumeratorIntegerDescriptor;
+import com.intellij.util.io.DifferentSerializableBytesImplyNonEqualityPolicy;
 import com.intellij.util.io.KeyDescriptor;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
 
 /**
  * @author lambdamix
  */
-public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Integer, Collection<IntIdEquation>> {
-  public static final ID<Integer, Collection<IntIdEquation>> NAME = ID.create("bytecodeAnalysis");
+public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Long, IdEquation> {
+  public static final ID<Long, IdEquation> NAME = ID.create("bytecodeAnalysis");
   private final EquationExternalizer myExternalizer = new EquationExternalizer();
-  private static final DataIndexer<Integer, Collection<IntIdEquation>, FileContent> INDEXER =
+  private static final DataIndexer<Long, IdEquation, FileContent> INDEXER =
     new ClassDataIndexer(BytecodeAnalysisConverter.getInstance());
+  private static final SmartLongKeyDescriptor KEY_DESCRIPTOR = new SmartLongKeyDescriptor();
 
-  private static final int ourInternalVersion = 2;
+  private static final int ourInternalVersion = 3;
   private static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.bytecode.contract.inference", isEnabledByDefault());
 
   private static boolean isEnabledByDefault() {
@@ -51,31 +49,27 @@
     return application.isInternal() || application.isUnitTestMode();
   }
 
-  public static int indexKey(VirtualFile file, boolean parameters) {
-    return (file instanceof VirtualFileWithId ? ((VirtualFileWithId)file).getId() * 2 :  -2) + (parameters ? 1 : 0);
-  }
-
   @NotNull
   @Override
-  public ID<Integer, Collection<IntIdEquation>> getName() {
+  public ID<Long, IdEquation> getName() {
     return NAME;
   }
 
   @NotNull
   @Override
-  public DataIndexer<Integer, Collection<IntIdEquation>, FileContent> getIndexer() {
+  public DataIndexer<Long, IdEquation, FileContent> getIndexer() {
     return INDEXER;
   }
 
   @NotNull
   @Override
-  public KeyDescriptor<Integer> getKeyDescriptor() {
-    return EnumeratorIntegerDescriptor.INSTANCE;
+  public KeyDescriptor<Long> getKeyDescriptor() {
+    return KEY_DESCRIPTOR;
   }
 
   @NotNull
   @Override
-  public DataExternalizer<Collection<IntIdEquation>> getValueExternalizer() {
+  public DataExternalizer<IdEquation> getValueExternalizer() {
     return myExternalizer;
   }
 
@@ -100,68 +94,108 @@
     return ourInternalVersion + BytecodeAnalysisConverter.getInstance().getVersion() + (ourEnabled ? 0xFF : 0);
   }
 
-  public static class EquationExternalizer implements DataExternalizer<Collection<IntIdEquation>> {
+  public static class EquationExternalizer implements DataExternalizer<IdEquation>, DifferentSerializableBytesImplyNonEqualityPolicy {
     @Override
-    public void save(@NotNull DataOutput out, Collection<IntIdEquation> equations) throws IOException {
-      DataInputOutputUtil.writeINT(out, equations.size());
+    public void save(@NotNull DataOutput out, IdEquation equation) throws IOException {
+      long id = equation.id;
+      int sign = id > 0 ? 1 : -1;
+      id = Math.abs(id);
+      int primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+      int secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+      out.writeInt(sign * primaryId);
+      DataInputOutputUtil.writeINT(out, secondaryId);
+      IdResult rhs = equation.rhs;
+      if (rhs instanceof IdFinal) {
+        IdFinal finalResult = (IdFinal)rhs;
+        out.writeBoolean(true); // final flag
+        DataInputOutputUtil.writeINT(out, finalResult.value.ordinal());
+      } else {
+        IdPending pendResult = (IdPending)rhs;
+        out.writeBoolean(false); // pending flag
+        DataInputOutputUtil.writeINT(out, pendResult.delta.length);
 
-      for (IntIdEquation equation : equations) {
-        out.writeInt(equation.id);
-        IntIdResult rhs = equation.rhs;
-        if (rhs instanceof IntIdFinal) {
-          IntIdFinal finalResult = (IntIdFinal)rhs;
-          out.writeBoolean(true); // final flag
-          DataInputOutputUtil.writeINT(out, finalResult.value.ordinal());
-        } else {
-          IntIdPending pendResult = (IntIdPending)rhs;
-          out.writeBoolean(false); // pending flag
-          DataInputOutputUtil.writeINT(out, pendResult.delta.length);
-
-          for (IntIdComponent component : pendResult.delta) {
-            DataInputOutputUtil.writeINT(out, component.value.ordinal());
-            int[] ids = component.ids;
-            DataInputOutputUtil.writeINT(out, ids.length);
-            for (int id : ids) {
-              out.writeInt(id);
-            }
+        for (IntIdComponent component : pendResult.delta) {
+          DataInputOutputUtil.writeINT(out, component.value.ordinal());
+          long[] ids = component.ids;
+          DataInputOutputUtil.writeINT(out, ids.length);
+          for (long id1 : ids) {
+            sign = id1 > 0 ? 1 : -1;
+            id = Math.abs(id1);
+            primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+            secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+            out.writeInt(sign * primaryId);
+            DataInputOutputUtil.writeINT(out, secondaryId);
           }
         }
       }
     }
 
     @Override
-    public Collection<IntIdEquation> read(@NotNull DataInput in) throws IOException {
+    public IdEquation read(@NotNull DataInput in) throws IOException {
+      long primaryId = in.readInt();
+      int sign = primaryId > 0 ? 1 : -1;
+      primaryId = Math.abs(primaryId);
+      int secondaryId = DataInputOutputUtil.readINT(in);
+      long equationId = sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+      boolean isFinal = in.readBoolean(); // flag
+      if (isFinal) {
+        int ordinal = DataInputOutputUtil.readINT(in);
+        Value value = Value.values()[ordinal];
+        return new IdEquation(equationId, new IdFinal(value));
+      } else {
 
-      int size = DataInputOutputUtil.readINT(in);
-      ArrayList<IntIdEquation> result = new ArrayList<IntIdEquation>(size);
+        int sumLength = DataInputOutputUtil.readINT(in);
+        IntIdComponent[] components = new IntIdComponent[sumLength];
 
-      for (int x = 0; x < size; x++) {
-        int equationId = in.readInt();
-        boolean isFinal = in.readBoolean(); // flag
-        if (isFinal) {
+        for (int i = 0; i < sumLength; i++) {
           int ordinal = DataInputOutputUtil.readINT(in);
           Value value = Value.values()[ordinal];
-          result.add(new IntIdEquation(equationId, new IntIdFinal(value)));
-        } else {
-
-          int sumLength = DataInputOutputUtil.readINT(in);
-          IntIdComponent[] components = new IntIdComponent[sumLength];
-
-          for (int i = 0; i < sumLength; i++) {
-            int ordinal = DataInputOutputUtil.readINT(in);
-            Value value = Value.values()[ordinal];
-            int componentSize = DataInputOutputUtil.readINT(in);
-            int[] ids = new int[componentSize];
-            for (int j = 0; j < componentSize; j++) {
-              ids[j] = in.readInt();
-            }
-            components[i] = new IntIdComponent(value, ids);
+          int componentSize = DataInputOutputUtil.readINT(in);
+          long[] ids = new long[componentSize];
+          for (int j = 0; j < componentSize; j++) {
+            primaryId = in.readInt();
+            sign = primaryId > 0 ? 1 : -1;
+            primaryId = Math.abs(primaryId);
+            secondaryId = DataInputOutputUtil.readINT(in);
+            long id = sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+            ids[j] = id;
           }
-          result.add(new IntIdEquation(equationId, new IntIdPending(components)));
+          components[i] = new IntIdComponent(value, ids);
         }
+        return new IdEquation(equationId, new IdPending(components));
       }
+    }
+  }
 
-      return result;
+  private static class SmartLongKeyDescriptor implements KeyDescriptor<Long>, DifferentSerializableBytesImplyNonEqualityPolicy {
+    @Override
+    public void save(@NotNull DataOutput out, Long value) throws IOException {
+      long id = value.longValue();
+      int sign = id > 0 ? 1 : -1;
+      id = Math.abs(id);
+      int primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+      int secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+      out.writeInt(primaryId * sign);
+      DataInputOutputUtil.writeINT(out, secondaryId);
+    }
+
+    @Override
+    public Long read(@NotNull DataInput in) throws IOException {
+      long primaryId = in.readInt();
+      int sign = primaryId > 0 ? 1 : -1;
+      primaryId = Math.abs(primaryId);
+      int secondaryId = DataInputOutputUtil.readINT(in);
+      return sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+    }
+
+    @Override
+    public int getHashCode(Long value) {
+      return value.hashCode();
+    }
+
+    @Override
+    public boolean isEqual(Long val1, Long val2) {
+      return val1.longValue() == val2.longValue();
     }
   }
 }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
index 5e74a8b..9e656b9 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
@@ -33,7 +33,7 @@
 /**
  * @author lambdamix
  */
-public class ClassDataIndexer implements DataIndexer<Integer, Collection<IntIdEquation>, FileContent> {
+public class ClassDataIndexer implements DataIndexer<Long, IdEquation, FileContent> {
   final BytecodeAnalysisConverter myConverter;
 
   public ClassDataIndexer(BytecodeAnalysisConverter converter) {
@@ -42,25 +42,20 @@
 
   @NotNull
   @Override
-  public Map<Integer, Collection<IntIdEquation>> map(@NotNull FileContent inputData) {
-    HashMap<Integer, Collection<IntIdEquation>> map = new HashMap<Integer, Collection<IntIdEquation>>(2);
+  public Map<Long, IdEquation> map(@NotNull FileContent inputData) {
+    HashMap<Long, IdEquation> map = new HashMap<Long, IdEquation>();
     try {
       ClassEquations rawEquations = processClass(new ClassReader(inputData.getContent()));
       List<Equation<Key, Value>> rawParameterEquations = rawEquations.parameterEquations;
       List<Equation<Key, Value>> rawContractEquations = rawEquations.contractEquations;
 
-      Collection<IntIdEquation> idParameterEquations = new ArrayList<IntIdEquation>(rawParameterEquations.size());
-      Collection<IntIdEquation> idContractEquations = new ArrayList<IntIdEquation>(rawContractEquations.size());
-
-      map.put(BytecodeAnalysisIndex.indexKey(inputData.getFile(), true), idParameterEquations);
-      map.put(BytecodeAnalysisIndex.indexKey(inputData.getFile(), false), idContractEquations);
-
-
       for (Equation<Key, Value> rawParameterEquation: rawParameterEquations) {
-        idParameterEquations.add(myConverter.convert(rawParameterEquation));
+        IdEquation equation = myConverter.convert(rawParameterEquation);
+        map.put(equation.id, equation);
       }
       for (Equation<Key, Value> rawContractEquation: rawContractEquations) {
-        idContractEquations.add(myConverter.convert(rawContractEquation));
+        IdEquation equation = myConverter.convert(rawContractEquation);
+        map.put(equation.id, equation);
       }
     }
     catch (ProcessCanceledException e) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
index c837b12..7b6c52e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
@@ -49,7 +49,7 @@
   }
 
   @Override
-  Result<Key, Value> combineResults(Result<Key, Value> delta, List<Result<Key, Value>> subResults) {
+  Result<Key, Value> combineResults(Result<Key, Value> delta, List<Result<Key, Value>> subResults) throws AnalyzerException {
     Result<Key, Value> result = null;
     for (Result<Key, Value> subResult : subResults) {
       if (result == null) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
index 08c52c4..625eb8e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
@@ -78,8 +78,9 @@
   };
   static final class ConditionalNPE implements PResult {
     final Set<Set<Key>> sop;
-    public ConditionalNPE(Set<Set<Key>> sop) {
+    public ConditionalNPE(Set<Set<Key>> sop) throws AnalyzerException {
       this.sop = sop;
+      checkLimit(sop);
     }
 
     public ConditionalNPE(Key key) {
@@ -88,9 +89,19 @@
       prod.add(key);
       sop.add(prod);
     }
+
+    static void checkLimit(Set<Set<Key>> sop) throws AnalyzerException {
+      int size = 0;
+      for (Set<Key> keys : sop) {
+        size += keys.size();
+      }
+      if (size > Analysis.EQUATION_SIZE_LIMIT) {
+        throw new AnalyzerException(null, "Equation size is too big");
+      }
+    }
   }
 
-  static PResult join(PResult r1, PResult r2) {
+  static PResult join(PResult r1, PResult r2) throws AnalyzerException {
     if (Identity == r1) return r2;
     if (Identity == r2) return r1;
     if (Return == r1) return Return;
@@ -102,7 +113,7 @@
     return new ConditionalNPE(join(cnpe1.sop, cnpe2.sop));
   }
 
-  static PResult meet(PResult r1, PResult r2) {
+  static PResult meet(PResult r1, PResult r2) throws AnalyzerException {
     if (Identity == r1) return r2;
     if (Return == r1) return r2;
     if (Return == r2) return r1;
@@ -130,7 +141,7 @@
   }
 
   @Override
-  PResult combineResults(PResult delta, List<PResult> subResults) {
+  PResult combineResults(PResult delta, List<PResult> subResults) throws AnalyzerException {
     PResult subResult = Identity;
     for (PResult sr : subResults) {
       subResult = join(subResult, sr);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
index 86b9dd1..23d9d5a 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
@@ -15,34 +15,31 @@
  */
 package com.intellij.codeInspection.bytecodeAnalysis;
 
-import com.intellij.ProjectTopics;
 import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ContentIterator;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.ModificationTracker;
-import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.ProjectScope;
 import com.intellij.psi.util.CachedValueProvider;
 import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiFormatUtil;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.LongStack;
 import com.intellij.util.indexing.FileBasedIndex;
-import com.intellij.util.messages.MessageBusConnection;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TLongArrayList;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongObjectHashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.IOException;
-import java.util.Collection;
+import java.util.List;
 
 /**
  * @author lambdamix
@@ -50,93 +47,15 @@
 public class ProjectBytecodeAnalysis {
   public static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.bytecodeAnalysis");
   public static final Key<Boolean> INFERRED_ANNOTATION = Key.create("INFERRED_ANNOTATION");
+  public static final int EQUATIONS_LIMIT = 1000;
   private final Project myProject;
 
-  private volatile Annotations myAnnotations = null;
-
   public static ProjectBytecodeAnalysis getInstance(@NotNull Project project) {
     return ServiceManager.getService(project, ProjectBytecodeAnalysis.class);
   }
 
   public ProjectBytecodeAnalysis(Project project) {
     myProject = project;
-    final MessageBusConnection connection = myProject.getMessageBus().connect();
-    connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
-      @Override
-      public void rootsChanged(ModuleRootEvent event) {
-        unloadAnnotations();
-      }
-    });
-  }
-
-  private void loadAnnotations() {
-    Annotations annotations = new Annotations();
-    loadParameterAnnotations(annotations);
-    loadContractAnnotations(annotations);
-    myAnnotations = annotations;
-    LOG.debug("NotNull annotations: " + myAnnotations.notNulls.size());
-    LOG.debug("Contract annotations: " + myAnnotations.contracts.size());
-  }
-
-  private void unloadAnnotations() {
-    myAnnotations = null;
-    LOG.debug("unloaded");
-  }
-
-  private void loadParameterAnnotations(Annotations annotations) {
-    LOG.debug("initializing parameter annotations");
-    final IntIdSolver solver = new IntIdSolver(new ELattice<Value>(Value.NotNull, Value.Top));
-
-    processValues(true, new FileBasedIndex.ValueProcessor<Collection<IntIdEquation>>() {
-      @Override
-      public boolean process(VirtualFile file, Collection<IntIdEquation> value) {
-        for (IntIdEquation intIdEquation : value) {
-          solver.addEquation(intIdEquation);
-        }
-        return true;
-      }
-    });
-
-    LOG.debug("parameter equations are constructed");
-    LOG.debug("equations: " + solver.getSize());
-    TIntObjectHashMap<Value> solutions = solver.solve();
-    LOG.debug("parameter equations are solved");
-    BytecodeAnalysisConverter.getInstance().addAnnotations(solutions, annotations);
-  }
-
-  private void processValues(final boolean parameters, final FileBasedIndex.ValueProcessor<Collection<IntIdEquation>> processor) {
-    final GlobalSearchScope libScope = ProjectScope.getLibrariesScope(myProject);
-    final FileBasedIndex index = FileBasedIndex.getInstance();
-    index.iterateIndexableFiles(new ContentIterator() {
-      @Override
-      public boolean processFile(VirtualFile fileOrDir) {
-        ProgressManager.checkCanceled();
-        if (!fileOrDir.isDirectory() && libScope.contains(fileOrDir)) {
-          index.processValues(BytecodeAnalysisIndex.NAME, BytecodeAnalysisIndex.indexKey(fileOrDir, parameters),
-                              fileOrDir, processor, GlobalSearchScope.fileScope(myProject, fileOrDir));
-        }
-        return false;
-      }
-    }, myProject, null);
-  }
-
-  private void loadContractAnnotations(Annotations annotations) {
-    LOG.debug("initializing contract annotations");
-    final IntIdSolver solver = new IntIdSolver(new ELattice<Value>(Value.Bot, Value.Top));
-    processValues(false, new FileBasedIndex.ValueProcessor<Collection<IntIdEquation>>() {
-      @Override
-      public boolean process(VirtualFile file, Collection<IntIdEquation> value) {
-        for (IntIdEquation intIdEquation : value) {
-          solver.addEquation(intIdEquation);
-        }
-        return true;
-      }
-    });
-    LOG.debug("contract equations are constructed");
-    LOG.debug("equations: " + solver.getSize());
-    TIntObjectHashMap<Value> solutions = solver.solve();
-    LOG.debug("contract equations are solved");
-    BytecodeAnalysisConverter.getInstance().addAnnotations(solutions, annotations);
   }
 
   @Nullable
@@ -144,11 +63,14 @@
     if (!(listOwner instanceof PsiCompiledElement)) {
       return null;
     }
-    if (annotationFQN.equals("org.jetbrains.annotations.NotNull")) {
-      return findNotNullAnnotation(listOwner);
-    }
-    else if (annotationFQN.equals("org.jetbrains.annotations.Contract")) {
-      return findContractAnnotation(listOwner);
+    if (annotationFQN.equals(AnnotationUtil.NOT_NULL) || annotationFQN.equals(ControlFlowAnalyzer.ORG_JETBRAINS_ANNOTATIONS_CONTRACT)) {
+      PsiAnnotation[] annotations = findInferredAnnotations(listOwner);
+      for (PsiAnnotation annotation : annotations) {
+        if (annotationFQN.equals(annotation.getQualifiedName())) {
+          return annotation;
+        }
+      }
+      return null;
     }
     else {
       return null;
@@ -156,26 +78,30 @@
   }
 
   @NotNull
-  public PsiAnnotation[] findInferredAnnotations(@NotNull PsiModifierListOwner listOwner) {
+  public PsiAnnotation[] findInferredAnnotations(@NotNull final PsiModifierListOwner listOwner) {
     if (!(listOwner instanceof PsiCompiledElement)) {
       return PsiAnnotation.EMPTY_ARRAY;
     }
-    return collectInferredAnnotations(listOwner);
+    return CachedValuesManager.getCachedValue(listOwner, new CachedValueProvider<PsiAnnotation[]>() {
+      @Nullable
+      @Override
+      public Result<PsiAnnotation[]> compute() {
+        return Result.create(collectInferredAnnotations(listOwner), listOwner);
+      }
+    });
   }
 
-  // TODO the best way to synchronize?
   @NotNull
-  private synchronized PsiAnnotation[] collectInferredAnnotations(PsiModifierListOwner listOwner) {
-    if (myAnnotations == null) {
-      loadAnnotations();
-    }
+  private PsiAnnotation[] collectInferredAnnotations(PsiModifierListOwner listOwner) {
     try {
-      int key = getKey(listOwner);
-      if (key == -1) {
+      long ownerKey = getKey(listOwner);
+      if (ownerKey == -1) {
         return PsiAnnotation.EMPTY_ARRAY;
       }
-      boolean notNull = myAnnotations.notNulls.contains(key);
-      String contractValue = myAnnotations.contracts.get(key);
+      TLongArrayList allKeys = contractKeys(listOwner, ownerKey);
+      Annotations annotations = loadAnnotations(listOwner, ownerKey, allKeys);
+      boolean notNull = annotations.notNulls.contains(ownerKey);
+      String contractValue = annotations.contracts.get(ownerKey);
 
       if (notNull && contractValue != null) {
         return new PsiAnnotation[]{
@@ -201,6 +127,11 @@
       LOG.debug(e);
       return PsiAnnotation.EMPTY_ARRAY;
     }
+    catch (EquationsLimitException e) {
+      String externalName = PsiFormatUtil.getExternalName(listOwner, false, Integer.MAX_VALUE);
+      LOG.info("Too many equations for " + externalName);
+      return PsiAnnotation.EMPTY_ARRAY;
+    }
   }
 
   private PsiAnnotation getNotNullAnnotation() {
@@ -213,54 +144,15 @@
     });
   }
 
-  @Nullable
-  private synchronized PsiAnnotation findNotNullAnnotation(PsiModifierListOwner listOwner) {
-    if (myAnnotations == null) {
-      loadAnnotations();
-    }
-    try {
-      int key = getKey(listOwner);
-      if (key == -1) {
-        return null;
-      }
-      return myAnnotations.notNulls.contains(key) ? getNotNullAnnotation() : null;
-    }
-    catch (IOException e) {
-      LOG.debug(e);
-      return null;
-    }
-  }
-
-  @Nullable
-  private synchronized PsiAnnotation findContractAnnotation(PsiModifierListOwner listOwner) {
-    if (myAnnotations == null) {
-      loadAnnotations();
-    }
-    try {
-      int key = getKey(listOwner);
-      if (key == -1) {
-        return null;
-      }
-      String contractValue = myAnnotations.contracts.get(key);
-      return contractValue != null ? createContractAnnotation(contractValue) : null;
-    }
-    catch (IOException e) {
-      LOG.debug(e);
-      return null;
-    }
-  }
-
   public PsiAnnotation createContractAnnotation(String contractValue) {
     return createAnnotationFromText("@org.jetbrains.annotations.Contract(" + contractValue + ")");
   }
 
-  public static int getKey(@NotNull PsiModifierListOwner owner) throws IOException {
+  public static long getKey(@NotNull PsiModifierListOwner owner) throws IOException {
     LOG.assertTrue(owner instanceof PsiCompiledElement, owner);
-
     if (owner instanceof PsiMethod) {
       return BytecodeAnalysisConverter.getInstance().mkPsiKey((PsiMethod)owner, new Out());
     }
-
     if (owner instanceof PsiParameter) {
       PsiElement parent = owner.getParent();
       if (parent instanceof PsiParameterList) {
@@ -275,6 +167,80 @@
     return -1;
   }
 
+  public static TLongArrayList contractKeys(@NotNull PsiModifierListOwner owner, long primaryKey) throws IOException {
+    if (owner instanceof PsiMethod) {
+      TLongArrayList result = BytecodeAnalysisConverter.getInstance().mkInOutKeys((PsiMethod)owner, primaryKey);
+      result.add(primaryKey);
+      return result;
+    }
+    TLongArrayList result = new TLongArrayList(1);
+    result.add(primaryKey);
+    return result;
+  }
+
+  private Annotations loadAnnotations(@NotNull PsiModifierListOwner owner, long key, TLongArrayList allKeys)
+    throws IOException, EquationsLimitException {
+    Annotations result = new Annotations();
+    if (owner instanceof PsiParameter) {
+      final Solver solver = new Solver(new ELattice<Value>(Value.NotNull, Value.Top));
+      collectEquations(allKeys, solver);
+      TLongObjectHashMap<Value> solutions = solver.solve();
+      BytecodeAnalysisConverter.getInstance().addParameterAnnotations(solutions, result);
+    } else if (owner instanceof PsiMethod) {
+      final Solver solver = new Solver(new ELattice<Value>(Value.Bot, Value.Top));
+      collectEquations(allKeys, solver);
+      TLongObjectHashMap<Value> solutions = solver.solve();
+      BytecodeAnalysisConverter.getInstance().addMethodAnnotations(solutions, result, key,
+                                                                   ((PsiMethod)owner).getParameterList().getParameters().length);
+    }
+    return result;
+  }
+
+  private void collectEquations(TLongArrayList keys, Solver solver) throws EquationsLimitException {
+    GlobalSearchScope librariesScope = ProjectScope.getLibrariesScope(myProject);
+    TLongHashSet queued = new TLongHashSet();
+    LongStack queue = new LongStack();
+
+    for (int i = 0; i < keys.size(); i++) {
+      long key = keys.get(i);
+      queue.push(key);
+      queued.add(key);
+      // stable/unstable
+      queue.push(-key);
+      queued.add(-key);
+    }
+
+    FileBasedIndex index = FileBasedIndex.getInstance();
+    while (!queue.empty()) {
+      if (queued.size() > EQUATIONS_LIMIT) {
+        throw new EquationsLimitException();
+      }
+      ProgressManager.checkCanceled();
+      List<IdEquation> equations = index.getValues(BytecodeAnalysisIndex.NAME, queue.pop(), librariesScope);
+      for (IdEquation equation : equations) {
+        IdResult rhs = equation.rhs;
+        solver.addEquation(equation);
+        if (rhs instanceof IdPending) {
+          IdPending intIdPending = (IdPending)rhs;
+          for (IntIdComponent component : intIdPending.delta) {
+            for (long depKey : component.ids) {
+              if (!queued.contains(depKey)) {
+                queue.push(depKey);
+                queued.add(depKey);
+              }
+              // stable/unstable
+              long swapped = -depKey;
+              if (!queued.contains(swapped)) {
+                queue.push(swapped);
+                queued.add(swapped);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
   @NotNull
   private PsiAnnotation createAnnotationFromText(@NotNull final String text) throws IncorrectOperationException {
     PsiAnnotation annotation = JavaPsiFacade.getElementFactory(myProject).createAnnotationFromText(text, null);
@@ -285,7 +251,9 @@
 
 class Annotations {
   // @NotNull keys
-  final TIntHashSet notNulls = new TIntHashSet();
+  final TLongHashSet notNulls = new TLongHashSet();
   // @Contracts
-  final TIntObjectHashMap<String> contracts = new TIntObjectHashMap<String>();
+  final TLongObjectHashMap<String> contracts = new TLongObjectHashMap<String>();
 }
+
+class EquationsLimitException extends Exception {}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
index 47c9779..1dec1de 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
@@ -15,10 +15,12 @@
  */
 package com.intellij.codeInspection.bytecodeAnalysis;
 
-import com.intellij.util.containers.IntStack;
-import com.intellij.util.containers.IntToIntSetMap;
-import gnu.trove.TIntObjectHashMap;
+import com.intellij.util.containers.LongStack;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongIterator;
+import gnu.trove.TLongObjectHashMap;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
 
 import java.util.*;
 
@@ -49,9 +51,9 @@
 // component specialized for ints
 final class IntIdComponent {
   Value value;
-  final int[] ids;
+  final long[] ids;
 
-  IntIdComponent(Value value,  int[] ids) {
+  IntIdComponent(Value value,  long[] ids) {
     this.value = value;
     this.ids = ids;
   }
@@ -74,7 +76,7 @@
     return value.ordinal() + Arrays.hashCode(ids);
   }
 
-  public boolean remove(int id) {
+  public boolean remove(long id) {
     return IdUtils.remove(ids, id);
   }
 
@@ -89,18 +91,18 @@
 
 class IdUtils {
   // removed value
-  static final int nullId = 0;
+  static final long nullId = 0;
 
-  static boolean contains(int[] ids, int id) {
-    for (int id1 : ids) {
+  static boolean contains(long[] ids, int id) {
+    for (long id1 : ids) {
       if (id1 == id) return true;
     }
 
     return false;
   }
 
-  static boolean isEmpty(int[] ids) {
-    for (int id : ids) {
+  static boolean isEmpty(long[] ids) {
+    for (long id : ids) {
       if (id != nullId) return false;
     }
     return true;
@@ -117,7 +119,7 @@
     return result;
   }
 
-  static boolean remove(int[] ids, int id) {
+  static boolean remove(long[] ids, long id) {
     boolean removed = false;
     for (int i = 0; i < ids.length; i++) {
       if (ids[i] == id) {
@@ -137,7 +139,7 @@
     top = lattice.top;
   }
 
-  Result<Id, T> join(Result<Id, T> r1, Result<Id, T> r2) {
+  Result<Id, T> join(Result<Id, T> r1, Result<Id, T> r2) throws AnalyzerException {
     if (r1 instanceof Final && ((Final) r1).value == top) {
       return r1;
     }
@@ -166,8 +168,19 @@
     Set<Product<Id, T>> sum = new HashSet<Product<Id, T>>();
     sum.addAll(pending1.sum);
     sum.addAll(pending2.sum);
+    checkLimit(sum);
     return new Pending<Id, T>(sum);
   }
+
+  private void checkLimit(Set<Product<Id, T>> sum) throws AnalyzerException {
+    int size = 0;
+    for (Product<Id, T> prod : sum) {
+      size += prod.ids.size();
+    }
+    if (size > Analysis.EQUATION_SIZE_LIMIT) {
+      throw new AnalyzerException(null, "Equation size is too big");
+    }
+  }
 }
 
 final class Product<K, V> {
@@ -222,11 +235,11 @@
 
 }
 
-interface IntIdResult {}
+interface IdResult {}
 // this just wrapper, no need for this really
-final class IntIdFinal implements IntIdResult {
+final class IdFinal implements IdResult {
   final Value value;
-  public IntIdFinal(Value value) {
+  public IdFinal(Value value) {
     this.value = value;
   }
 
@@ -235,7 +248,7 @@
     if (this == o) return true;
     if (o == null || getClass() != o.getClass()) return false;
 
-    IntIdFinal that = (IntIdFinal)o;
+    IdFinal that = (IdFinal)o;
 
     if (value != that.value) return false;
 
@@ -253,19 +266,19 @@
   }
 }
 
-final class IntIdPending implements IntIdResult {
+final class IdPending implements IdResult {
   final IntIdComponent[] delta;
 
-  IntIdPending(IntIdComponent[] delta) {
+  IdPending(IntIdComponent[] delta) {
     this.delta = delta;
   }
 
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
-    if (!(o instanceof IntIdPending)) return false;
-    IntIdPending pending = (IntIdPending)o;
-    return !Arrays.equals(delta, pending.delta);
+    if (!(o instanceof IdPending)) return false;
+    IdPending pending = (IdPending)o;
+    return Arrays.equals(delta, pending.delta);
   }
 
   @Override
@@ -273,20 +286,20 @@
     return Arrays.hashCode(delta);
   }
 
-  IntIdPending copy() {
+  IdPending copy() {
     IntIdComponent[] delta1 = new IntIdComponent[delta.length];
     for (int i = 0; i < delta.length; i++) {
       delta1[i] = delta[i].copy();
     }
-    return new IntIdPending(delta1);
+    return new IdPending(delta1);
   }
 }
 
-final class IntIdEquation {
-  final int id;
-  final IntIdResult rhs;
+final class IdEquation {
+  final long id;
+  final IdResult rhs;
 
-  IntIdEquation(int id, IntIdResult rhs) {
+  IdEquation(long id, IdResult rhs) {
     this.id = id;
     this.rhs = rhs;
   }
@@ -294,9 +307,9 @@
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
-    if (!(o instanceof IntIdEquation)) return false;
+    if (!(o instanceof IdEquation)) return false;
 
-    IntIdEquation equation = (IntIdEquation)o;
+    IdEquation equation = (IdEquation)o;
 
     if (id != equation.id) return false;
     if (!rhs.equals(equation.rhs)) return false;
@@ -306,9 +319,7 @@
 
   @Override
   public int hashCode() {
-    int result = id;
-    result = 31 * result + rhs.hashCode();
-    return result;
+    return 31 * ((int)(id ^ (id >>> 32))) + rhs.hashCode();
   }
 }
 
@@ -337,41 +348,46 @@
   }
 }
 
-final class IntIdSolver {
+final class Solver {
 
   private int size = 0;
   private final ELattice<Value> lattice;
-  private final IntToIntSetMap dependencies = new IntToIntSetMap(10000, 0.5f);
-  private final TIntObjectHashMap<IntIdPending> pending = new TIntObjectHashMap<IntIdPending>();
-  private final TIntObjectHashMap<Value> solved = new TIntObjectHashMap<Value>();
-  private final IntStack moving = new IntStack();
+  private final TLongObjectHashMap<TLongHashSet> dependencies = new TLongObjectHashMap<TLongHashSet>();
+  private final TLongObjectHashMap<IdPending> pending = new TLongObjectHashMap<IdPending>();
+  private final TLongObjectHashMap<Value> solved = new TLongObjectHashMap<Value>();
+  private final LongStack moving = new LongStack();
 
   int getSize() {
     return size;
   }
 
-  IntIdSolver(ELattice<Value> lattice) {
+  Solver(ELattice<Value> lattice) {
     this.lattice = lattice;
   }
 
-  void addEquation(IntIdEquation equation) {
+  void addEquation(IdEquation equation) {
     size ++;
-    IntIdResult rhs = equation.rhs;
-    if (rhs instanceof IntIdFinal) {
-      solved.put(equation.id, ((IntIdFinal) rhs).value);
+    IdResult rhs = equation.rhs;
+    if (rhs instanceof IdFinal) {
+      solved.put(equation.id, ((IdFinal) rhs).value);
       moving.push(equation.id);
-    } else if (rhs instanceof IntIdPending) {
-      IntIdPending pendResult = ((IntIdPending)rhs).copy();
-      IntIdResult norm = normalize(pendResult.delta);
-      if (norm instanceof IntIdFinal) {
-        solved.put(equation.id, ((IntIdFinal) norm).value);
+    } else if (rhs instanceof IdPending) {
+      IdPending pendResult = ((IdPending)rhs).copy();
+      IdResult norm = normalize(pendResult.delta);
+      if (norm instanceof IdFinal) {
+        solved.put(equation.id, ((IdFinal) norm).value);
         moving.push(equation.id);
       }
       else {
-        IntIdPending pendResult1 = ((IntIdPending)rhs).copy();
+        IdPending pendResult1 = ((IdPending)rhs).copy();
         for (IntIdComponent component : pendResult1.delta) {
-          for (int trigger : component.ids) {
-            dependencies.addOccurence(trigger, equation.id);
+          for (long trigger : component.ids) {
+            TLongHashSet set = dependencies.get(trigger);
+            if (set == null) {
+              set = new TLongHashSet();
+              dependencies.put(trigger, set);
+            }
+            set.add(equation.id);
           }
           pending.put(equation.id, pendResult1);
         }
@@ -379,31 +395,35 @@
     }
   }
 
-  TIntObjectHashMap<Value> solve() {
+  TLongObjectHashMap<Value> solve() {
     while (!moving.empty()) {
-      int id = moving.pop();
+      long id = moving.pop();
       Value value = solved.get(id);
 
       boolean stable = id > 0;
-      int[] pIds  = stable ? new int[]{id, -id} : new int[]{-id, id};
+      long[] pIds  = stable ? new long[]{id, -id} : new long[]{-id, id};
       Value[] pVals = stable ? new Value[]{value, value} : new Value[]{value, lattice.top};
 
       for (int i = 0; i < pIds.length; i++) {
-        int pId = pIds[i];
+        long pId = pIds[i];
         Value pVal = pVals[i];
-        // todo - remove
-        int[] dIds = dependencies.get(pId);
-        for (int dId : dIds) {
-          IntIdPending pend = pending.remove(dId);
+        TLongHashSet dIds = dependencies.get(pId);
+        if (dIds == null) {
+          continue;
+        }
+        TLongIterator dIdsIterator = dIds.iterator();
+        while (dIdsIterator.hasNext()) {
+          long dId = dIdsIterator.next();
+          IdPending pend = pending.remove(dId);
           if (pend != null) {
-            IntIdResult pend1 = substitute(pend, pId, pVal);
-            if (pend1 instanceof IntIdFinal) {
-              IntIdFinal fi = (IntIdFinal)pend1;
+            IdResult pend1 = substitute(pend, pId, pVal);
+            if (pend1 instanceof IdFinal) {
+              IdFinal fi = (IdFinal)pend1;
               solved.put(dId, fi.value);
               moving.push(dId);
             }
             else {
-              pending.put(dId, (IntIdPending)pend1);
+              pending.put(dId, (IdPending)pend1);
             }
           }
         }
@@ -414,7 +434,7 @@
   }
 
   // substitute id -> value into pending
-  IntIdResult substitute(IntIdPending pending, int id, Value value) {
+  IdResult substitute(IdPending pending, long id, Value value) {
     IntIdComponent[] sum = pending.delta;
     for (IntIdComponent intIdComponent : sum) {
       if (intIdComponent.remove(id)) {
@@ -424,7 +444,7 @@
     return normalize(sum);
   }
 
-  IntIdResult normalize(IntIdComponent[] sum) {
+  IdResult normalize(IntIdComponent[] sum) {
     Value acc = lattice.bot;
     boolean computableNow = true;
     for (IntIdComponent prod : sum) {
@@ -434,7 +454,7 @@
         computableNow = false;
       }
     }
-    return (acc == lattice.top || computableNow) ? new IntIdFinal(acc) : new IntIdPending(sum);
+    return (acc == lattice.top || computableNow) ? new IdFinal(acc) : new IdPending(sum);
   }
 
 }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
index a1c9088..bd207e5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
@@ -71,7 +71,23 @@
     if (statements.length == 1) {
       if (statements[0] instanceof PsiReturnStatement) {
         List<MethodContract> result = handleDelegation(((PsiReturnStatement)statements[0]).getReturnValue(), false);
-        if (result != null) return result;
+        if (result != null) {
+          PsiTypeElement typeElement = myMethod.getReturnTypeElement();
+          final boolean returningObject = typeElement == null || !(typeElement.getType() instanceof PsiClassType);
+          return ContainerUtil.findAll(result, new Condition<MethodContract>() {
+            @Override
+            public boolean value(MethodContract contract) {
+              if ((contract.returnValue == NULL_VALUE || contract.returnValue == NOT_NULL_VALUE) && returningObject) {
+                return false;
+              }
+              if ((contract.returnValue == TRUE_VALUE || contract.returnValue == FALSE_VALUE) && !returningObject) {
+                return false;
+              }
+
+              return true;
+            }
+          });
+        }
       }
       else if (statements[0] instanceof PsiExpressionStatement && ((PsiExpressionStatement)statements[0]).getExpression() instanceof PsiMethodCallExpression) {
         List<MethodContract> result = handleDelegation(((PsiExpressionStatement)statements[0]).getExpression(), false);
@@ -132,6 +148,9 @@
                 }
                 else {
                   answer = withConstraint(answer, paramIndex, argConstraint);
+                  if (answer == null) {
+                    return null;
+                  }
                 }
               }
             }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
index 691c2f0..1167210 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
@@ -89,10 +89,16 @@
         throw new ParseException("A contract clause must be in form arg1, ..., argN -> return-value");
       }
 
-      String[] argStrings = clause.substring(0, arrowIndex).split(",");
-      ValueConstraint[] args = new ValueConstraint[argStrings.length];
-      for (int i = 0; i < args.length; i++) {
-        args[i] = parseConstraint(argStrings[i]);
+      String beforeArrow = clause.substring(0, arrowIndex);
+      ValueConstraint[] args;
+      if (StringUtil.isNotEmpty(beforeArrow)) {
+        String[] argStrings = beforeArrow.split(",");
+        args = new ValueConstraint[argStrings.length];
+        for (int i = 0; i < args.length; i++) {
+          args[i] = parseConstraint(argStrings[i]);
+        }
+      } else {
+        args = new ValueConstraint[0];
       }
       result.add(new MethodContract(args, parseConstraint(clause.substring(arrowIndex + arrow.length()))));
     }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index 013e24c..3644912 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -500,21 +500,19 @@
 
     PsiType varType = var.getVariableType();
     if (!(varType instanceof PsiPrimitiveType)) return null;
+    
+    if (varType == PsiType.FLOAT || varType == PsiType.DOUBLE) return null;
 
     double minValue = varType == PsiType.BYTE ? Byte.MIN_VALUE :
                       varType == PsiType.SHORT ? Short.MIN_VALUE :
                       varType == PsiType.INT ? Integer.MIN_VALUE :
                       varType == PsiType.CHAR ? Character.MIN_VALUE :
-                      varType == PsiType.LONG ? Long.MIN_VALUE :
-                      varType == PsiType.FLOAT ? Float.MIN_VALUE :
-                      Double.MIN_VALUE;
+                      Long.MIN_VALUE;
     double maxValue = varType == PsiType.BYTE ? Byte.MAX_VALUE :
                       varType == PsiType.SHORT ? Short.MAX_VALUE :
                       varType == PsiType.INT ? Integer.MAX_VALUE :
                       varType == PsiType.CHAR ? Character.MAX_VALUE :
-                      varType == PsiType.LONG ? Long.MAX_VALUE :
-                      varType == PsiType.FLOAT ? Float.MAX_VALUE :
-                      Double.MAX_VALUE;
+                      Long.MAX_VALUE;
 
     return checkComparisonWithKnownRange(instruction, runner, memState, opSign, comparedWith, minValue, maxValue);
   }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
index 0a914c0..8c9e4a7 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,6 @@
 import com.intellij.codeInspection.XmlSuppressableInspectionTool;
 import com.intellij.codeInspection.deprecation.DeprecationInspection;
 import com.intellij.psi.*;
-import com.intellij.psi.xml.XmlAttribute;
 import com.intellij.psi.xml.XmlAttributeValue;
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.util.ArrayUtil;
@@ -46,11 +45,6 @@
       }
 
       @Override
-      public void visitXmlAttribute(XmlAttribute attribute) {
-        checkReferences(attribute, holder);
-      }
-
-      @Override
       public void visitXmlAttributeValue(XmlAttributeValue value) {
         checkReferences(value, holder);
       }
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
index b60094f..ad53d94 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
@@ -138,8 +138,8 @@
     qualifiedWithField,
     qualifiedWithGetter,
     superMethodParameters,
-    expectedTypeConstant,
     field,
+    expectedTypeConstant,
     getter,
     normal,
     collectionFactory,
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
index ff85137..4ab9d43 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
@@ -69,10 +69,14 @@
     if (element == null || !element.isValid()) {
       return false;
     }
+    return getOrFindCandidates().size() != 0;
+  }
+
+  private synchronized List<PsiVariable> getOrFindCandidates() {
     if (myCandidates == null) {
       findCandidates();
     }
-    return myCandidates.size() != 0;
+    return myCandidates;
   }
 
   private void findCandidates() {
@@ -84,6 +88,9 @@
     }
 
     for (final PsiVariable var : CreateFromUsageUtils.guessMatchingVariables(methodCallElement)) {
+      if (var.getName() == null) {
+        continue;
+      }
       final PsiType type = var.getType();
       if (!(type instanceof PsiClassType)) {
         continue;
@@ -132,7 +139,7 @@
         @NotNull
         @Override
         public String getTextFor(final PsiVariable value) {
-          return ObjectUtils.assertNotNull(value.getName());
+          return value.getName();
         }
 
         @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java
new file mode 100644
index 0000000..421c43c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.psi.PsiAnonymousClass;
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public class AnonymousTargetClassPreselectionUtil {
+  private static final String PRESELECT_ANONYMOUS = "create.member.preselect.anonymous";
+
+  public static void rememberSelection(PsiClass aClass, PsiClass firstClass) {
+    if (firstClass instanceof PsiAnonymousClass) {
+      PropertiesComponent.getInstance().setValue(PRESELECT_ANONYMOUS, String.valueOf(aClass == firstClass));
+    }
+  }
+
+  @Nullable
+  public static PsiClass getPreselection(Collection<PsiClass> classes, PsiClass firstClass) {
+    if (firstClass instanceof PsiAnonymousClass && !PropertiesComponent.getInstance().getBoolean(PRESELECT_ANONYMOUS, true)) {
+      for (PsiClass aClass : classes) {
+        if (!(aClass instanceof PsiAnonymousClass)) {
+          return aClass;
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
index 09b83e2..abe9368 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
@@ -119,7 +119,8 @@
   protected abstract PsiElement getElement();
 
   private void chooseTargetClass(List<PsiClass> classes, final Editor editor) {
-    final Project project = classes.get(0).getProject();
+    final PsiClass firstClass = classes.get(0);
+    final Project project = firstClass.getProject();
 
     final JList list = new JBList(classes);
     PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
@@ -128,12 +129,18 @@
     final PopupChooserBuilder builder = new PopupChooserBuilder(list);
     renderer.installSpeedSearch(builder);
 
+    final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, firstClass);
+    if (preselection != null) {
+      list.setSelectedValue(preselection, true);
+    }
+
     Runnable runnable = new Runnable() {
       @Override
       public void run() {
         int index = list.getSelectedIndex();
         if (index < 0) return;
         final PsiClass aClass = (PsiClass) list.getSelectedValue();
+        AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, firstClass);
         CommandProcessor.getInstance().executeCommand(project, new Runnable() {
           @Override
           public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
index 906dfa6..e699173 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
@@ -144,6 +144,17 @@
                                                                            RangeMarker bounds,
                                                                            ReferenceData[] referenceData);
 
+  protected PsiElement resolveReferenceIgnoreOverriding(PsiPolyVariantReference reference) {
+    PsiElement referent = reference.resolve();
+    if (referent == null) {
+      final ResolveResult[] results = reference.multiResolve(true);
+      if (results.length > 0) {
+        referent = results[0].getElement();
+      }
+    }
+    return referent;
+  }
+
   protected abstract void restoreReferences(ReferenceData[] referenceData,
                                             TRef[] refs);
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
index 51edddd..76be78b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
@@ -88,7 +88,8 @@
           }
           else {
             if (reference instanceof PsiReferenceExpression) {
-              PsiElement referent = reference.resolve();
+              PsiElement referent = resolveReferenceIgnoreOverriding(reference);
+
               if (!(referent instanceof PsiNamedElement)
                   || !data.staticMemberName.equals(((PsiNamedElement)referent).getName())
                   || !(referent instanceof PsiMember)
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
index 1d4d281..08e0628 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
@@ -36,7 +36,7 @@
     final Document doc = editor.getDocument();
 
     PsiCodeBlock body = catchSection.getCatchBlock();
-    if (body != null && startLine(doc, body) == startLine(doc, catchSection)) return;
+    if (body != null && body.getLBrace() != null && body.getRBrace() != null) return;
 
     final PsiJavaToken rParenth = catchSection.getRParenth();
     if (rParenth == null) return;
@@ -44,7 +44,4 @@
     doc.insertString(rParenth.getTextRange().getEndOffset(), "{}");
   }
 
-  private static int startLine(Document doc, PsiElement psiElement) {
-    return doc.getLineNumber(psiElement.getTextRange().getStartOffset());
-  }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
index 6bafcc0..884442c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
@@ -83,6 +83,22 @@
 
   @Nullable
   private static PsiCodeBlock getControlStatementBlock(int caret, PsiElement element) {
+    if (element instanceof PsiTryStatement) {
+      PsiCodeBlock tryBlock = ((PsiTryStatement)element).getTryBlock();
+      if (tryBlock != null && caret < tryBlock.getTextRange().getEndOffset()) return tryBlock;
+
+      for (PsiCodeBlock catchBlock : ((PsiTryStatement)element).getCatchBlocks()) {
+        if (catchBlock != null && caret < catchBlock.getTextRange().getEndOffset()) return catchBlock;
+      }
+
+      return ((PsiTryStatement)element).getFinallyBlock();
+    }
+
+    if (element instanceof PsiMethod) {
+      PsiCodeBlock methodBody = ((PsiMethod)element).getBody();
+      if (methodBody != null) return methodBody;
+    }
+
     PsiStatement body = null;
     if (element instanceof PsiIfStatement) {
       body =  ((PsiIfStatement)element).getThenBranch();
@@ -102,10 +118,6 @@
     else if (element instanceof PsiDoWhileStatement) {
       body =  ((PsiDoWhileStatement)element).getBody();
     }
-    else if (element instanceof PsiMethod) {
-      PsiCodeBlock methodBody = ((PsiMethod)element).getBody();
-      if (methodBody != null) return methodBody;
-    }
 
     return body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : null;
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
index fd85d11..daf2e30 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
@@ -450,18 +450,24 @@
       final PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
       if (element != null) {
         final PsiElement resolved = element.resolve();
-        if (resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiClass)resolved, "java.lang.annotation.Documented", false)) continue;
+        if (resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiClass)resolved, "java.lang.annotation.Documented", false, true)) {
+          continue;
+        }
 
         String referenceName = element.getReferenceName();
-        if (!shownAnnotations.add(referenceName)) continue;
-
-        if (lastSize != buffer.length()) buffer.append(" ");
-        buffer.append("@").append(referenceName);
+        if (shownAnnotations.add(referenceName) || isRepeatableAnnotation(resolved)) {
+          if (lastSize != buffer.length()) buffer.append(" ");
+          buffer.append("@").append(referenceName);
+        }
       }
     }
     if (lastSize != buffer.length()) buffer.append(" ");
   }
 
+  private static boolean isRepeatableAnnotation(PsiElement resolved) {
+    return resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiModifierListOwner)resolved, CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE, false, true);
+  }
+
   @Override
   public void updateUI(final Object p, @NotNull final ParameterInfoUIContext context) {
     if (p instanceof CandidateInfo) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
index ccec3c3..37fb882 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
@@ -187,14 +187,14 @@
     modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
 
     final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
-    final String nullable = manager.getNullable(parameter);
-    if (nullable != null) {
-      modifierList.addAfter(factory.createAnnotationFromText("@" + nullable, field), null);
+    final PsiAnnotation nullable = manager.getNullableAnnotation(parameter, false);
+    if (nullable != null && !manager.isContainerAnnotation(nullable)) {
+      modifierList.addAfter(factory.createAnnotationFromText("@" + nullable.getQualifiedName(), field), null);
     }
     else if (isFinal) {
-      final String notNull = manager.getNotNull(parameter);
-      if (notNull != null) {
-        modifierList.addAfter(factory.createAnnotationFromText("@" + notNull, field), null);
+      final PsiAnnotation notNull = manager.getNotNullAnnotation(parameter, false);
+      if (notNull != null && !manager.isContainerAnnotation(notNull)) {
+        modifierList.addAfter(factory.createAnnotationFromText("@" + notNull.getQualifiedName(), field), null);
       }
     }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
index 952987a..1405917 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
@@ -20,13 +20,17 @@
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
 
-public class CastExpressionPostfixTemplate extends JavaPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
+public class CastExpressionPostfixTemplate extends PostfixTemplateWithExpressionSelector {
   public CastExpressionPostfixTemplate() {
-    super("cast", "((SomeType) expr)");
+    super("cast", "((SomeType) expr)", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
   }
 
   @Override
-  protected void doIt(@NotNull final Editor editor, @NotNull final PsiElement expression) {
+  protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
     PostfixTemplatesUtils.surround(new JavaWithCastSurrounder(), editor, expression);
   }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
index 40da7fd..2bac79d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
@@ -23,13 +23,17 @@
 import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
 import org.jetbrains.annotations.NotNull;
 
-public class IntroduceFieldPostfixTemplate extends JavaPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
+public class IntroduceFieldPostfixTemplate extends PostfixTemplateWithExpressionSelector {
   public IntroduceFieldPostfixTemplate() {
-    super("field", "myField = expr");
+    super("field", "myField = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
   }
 
   @Override
-  protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
+  protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
     IntroduceFieldHandler handler =
       ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler(expression) : new IntroduceFieldHandler();
     handler.invoke(expression.getProject(), new PsiElement[]{expression}, null);
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
index 57c03f9..be2dc23 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
@@ -28,14 +28,18 @@
 import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
 import org.jetbrains.annotations.NotNull;
 
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
 // todo: support for int[].var (parses as .class access!)
-public class IntroduceVariablePostfixTemplate extends JavaPostfixTemplateWithChooser {
+public class IntroduceVariablePostfixTemplate extends PostfixTemplateWithExpressionSelector {
   public IntroduceVariablePostfixTemplate() {
-    super("var", "T name = expr");
+    super("var", "T name = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
   }
 
   @Override
-  protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
+  protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
     // for advanced stuff use ((PsiJavaCodeReferenceElement)expression).advancedResolve(true).getElement();
     IntroduceVariableHandler handler =
       ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler() : new IntroduceVariableHandler();
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
index 148f4bb..629d4dd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
@@ -144,6 +144,6 @@
   }
 
   private static boolean isSemicolonNeeded(@NotNull PsiFile file, @NotNull Editor editor) {
-    return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor));
+    return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor.getCaretModel().getCurrentCaret()));
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java
deleted file mode 100644
index 72de706..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-
-import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
-
-public abstract class JavaPostfixTemplateWithChooser extends ExpressionPostfixTemplateWithChooser {
-
-
-  protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String example) {
-    super(name, example, JAVA_PSI_INFO);
-  }
-
-  protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String key, @NotNull String example) {
-    super(name, key, example, JAVA_PSI_INFO);
-  }
-
-  @NotNull
-  @Override
-  protected Condition<PsiElement> getTypeCondition() {
-    return JavaPostfixTemplatesUtils.IS_NON_VOID;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
index ac6f22c..6160433 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
@@ -15,26 +15,16 @@
  */
 package com.intellij.codeInsight.template.postfix.templates;
 
-import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN;
 import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
 
 public class NotExpressionPostfixTemplate extends NotPostfixTemplate {
 
   public NotExpressionPostfixTemplate() {
-    super(JAVA_PSI_INFO);
+    super(JAVA_PSI_INFO, IS_BOOLEAN);
   }
 
   public NotExpressionPostfixTemplate(String alias) {
-    super(alias, alias, "!expr", JAVA_PSI_INFO);
-  }
-
-  @NotNull
-  @Override
-  protected Condition<PsiElement> getTypeCondition() {
-    return JavaPostfixTemplatesUtils.IS_BOOLEAN;
+    super(alias, alias, "!expr", JAVA_PSI_INFO, IS_BOOLEAN);
   }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
index 68b5c48..46c0c30 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
@@ -15,21 +15,11 @@
  */
 package com.intellij.codeInsight.template.postfix.templates;
 
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
 import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
 import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
 
 public class ParenthesizedExpressionPostfixTemplate extends ParenthesizedPostfixTemplate {
   public ParenthesizedExpressionPostfixTemplate() {
-    super(JAVA_PSI_INFO);
-  }
-
-  @NotNull
-  @Override
-  protected Condition<PsiElement> getTypeCondition() {
-    return IS_NON_VOID;
+    super(JAVA_PSI_INFO, IS_NON_VOID);
   }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
index e217175..2142c8f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
@@ -16,7 +16,7 @@
 package com.intellij.codeInsight.template.postfix.util;
 
 import com.intellij.codeInsight.CodeInsightServicesUtil;
-import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfoBase;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.util.Condition;
 import com.intellij.psi.*;
@@ -36,7 +36,7 @@
   private JavaPostfixTemplatesUtils() {
   }
 
-  public static final PostfixTemplatePsiInfoBase JAVA_PSI_INFO = new PostfixTemplatePsiInfoBase() {
+  public static final PostfixTemplatePsiInfo JAVA_PSI_INFO = new PostfixTemplatePsiInfo() {
 
     @NotNull
     @Override
@@ -136,7 +136,11 @@
 
   @Contract("null -> false")
   public static boolean isNotPrimitiveTypeExpression(@Nullable PsiExpression expression) {
-    return expression != null && !(expression.getType() instanceof PsiPrimitiveType);
+    if (expression == null) {
+      return false;
+    }
+    PsiType type = expression.getType();
+    return type != null && !(type instanceof PsiPrimitiveType);
   }
 
   @Contract("null -> false")
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
index aff69ec..b3aed06 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
@@ -194,7 +194,7 @@
     final SearchScope searchScope = new GlobalSearchScope(refManager.getProject()) {
       @Override
       public boolean contains(@NotNull VirtualFile file) {
-        return !scope.contains(file) || file.getFileType() != StdFileTypes.JAVA;
+        return scope != null && !scope.contains(file) || file.getFileType() != StdFileTypes.JAVA;
       }
 
       @Override
@@ -394,7 +394,7 @@
       @Override
       public boolean execute(PsiReference reference) {
         AnalysisScope scope = context.getRefManager().getScope();
-        if (scope.contains(reference.getElement()) && reference.getElement().getLanguage() == StdLanguages.JAVA ||
+        if (scope != null && scope.contains(reference.getElement()) && reference.getElement().getLanguage() == StdLanguages.JAVA ||
             PsiTreeUtil.getParentOfType(reference.getElement(), PsiDocComment.class) != null) {
           return true;
         }
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 baab93d..bcfea46 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -76,7 +76,7 @@
     public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
       final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
-      LOG.assertTrue(method != null);
+      if (method == null) return;
       PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
       if (parameter == null) {
         final PsiParameter[] parameters = method.getParameterList().getParameters();
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
index c33d0d6..bb97f5c 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
@@ -132,7 +132,7 @@
                   int idx = refParameter.getIndex();
                   final boolean[] found = {false};
                   for (int i = 0; i < derived.length && !found[0]; i++) {
-                    if (!scope.contains(derived[i])) {
+                    if (scope == null || !scope.contains(derived[i])) {
                       final PsiParameter[] parameters = derived[i].getParameterList().getParameters();
                       if (parameters.length >= idx) continue;
                       PsiParameter psiParameter = parameters[idx];
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 38ee744..51beb42 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
@@ -63,7 +63,7 @@
     @Override
     protected PsiElement moveDeclaration(@NotNull final Project project, @NotNull final PsiField variable) {
       final Map<PsiCodeBlock, Collection<PsiReference>> refs = new HashMap<PsiCodeBlock, Collection<PsiReference>>();
-      groupByCodeBlocks(ReferencesSearch.search(variable).findAll(), refs);
+      if (!groupByCodeBlocks(ReferencesSearch.search(variable).findAll(), refs)) return null;
       PsiElement element = null;
       for (Collection<PsiReference> psiReferences : refs.values()) {
         element = super.moveDeclaration(project, variable, psiReferences, false);
@@ -82,11 +82,14 @@
       return element;
     }
 
-    private static void groupByCodeBlocks(final Collection<PsiReference> allReferences, Map<PsiCodeBlock, Collection<PsiReference>> refs) {
+    private static boolean groupByCodeBlocks(final Collection<PsiReference> allReferences, Map<PsiCodeBlock, Collection<PsiReference>> refs) {
       for (PsiReference psiReference : allReferences) {
         final PsiElement element = psiReference.getElement();
         final PsiCodeBlock block = PsiTreeUtil.getTopmostParentOfType(element, PsiCodeBlock.class);
-        LOG.assertTrue(block != null);
+        if (block == null) {
+          return false;
+        }
+        
         Collection<PsiReference> references = refs.get(block);
         if (references == null) {
           references = new ArrayList<PsiReference>();
@@ -95,6 +98,7 @@
         }
         references.add(psiReference);
       }
+      return true;
     }
 
     private static boolean findExistentBlock(Map<PsiCodeBlock, Collection<PsiReference>> refs,
diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
index 98f1fbe..73fcc83 100644
--- a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
+++ b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
@@ -28,9 +28,7 @@
 import com.intellij.ide.impl.PackagesPaneSelectInTarget;
 import com.intellij.ide.projectView.ProjectView;
 import com.intellij.ide.projectView.ViewSettings;
-import com.intellij.ide.projectView.impl.nodes.PackageElement;
-import com.intellij.ide.projectView.impl.nodes.PackageUtil;
-import com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode;
+import com.intellij.ide.projectView.impl.nodes.*;
 import com.intellij.ide.util.DeleteHandler;
 import com.intellij.ide.util.treeView.AbstractTreeBuilder;
 import com.intellij.ide.util.treeView.AbstractTreeNode;
@@ -48,8 +46,8 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiPackage;
 import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -140,14 +138,30 @@
 
   @Override
   public PsiDirectory[] getSelectedDirectories() {
-    final PackageElement packageElement = getSelectedPackageElement();
-    if (packageElement != null) {
-      final Module module = packageElement.getModule();
-      final PsiPackage aPackage = packageElement.getPackage();
-      if (module != null && aPackage != null) {
-        return aPackage.getDirectories(GlobalSearchScope.moduleScope(module));
+    List<PsiDirectory> directories = ContainerUtil.newArrayList();
+    for (PackageElementNode node : getSelectedNodes(PackageElementNode.class)) {
+      PackageElement packageElement = node.getValue();
+      PsiPackage aPackage = packageElement != null ? packageElement.getPackage() : null;
+      final Module module = packageElement != null ? packageElement.getModule() : null;
+      if (aPackage != null && module != null) {
+        GlobalSearchScope scope = GlobalSearchScope.moduleScope(module);
+        Collections.addAll(directories, aPackage.getDirectories(scope));
+
+        Object parentValue = node.getParent().getValue();
+        PsiPackage parentNodePackage = parentValue instanceof PackageElement ? ((PackageElement)parentValue).getPackage() : null;
+        while (true) {
+          aPackage = aPackage.getParentPackage();
+          if (aPackage == null || aPackage.getQualifiedName().isEmpty() || aPackage.equals(parentNodePackage)) {
+            break;
+          }
+          Collections.addAll(directories, aPackage.getDirectories(scope));
+        }
       }
     }
+    if (!directories.isEmpty()) {
+      return directories.toArray(new PsiDirectory[directories.size()]);
+    }
+
     return super.getSelectedDirectories();
   }
 
diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
index b0cbc06..2f54186 100644
--- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
+++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
@@ -19,10 +19,14 @@
 import com.intellij.navigation.GotoClassContributor;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
+import com.intellij.psi.codeStyle.NameUtil;
 import com.intellij.psi.presentation.java.SymbolPresentationUtil;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.psi.util.ClassUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.CommonProcessors;
 import com.intellij.util.Processor;
@@ -32,6 +36,8 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.regex.Matcher;
+
 public class DefaultClassNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor {
   @Override
   @NotNull
@@ -74,7 +80,7 @@
 
   @Override
   public String getQualifiedNameSeparator() {
-    return ".";
+    return "$";
   }
 
   @Override
@@ -86,12 +92,28 @@
   public void processElementsWithName(@NotNull String name,
                                       @NotNull final Processor<NavigationItem> processor,
                                       @NotNull final FindSymbolParameters parameters) {
+    String namePattern = StringUtil.getShortName(parameters.getCompletePattern());
+    boolean hasDollar = namePattern.contains("$");
+    if (hasDollar) {
+      Matcher matcher = ChooseByNamePopup.patternToDetectAnonymousClasses.matcher(namePattern);
+      if (matcher.matches()) {
+        namePattern = matcher.group(1);
+        hasDollar = namePattern.contains("$");
+      }
+    }
+    final MinusculeMatcher innerMatcher = hasDollar ? new MinusculeMatcher("*" + namePattern, NameUtil.MatchingCaseSensitivity.NONE) : null;
     PsiShortNamesCache.getInstance(parameters.getProject()).processClassesWithName(name, new Processor<PsiClass>() {
       final boolean isAnnotation = parameters.getLocalPatternName().startsWith("@");
+
       @Override
       public boolean process(PsiClass aClass) {
         if (aClass.getContainingFile().getVirtualFile() == null || !aClass.isPhysical()) return true;
         if (isAnnotation && !aClass.isAnnotationType()) return true;
+        if (innerMatcher != null) {
+          if (aClass.getContainingClass() == null) return true;
+          String jvmQName = ClassUtil.getJVMClassName(aClass);
+          if (jvmQName == null || !innerMatcher.matches(StringUtil.getShortName(jvmQName))) return true;
+        }
         return processor.process(aClass);
       }
     }, parameters.getSearchScope(), parameters.getIdFilter());
diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
index adbacfc..c825d83 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
@@ -15,16 +15,12 @@
  */
 package com.intellij.openapi.roots.impl;
 
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.CompilerModuleExtension;
 import com.intellij.openapi.roots.CompilerProjectExtension;
 import com.intellij.openapi.roots.ModuleRootModel;
-import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
-import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
@@ -40,26 +36,6 @@
     myProject = project;
   }
 
-  @Override
-  public boolean isExcludeRoot(final VirtualFile file) {
-    CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(myProject);
-    if (isEqualWithFileOrUrl(file, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
-
-    for (Module m : ModuleManager.getInstance(myProject).getModules()) {
-      CompilerModuleExtension rm = CompilerModuleExtension.getInstance(m);
-      if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
-      if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
-    }
-    return false;
-  }
-
-  @Override
-  public boolean isExcludeRootForModule(@NotNull final Module module, final VirtualFile excludeRoot) {
-    final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
-    return Comparing.equal(compilerModuleExtension.getCompilerOutputPath(), excludeRoot) ||
-           Comparing.equal(compilerModuleExtension.getCompilerOutputPathForTests(), excludeRoot);
-  }
-
   @NotNull
   @Override
   public VirtualFile[] getExcludeRootsForProject() {
@@ -88,14 +64,4 @@
     }
     return result.isEmpty() ? VirtualFilePointer.EMPTY_ARRAY : result.toArray(new VirtualFilePointer[result.size()]);
   }
-
-  private static boolean isEqualWithFileOrUrl(VirtualFile file, VirtualFile fileToCompareWith, String url) {
-    if (fileToCompareWith != null) {
-      if (Comparing.equal(fileToCompareWith, file)) return true;
-    }
-    else if (url != null) {
-      if (FileUtil.pathsEqual(url, file.getUrl())) return true;
-    }
-    return false;
-  }
 }
diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
index 3651fa1..ff1170b 100644
--- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
@@ -280,6 +280,7 @@
         if (ref instanceof PsiField && containingClassFields.contains(ref)) {
           referencedElements.add((PsiField)ref);
         }
+        super.visitReferenceExpression(expression);
       }
     });
 
diff --git a/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java b/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
index a8316f8..eaa9387 100644
--- a/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
@@ -18,6 +18,7 @@
 import com.intellij.lang.LanguageParserDefinitions;
 import com.intellij.lang.ParserDefinition;
 import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.impl.EditorHighlighterCache;
 import com.intellij.psi.JspPsiUtil;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.impl.source.tree.StdTokenSets;
@@ -34,7 +35,7 @@
   @Override
   public Lexer getIndexingLexer(@NotNull final PsiFile file) {
     if (JspPsiUtil.isInJspFile(file)) {
-      return LexerEditorHighlighterLexer.getLexerBasedOnLexerHighlighter(file.getText(), file.getVirtualFile(), file.getProject());
+      return EditorHighlighterCache.getLexerBasedOnLexerHighlighter(file.getText(), file.getVirtualFile(), file.getProject());
     }
 
     return null;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
index 827a3d1..5380043 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
@@ -142,9 +142,7 @@
   @NotNull
   public static Collection<PsiFileSystemItem> getRoots(final Module thisModule, boolean includingClasses) {
     if (thisModule == null) return Collections.emptyList();
-    Set<Module> modules = new com.intellij.util.containers.HashSet<Module>();
     ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(thisModule);
-    ModuleUtilCore.getDependencies(thisModule, modules);
     List<PsiFileSystemItem> result = new ArrayList<PsiFileSystemItem>();
     final PsiManager psiManager = PsiManager.getInstance(thisModule.getProject());
     if (includingClasses) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
index f7dc89c..307d608 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
@@ -16,7 +16,6 @@
 package com.intellij.psi.impl.source.resolve.reference.impl.providers;
 
 import com.intellij.psi.*;
-import com.intellij.psi.jsp.JspImplicitVariable;
 import com.intellij.psi.jsp.JspSpiUtil;
 import com.intellij.psi.util.PropertyUtil;
 import com.intellij.psi.xml.XmlAttribute;
@@ -62,8 +61,8 @@
           }
         } else if (psiElement instanceof PsiClass) {
           return (PsiClass)psiElement;
-        } else if (psiElement instanceof JspImplicitVariable) {
-          final PsiType type=((JspImplicitVariable)psiElement).getType();
+        } else if (psiElement instanceof PsiVariable) {
+          final PsiType type=((PsiVariable)psiElement).getType();
           if (type instanceof PsiClassType) {
             return ((PsiClassType)type).resolve();
           }
diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
index 7bca3c0..8020155 100644
--- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
@@ -86,20 +86,23 @@
     final String[] names;
     String name = myAnonClass.getBaseClassReference().getReferenceName();
     PsiType[] typeParameters = myAnonClass.getBaseClassReference().getTypeParameters();
-    if (typeParameters.length > 0) {
-      names = new String[]{StringUtil.join(typeParameters, new Function<PsiType, String>() {
-        public String fun(PsiType psiType) {
-          PsiType type = psiType;
-          if (psiType instanceof PsiClassType) {
-            type = TypeConversionUtil.erasure(psiType);
-          }
-          if (type == null || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return "";
-          if (type instanceof PsiArrayType) {
-            type = type.getDeepComponentType();
-          }
-          return StringUtil.getShortName(type.getPresentableText());
+
+    final String typeParamsList = StringUtil.join(typeParameters, new Function<PsiType, String>() {
+      public String fun(PsiType psiType) {
+        PsiType type = psiType;
+        if (psiType instanceof PsiClassType) {
+          type = TypeConversionUtil.erasure(psiType);
         }
-      }, "") + name, "My" + name};
+        if (type == null || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return "";
+        if (type instanceof PsiArrayType) {
+          type = type.getDeepComponentType();
+        }
+        return StringUtil.getShortName(type.getPresentableText());
+      }
+    }, "") + name;
+
+    if (!typeParamsList.equals(name)) {
+      names = new String[]{typeParamsList, "My" + name};
     } else {
       names = new String[]{"My" + name};
     }
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
index 75544f9..ce52274 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
@@ -19,6 +19,7 @@
 import com.intellij.codeInsight.ExceptionUtil;
 import com.intellij.codeInsight.NullableNotNullManager;
 import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
 import com.intellij.codeInsight.highlighting.HighlightManager;
 import com.intellij.codeInsight.intention.impl.AddNullableAnnotationFix;
 import com.intellij.codeInsight.navigation.NavigationUtil;
@@ -1133,6 +1134,7 @@
       final PsiElementProcessor<PsiClass> processor = new PsiElementProcessor<PsiClass>() {
         @Override
         public boolean execute(@NotNull PsiClass selectedClass) {
+          AnonymousTargetClassPreselectionUtil.rememberSelection(selectedClass, myTargetClass);
           final List<PsiVariable> array = classes.get(selectedClass);
           myNeedChangeContext = myTargetClass != selectedClass;
           myTargetClass = selectedClass;
@@ -1184,7 +1186,9 @@
 
       if (classes.size() > 1) {
         final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
-        NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose Destination Class", processor).showInBestPositionFor(myEditor);
+        final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes.keySet(), psiClasses[0]);
+        NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose Destination Class", processor, preselection)
+          .showInBestPositionFor(myEditor);
         return true;
       }
     }
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
index a751ace..7547395 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
@@ -27,6 +27,7 @@
 import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.ChangeContextUtil;
 import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
 import com.intellij.codeInsight.highlighting.HighlightManager;
 import com.intellij.codeInsight.lookup.LookupManager;
 import com.intellij.codeInsight.navigation.NavigationUtil;
@@ -129,18 +130,13 @@
       return !convertExpressionToField(selectedExpr, editor, file, project, tempType);
     }
     else {
-      PsiClass selection = null;
-      for (PsiClass psiClass : classes) {
-        if (!(psiClass instanceof PsiAnonymousClass)) {
-          selection = psiClass;
-          break;
-        }
-      }
+      PsiClass selection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, myParentClass);
       NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(),
                                         "Choose class to introduce " + (myIsConstant ? "constant" : "field"),
                                         new PsiElementProcessor<PsiClass>() {
                                           @Override
                                           public boolean execute(@NotNull PsiClass aClass) {
+                                            AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, myParentClass);
                                             myParentClass = aClass;
                                             convertExpressionToField(selectedExpr, editor, file, project, tempType);
                                             return false;
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
index 5b5c39f..0b31eed 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
@@ -18,6 +18,7 @@
 import com.intellij.codeInsight.ChangeContextUtil;
 import com.intellij.codeInsight.CodeInsightUtil;
 import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
 import com.intellij.codeInsight.navigation.NavigationUtil;
 import com.intellij.ide.util.PsiClassListCellRenderer;
 import com.intellij.openapi.application.ApplicationManager;
@@ -66,7 +67,7 @@
   public boolean convertLocalToField(final PsiLocalVariable local, final Editor editor) {
     boolean tempIsStatic = myIsConstant;
     PsiElement parent = local.getParent();
-    List<PsiClass> classes = new ArrayList<PsiClass>();
+    final List<PsiClass> classes = new ArrayList<PsiClass>();
     while (parent != null && parent.getContainingFile() != null) {
       if (parent instanceof PsiClass && !(myIsConstant && parent instanceof PsiAnonymousClass)) {
         classes.add((PsiClass)parent);
@@ -90,13 +91,16 @@
       if (convertLocalToField(local, classes.get(getChosenClassIndex(classes)), editor, tempIsStatic)) return false;
     } else {
       final boolean isStatic = tempIsStatic;
+      final PsiClass firstClass = classes.get(0);
+      final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, firstClass);
       NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor<PsiClass>() {
         @Override
         public boolean execute(@NotNull PsiClass aClass) {
+          AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, aClass);
           convertLocalToField(local, aClass, editor, isStatic);
           return false;
         }
-      }).showInBestPositionFor(editor);
+      }, preselection).showInBestPositionFor(editor);
     }
 
     return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
index c410d76..f09da83 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
@@ -210,10 +210,16 @@
           if (element instanceof PsiReferenceExpression) {
             if (((PsiReferenceExpression)element).resolve() == methodToRename) {
               final PsiElement parent = element.getParent();
-              LOG.assertTrue(parent instanceof PsiMethodCallExpression, parent.getText());
-              final PsiMethodCallExpression copy = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(element.getProject())
-                .createExpressionFromText(parent.getText(), element);
-              final PsiReferenceExpression expression = (PsiReferenceExpression)processRef(copy.getMethodExpression(), newName);
+              final PsiReferenceExpression copyRef;
+              if (parent instanceof PsiMethodCallExpression) {
+                final PsiMethodCallExpression copy = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(element.getProject())
+                  .createExpressionFromText(parent.getText(), element);
+                copyRef = copy.getMethodExpression();
+              } else {
+                LOG.assertTrue(element instanceof PsiMethodReferenceExpression, element.getText());
+                copyRef = (PsiReferenceExpression)element.copy();
+              }
+              final PsiReferenceExpression expression = (PsiReferenceExpression)processRef(copyRef, newName);
               if (expression == null) continue;
               final JavaResolveResult resolveResult = expression.advancedResolve(true);
               final PsiMember resolveResultElement = (PsiMember)resolveResult.getElement();
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index f2ac34e..ca01331 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -617,7 +617,7 @@
     Project project = expr.getProject();
     String[] suggestedNames =
       JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, expr, null).names;
-    final String prefix = suggestedNames[0];
+    final String prefix = suggestedNames.length > 0 ? suggestedNames[0] : "var";
     final String id = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName(prefix, context, true);
 
     PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory();
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
index b34d28e..ee8bcf0 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
@@ -20,19 +20,15 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiMethod;
-import com.intellij.refactoring.ui.MemberSelectionPanel;
+import com.intellij.psi.*;
 import com.intellij.refactoring.ui.MemberSelectionTable;
 import com.intellij.refactoring.util.classMembers.MemberInfo;
 import com.intellij.testIntegration.TestFramework;
 import com.intellij.testIntegration.TestIntegrationUtils;
 import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.SeparatorFactory;
 import com.intellij.ui.components.JBCheckBox;
 import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nullable;
 
@@ -40,8 +36,10 @@
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 public class MissedTestsDialog extends DialogWrapper {
   private final PsiClass mySourceClass;
@@ -85,9 +83,7 @@
 
   private void disableMethodsWithTests(List<MemberInfo> info) {
     final Set<String> existingNames = new HashSet<String>();
-    final Template template = TestIntegrationUtils
-      .createTestMethodTemplate(TestIntegrationUtils.MethodKind.TEST, myDescriptor, myTestClass, null, true, existingNames);
-    final String prefix = JavaPsiFacade.getElementFactory(myTestClass.getProject()).createMethodFromText(template.getTemplateText(), myTestClass).getName();
+    final String prefix = getTestPrefix(existingNames);
 
     existingNames.addAll(ContainerUtil.map(myTestClass.getMethods(), new Function<PsiMethod, String>() {
       @Override
@@ -103,6 +99,16 @@
     }
   }
 
+  private String getTestPrefix(Set<String> existingNames) {
+    final Template template = TestIntegrationUtils.createTestMethodTemplate(TestIntegrationUtils.MethodKind.TEST, myDescriptor, myTestClass, null, true, existingNames);
+    try {
+      return JavaPsiFacade.getElementFactory(myTestClass.getProject()).createMethodFromText(template.getTemplateText(), myTestClass).getName();
+    }
+    catch (IncorrectOperationException e) {
+      return "";
+    }
+  }
+
   private void updateMethodsTable() {
     List<MemberInfo> infos = TestIntegrationUtils.extractClassMethods(mySourceClass, myIncludeInheritedCb.isSelected());
 
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
index 445a8aa..93b9737 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
@@ -70,7 +70,8 @@
             return UsageType.RECURSION;
           }
           if (qualifier != null && !(qualifier instanceof PsiThisExpression) && calledMethod != null) {
-            if (haveCommonSuperMethod(containerMethod, calledMethod)) {
+            if (Comparing.equal(containerMethod.getName(), calledMethod.getName()) &&
+                haveCommonSuperMethod(containerMethod, calledMethod)) {
               boolean parametersDelegated = parametersDelegated(containerMethod, callExpression);
 
               if (qualifier instanceof PsiSuperExpression) {
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java
new file mode 100644
index 0000000..c7d9e30
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author peter
+ */
+public class AnnotationTargetUtil {
+  public static final Set<PsiAnnotation.TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet(
+    PsiAnnotation.TargetType.PACKAGE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE,
+    PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.CONSTRUCTOR,
+    PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.LOCAL_VARIABLE));
+  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.AnnotationUtil");
+  private static final PsiAnnotation.TargetType[] PACKAGE_TARGETS = {PsiAnnotation.TargetType.PACKAGE};
+  private static final PsiAnnotation.TargetType[] TYPE_USE_TARGETS = {PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] ANNOTATION_TARGETS = {PsiAnnotation.TargetType.ANNOTATION_TYPE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] TYPE_TARGETS = {PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] TYPE_PARAMETER_TARGETS = {
+    PsiAnnotation.TargetType.TYPE_PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] CONSTRUCTOR_TARGETS = {PsiAnnotation.TargetType.CONSTRUCTOR, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] METHOD_TARGETS = {PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] FIELD_TARGETS = {PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] PARAMETER_TARGETS = {PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
+  private static final PsiAnnotation.TargetType[] LOCAL_VARIABLE_TARGETS ={
+    PsiAnnotation.TargetType.LOCAL_VARIABLE, PsiAnnotation.TargetType.TYPE_USE};
+
+  @NotNull
+  public static PsiAnnotation.TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
+    if (owner == null) {
+      return PsiAnnotation.TargetType.EMPTY_ARRAY;
+    }
+
+    if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
+      return TYPE_USE_TARGETS;
+    }
+
+    if (owner instanceof PsiTypeParameter) {
+      return TYPE_PARAMETER_TARGETS;
+    }
+
+    if (owner instanceof PsiModifierList) {
+      PsiElement element = ((PsiModifierList)owner).getParent();
+      if (element instanceof PsiPackageStatement) {
+        return PACKAGE_TARGETS;
+      }
+      if (element instanceof PsiClass) {
+        if (((PsiClass)element).isAnnotationType()) {
+          return ANNOTATION_TARGETS;
+        }
+        else {
+          return TYPE_TARGETS;
+        }
+      }
+      if (element instanceof PsiMethod) {
+        if (((PsiMethod)element).isConstructor()) {
+          return CONSTRUCTOR_TARGETS;
+        }
+        else {
+          return METHOD_TARGETS;
+        }
+      }
+      if (element instanceof PsiField) {
+        return FIELD_TARGETS;
+      }
+      if (element instanceof PsiParameter) {
+        return PARAMETER_TARGETS;
+      }
+      if (element instanceof PsiLocalVariable) {
+        return LOCAL_VARIABLE_TARGETS;
+      }
+    }
+
+    return PsiAnnotation.TargetType.EMPTY_ARRAY;
+  }
+
+  @Nullable
+  public static Set<PsiAnnotation.TargetType> extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) {
+    if (value instanceof PsiReference) {
+      PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)value);
+      if (targetType != null) {
+        return Collections.singleton(targetType);
+      }
+    }
+    else if (value instanceof PsiArrayInitializerMemberValue) {
+      Set <PsiAnnotation.TargetType> targets = ContainerUtil.newHashSet();
+      for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
+        if (initializer instanceof PsiReference) {
+          PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)initializer);
+          if (targetType != null) {
+            targets.add(targetType);
+          }
+        }
+      }
+      return targets;
+    }
+
+    return null;
+  }
+
+  @Nullable
+  private static PsiAnnotation.TargetType translateTargetRef(@NotNull PsiReference reference) {
+    PsiElement field = reference.resolve();
+    if (field instanceof PsiEnumConstant) {
+      String name = ((PsiEnumConstant)field).getName();
+      try {
+        return PsiAnnotation.TargetType.valueOf(name);
+      }
+      catch (IllegalArgumentException e) {
+        LOG.warn("Unknown target: " + name);
+      }
+    }
+    return null;
+  }
+}
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
index c2c79a9..25034e9 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
@@ -379,14 +379,14 @@
   @NotNull
   public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
                                                   boolean inHierarchy,
-                                                  Set<PsiModifierListOwner> visited) {
+                                                  @Nullable Set<PsiModifierListOwner> visited) {
     return getAllAnnotations(owner, inHierarchy, visited, true);
   }
 
   @NotNull
   public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
                                                   boolean inHierarchy,
-                                                  Set<PsiModifierListOwner> visited, boolean withInferred) {
+                                                  @Nullable Set<PsiModifierListOwner> visited, boolean withInferred) {
     final PsiModifierList list = owner.getModifierList();
     PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY;
     if (list != null) {
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
index 21e014e..2210e02 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
@@ -44,10 +44,13 @@
   public final JDOMExternalizableStringList myNullables = new JDOMExternalizableStringList();
   public final JDOMExternalizableStringList myNotNulls = new JDOMExternalizableStringList();
 
-  public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable",
+  private static final String JAVAX_ANNOTATION_NULLABLE = "javax.annotation.Nullable";
+  private static final String JAVAX_ANNOTATION_NONNULL = "javax.annotation.Nonnull";
+
+  public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, JAVAX_ANNOTATION_NULLABLE,
     "edu.umd.cs.findbugs.annotations.Nullable", "android.support.annotation.Nullable"
   };
-  public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull",
+  public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, JAVAX_ANNOTATION_NONNULL,
     "edu.umd.cs.findbugs.annotations.NonNull", "android.support.annotation.NonNull"
   };
 
@@ -103,6 +106,11 @@
     return findNullabilityAnnotation(owner, checkBases, true);
   }
 
+  public boolean isContainerAnnotation(@NotNull PsiAnnotation anno) {
+    PsiAnnotation.TargetType[] acceptAnyTarget = PsiAnnotation.TargetType.values();
+    return isNullabilityDefault(anno, true, acceptAnyTarget) || isNullabilityDefault(anno, false, acceptAnyTarget);
+  }
+      
   public void setDefaultNullable(@NotNull String defaultNullable) {
     LOG.assertTrue(getNullables().contains(defaultNullable));
     myDefaultNullable = defaultNullable;
@@ -138,15 +146,20 @@
       return annotation;
     }
 
-    if (owner instanceof PsiParameter && !TypeConversionUtil.isPrimitiveAndNotNull(((PsiParameter)owner).getType())) {
-      // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
-      if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
-        return null;
-      }
-      return findContainerAnnotation(owner, nullable
-                                            ? "javax.annotation.ParametersAreNullableByDefault"
-                                            : "javax.annotation.ParametersAreNonnullByDefault");
+    PsiType type = getOwnerType(owner);
+    if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null;
+
+    // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
+    if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
+      return null;
     }
+    return findNullabilityDefaultInHierarchy(owner, nullable);
+  }
+
+  @Nullable
+  private static PsiType getOwnerType(PsiModifierListOwner owner) {
+    if (owner instanceof PsiVariable) return ((PsiVariable)owner).getType();
+    if (owner instanceof PsiMethod) return ((PsiMethod)owner).getReturnType();
     return null;
   }
 
@@ -159,11 +172,13 @@
   }
 
   @Nullable 
-  private static PsiAnnotation findContainerAnnotation(PsiModifierListOwner owner, String annotationFQN) {
+  private static PsiAnnotation findNullabilityDefaultInHierarchy(PsiModifierListOwner owner, boolean nullable) {
+    PsiAnnotation.TargetType[] placeTargetTypes = AnnotationTargetUtil.getTargetsForLocation(owner.getModifierList());
+
     PsiElement element = owner.getParent();
     while (element != null) {
       if (element instanceof PsiModifierListOwner) {
-        PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiModifierListOwner)element, annotationFQN);
+        PsiAnnotation annotation = getNullabilityDefault((PsiModifierListOwner)element, nullable, placeTargetTypes);
         if (annotation != null) {
           return annotation;
         }
@@ -172,7 +187,7 @@
       if (element instanceof PsiClassOwner) {
         String packageName = ((PsiClassOwner)element).getPackageName();
         PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
-        return AnnotationUtil.findAnnotation(psiPackage, annotationFQN);
+        return psiPackage == null ? null : getNullabilityDefault(psiPackage, nullable, placeTargetTypes);
       }
 
       element = element.getContext();
@@ -180,6 +195,37 @@
     return null;
   }
 
+  private static PsiAnnotation getNullabilityDefault(@NotNull PsiModifierListOwner container, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) {
+    PsiModifierList modifierList = container.getModifierList();
+    if (modifierList == null) return null;
+    for (PsiAnnotation annotation : modifierList.getAnnotations()) {
+      if (isNullabilityDefault(annotation, nullable, placeTargetTypes)) {
+        return annotation;
+      }
+    }
+    return null;
+  }
+
+  private static boolean isNullabilityDefault(@NotNull PsiAnnotation annotation, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) {
+    PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
+    PsiElement declaration = element == null ? null : element.resolve();
+    if (!(declaration instanceof PsiClass)) return false;
+
+    if (!AnnotationUtil.isAnnotated((PsiClass)declaration,
+                                     nullable ? JAVAX_ANNOTATION_NULLABLE : JAVAX_ANNOTATION_NONNULL,
+                                     false,
+                                     true)) {
+      return false;
+    }
+
+    PsiAnnotation tqDefault = AnnotationUtil.findAnnotation((PsiClass)declaration, true, "javax.annotation.meta.TypeQualifierDefault");
+    if (tqDefault == null) return false;
+
+    Set<PsiAnnotation.TargetType> required = AnnotationTargetUtil.extractRequiredAnnotationTargets(tqDefault.findAttributeValue(null));
+    if (required == null) return false;
+    return required.isEmpty() || ContainerUtil.intersects(required, Arrays.asList(placeTargetTypes));
+  }
+
   public List<String> getNullables() {
     return myNullables;
   }
diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
index 7cabc11..52888f1 100644
--- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
@@ -476,6 +476,9 @@
           PsiType substituted = resolveResult.getSubstitutor().substitute(typeParam);
           if (substituted instanceof PsiWildcardType) {
             substituted = ((PsiWildcardType)substituted).getBound();
+            if (substituted instanceof PsiCapturedWildcardType) {
+              substituted = ((PsiCapturedWildcardType)substituted).getWildcard().getBound();
+            }
             if (substituted == null) substituted = TypeConversionUtil.typeParameterErasure(typeParam);
           }
           map.put(typeParam, substituted);
diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
index e7506eb..f433580 100644
--- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
+++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
@@ -180,7 +180,7 @@
   @NotNull
   public PsiSubstitutor getSubstitutor(boolean includeReturnConstraint) {
     PsiSubstitutor substitutor = myCalcedSubstitutor;
-    if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
+    if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) || isOverloadCheck()) {
       PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
       PsiMethod method = getElement();
       if (myTypeArguments == null) {
@@ -189,7 +189,7 @@
         final PsiSubstitutor inferredSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, includeReturnConstraint);
 
          if (!stackStamp.mayCacheNow() ||
-             !ourOverloadGuard.currentStack().isEmpty() ||
+             isOverloadCheck() ||
              !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) ||
              getMarkerList() != null && PsiResolveHelper.ourGraphGuard.currentStack().contains(getMarkerList().getParent())) {
           return inferredSubstitutor;
@@ -209,6 +209,10 @@
     return substitutor;
   }
 
+  public static boolean isOverloadCheck() {
+    return !ourOverloadGuard.currentStack().isEmpty();
+  }
+
 
   public boolean isTypeArgumentsApplicable() {
     return isTypeArgumentsApplicable(false);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
index 622714c..2259180 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
@@ -114,7 +114,7 @@
   }
 
   public static boolean areSignaturesEqual(@NotNull PsiMethod method1, @NotNull PsiMethod method2) {
-    return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
+    return areSignaturesEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY));
   }
 
   public static boolean areSignaturesEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
@@ -172,10 +172,10 @@
   public static boolean isSuperMethod(@NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) {
     PsiClass superClassCandidate = superMethodCandidate.getContainingClass();
     PsiClass derivedClass = derivedMethod.getContainingClass();
-    if (derivedClass == null || superClassCandidate == null) return false;
-    if (!derivedClass.isInheritor(superClassCandidate, true)) return false;
-    final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClassCandidate, derivedClass,
-                                                                                        PsiSubstitutor.EMPTY);
+    if (derivedClass == null || superClassCandidate == null || derivedClass == superClassCandidate) return false;
+    final PsiSubstitutor superSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(superClassCandidate, derivedClass,
+                                                                                             PsiSubstitutor.EMPTY, null);
+    if (superSubstitutor == null) return false;
     final MethodSignature superSignature = superMethodCandidate.getSignature(superSubstitutor);
     final MethodSignature derivedSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY);
     return isSubsignature(superSignature, derivedSignature);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
index e549371..a69e11a 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
@@ -1099,6 +1099,11 @@
         return true;
       }
     }
+    else if (parent instanceof PsiConditionalExpression) {
+      if (checkSameExpression(expr, ((PsiConditionalExpression)parent).getCondition())) {
+        return true;
+      }
+    }
     return false;
   }
 
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 477a74e..42f1494 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -128,6 +128,9 @@
         return boxedType != null && areTypesConvertible(boxedType, toType);
       }
       if (!fromIsPrimitive) {
+        // 5.5. Casting Contexts
+        if ((fromTypeRank == SHORT_RANK || fromTypeRank == BYTE_RANK) && toTypeRank == CHAR_RANK) return false;
+
         if (fromType instanceof PsiClassType) {
           if (languageLevel == null) {
             languageLevel = ((PsiClassType)fromType).getLanguageLevel();
@@ -162,7 +165,7 @@
   /**
    * see JLS 5.1.5, JLS3 5.1.6
    */
-  private static boolean isNarrowingReferenceConversionAllowed(PsiType fromType, PsiType toType) {
+  private static boolean isNarrowingReferenceConversionAllowed(@NotNull PsiType fromType, @NotNull PsiType toType) {
     if (toType instanceof PsiPrimitiveType || fromType instanceof PsiPrimitiveType) return fromType.equals(toType);
     //Done with primitives
     if (toType instanceof PsiDiamondType || fromType instanceof PsiDiamondType) return false;
@@ -280,60 +283,56 @@
         return false;
       }
     }
-    else {
-      if (!toClass.isInterface()) {
-        if (!toClass.hasModifierProperty(PsiModifier.FINAL)) {
-          return checkSuperTypesWithDifferentTypeArguments(fromResult, toClass, manager, toResult.getSubstitutor(), null, languageLevel);
-        }
-        else {
-          if (!toClass.isInheritor(fromClass, true)) return false;
-          PsiSubstitutor toSubstitutor = getSuperClassSubstitutor(fromClass, toClass, toResult.getSubstitutor());
-          return areSameArgumentTypes(fromClass, fromResult.getSubstitutor(), toSubstitutor);
-        }
+    else if (!toClass.isInterface()) {
+      if (!toClass.hasModifierProperty(PsiModifier.FINAL)) {
+        return checkSuperTypesWithDifferentTypeArguments(fromResult, toClass, manager, toResult.getSubstitutor(), null, languageLevel);
       }
       else {
-        if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) {
-          //In jls2 check for method in both interfaces with the same signature but different return types.
-          Collection<HierarchicalMethodSignature> fromClassMethodSignatures = fromClass.getVisibleSignatures();
-          Collection<HierarchicalMethodSignature> toClassMethodSignatures = toClass.getVisibleSignatures();
+        PsiSubstitutor toSubstitutor = getMaybeSuperClassSubstitutor(fromClass, toClass, toResult.getSubstitutor(), null);
+        return toSubstitutor != null && areSameArgumentTypes(fromClass, fromResult.getSubstitutor(), toSubstitutor);
+      }
+    }
+    else if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) {
+      //In jls2 check for method in both interfaces with the same signature but different return types.
+      Collection<HierarchicalMethodSignature> fromClassMethodSignatures = fromClass.getVisibleSignatures();
+      Collection<HierarchicalMethodSignature> toClassMethodSignatures = toClass.getVisibleSignatures();
 
-          for (HierarchicalMethodSignature fromMethodSignature : fromClassMethodSignatures) {
-            for (HierarchicalMethodSignature toMethodSignature : toClassMethodSignatures) {
-              if (fromMethodSignature.equals(toMethodSignature)) {
-                final PsiType fromClassReturnType = fromMethodSignature.getMethod().getReturnType();
-                final PsiType toClassReturnType = toMethodSignature.getMethod().getReturnType();
-                if (fromClassReturnType != null
-                    && toClassReturnType != null
-                    && !fromClassReturnType.equals(toClassReturnType)) {
-                  return false;
-                }
-              }
+      for (HierarchicalMethodSignature fromMethodSignature : fromClassMethodSignatures) {
+        for (HierarchicalMethodSignature toMethodSignature : toClassMethodSignatures) {
+          if (fromMethodSignature.equals(toMethodSignature)) {
+            final PsiType fromClassReturnType = fromMethodSignature.getMethod().getReturnType();
+            final PsiType toClassReturnType = toMethodSignature.getMethod().getReturnType();
+            if (fromClassReturnType != null
+                && toClassReturnType != null
+                && !fromClassReturnType.equals(toClassReturnType)) {
+              return false;
             }
           }
-          return true;
-        }
-        else {
-          //In jls3 check for super interface with distinct type arguments
-          PsiClassType.ClassResolveResult baseResult;
-          PsiClass derived;
-          PsiSubstitutor derivedSubstitutor;
-          if (toClass.isInheritor(fromClass, true)) {
-            baseResult = fromResult;
-            derived = toClass;
-            derivedSubstitutor = toResult.getSubstitutor();
-          }
-          else {
-            baseResult = toResult;
-            derived = fromClass;
-            derivedSubstitutor = fromResult.getSubstitutor();
-          }
-          return checkSuperTypesWithDifferentTypeArguments(baseResult, derived, manager, derivedSubstitutor, null, languageLevel);
         }
       }
+      return true;
+    }
+    else {
+      //In jls3 check for super interface with distinct type arguments
+      PsiClassType.ClassResolveResult baseResult;
+      PsiClass derived;
+      PsiSubstitutor derivedSubstitutor;
+      if (toClass.isInheritor(fromClass, true)) {
+        baseResult = fromResult;
+        derived = toClass;
+        derivedSubstitutor = toResult.getSubstitutor();
+      }
+      else {
+        baseResult = toResult;
+        derived = fromClass;
+        derivedSubstitutor = fromResult.getSubstitutor();
+      }
+      return checkSuperTypesWithDifferentTypeArguments(baseResult, derived, manager, derivedSubstitutor, null, languageLevel);
     }
   }
 
-  private static PsiClassType obtainSafeSuperType(final PsiTypeParameter typeParameter) {
+  @NotNull
+  private static PsiClassType obtainSafeSuperType(@NotNull PsiTypeParameter typeParameter) {
     final PsiClassType superType = typeParameter.getSuperTypes()[0];
     final PsiClassType.ClassResolveResult result = superType.resolveGenerics();
     final PsiClass superClass = result.getElement();
@@ -344,12 +343,12 @@
     return superType;
   }
 
-  private static boolean checkSuperTypesWithDifferentTypeArguments(PsiClassType.ClassResolveResult baseResult,
-                                                                   PsiClass derived,
-                                                                   PsiManager manager,
-                                                                   PsiSubstitutor derivedSubstitutor,
+  private static boolean checkSuperTypesWithDifferentTypeArguments(@NotNull PsiClassType.ClassResolveResult baseResult,
+                                                                   @NotNull PsiClass derived,
+                                                                   @NotNull PsiManager manager,
+                                                                   @NotNull PsiSubstitutor derivedSubstitutor,
                                                                    Set<PsiClass> visited,
-                                                                   final LanguageLevel languageLevel) {
+                                                                   @NotNull LanguageLevel languageLevel) {
     if (visited != null && visited.contains(derived)) return true;
 
     if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) return true;
@@ -359,10 +358,12 @@
       derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
       return areSameArgumentTypes(derived, baseResult.getSubstitutor(), derivedSubstitutor, 1);
     }
-    else if (base.isInheritor(derived, true)) {
-      derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
-      PsiSubstitutor baseSubstitutor = getSuperClassSubstitutor(derived, base, baseResult.getSubstitutor());
-      if (!areSameArgumentTypes(derived, baseSubstitutor, derivedSubstitutor)) return false;
+    else {
+      PsiSubstitutor baseSubstitutor = getMaybeSuperClassSubstitutor(derived, base, baseResult.getSubstitutor(), null);
+      if (baseSubstitutor != null) {
+        derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
+        if (!areSameArgumentTypes(derived, baseSubstitutor, derivedSubstitutor)) return false;
+      }
     }
 
     if (visited == null) visited = new THashSet<PsiClass>();
@@ -375,7 +376,7 @@
     return true;
   }
 
-  private static boolean areSameParameterTypes(PsiClassType type1, PsiClassType type2) {
+  private static boolean areSameParameterTypes(@NotNull PsiClassType type1, @NotNull PsiClassType type2) {
     PsiClassType.ClassResolveResult resolveResult1 = type1.resolveGenerics();
     PsiClassType.ClassResolveResult resolveResult2 = type2.resolveGenerics();
     final PsiClass aClass = resolveResult1.getElement();
@@ -386,13 +387,13 @@
            areSameArgumentTypes(aClass, resolveResult1.getSubstitutor(), resolveResult2.getSubstitutor());
   }
 
-  private static boolean areSameArgumentTypes(PsiClass aClass, PsiSubstitutor substitutor1, PsiSubstitutor substitutor2) {
+  private static boolean areSameArgumentTypes(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor1, @NotNull PsiSubstitutor substitutor2) {
     return areSameArgumentTypes(aClass, substitutor1, substitutor2, 0);
   }
 
-  private static boolean areSameArgumentTypes(PsiClass aClass,
-                                              PsiSubstitutor substitutor1,
-                                              PsiSubstitutor substitutor2,
+  private static boolean areSameArgumentTypes(@NotNull PsiClass aClass,
+                                              @NotNull PsiSubstitutor substitutor1,
+                                              @NotNull PsiSubstitutor substitutor2,
                                               int level) {
     for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
       PsiType typeArg1 = substitutor1.substitute(typeParameter);
@@ -463,7 +464,7 @@
    *         STRING_TYPE for String,
    *         Integer.MAX_VALUE for others
    */
-  public static int getTypeRank(PsiType type) {
+  public static int getTypeRank(@NotNull PsiType type) {
     PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
     if (unboxedType != null) {
       type = unboxedType;
@@ -597,13 +598,13 @@
     return isPrimitiveAndNotNull(type);
   }
 
-  public static boolean isUnaryOperatorApplicable(PsiJavaToken token, PsiExpression operand) {
+  public static boolean isUnaryOperatorApplicable(@NotNull PsiJavaToken token, PsiExpression operand) {
     if (operand == null) return false;
     PsiType type = operand.getType();
     return type != null && isUnaryOperatorApplicable(token, type);
   }
 
-  public static boolean isUnaryOperatorApplicable(final PsiJavaToken token, final PsiType type) {
+  public static boolean isUnaryOperatorApplicable(@NotNull PsiJavaToken token, @NotNull PsiType type) {
     IElementType i = token.getTokenType();
     int typeRank = getTypeRank(type);
     if (i == JavaTokenType.MINUSMINUS || i == JavaTokenType.PLUSPLUS) {
@@ -672,7 +673,7 @@
         value = ((Number)rValue).longValue();
       }
       else if (rValue instanceof Character) {
-        value = ((Character)rValue).charValue();
+        value = (Character)rValue;
       }
       else {
         return false;
@@ -832,7 +833,7 @@
     return isClassAssignable(leftResult, rightResult, allowUncheckedConversion);
   }
 
-  private static boolean isAssignableFromWildcard(PsiType left, PsiWildcardType rightWildcardType) {
+  private static boolean isAssignableFromWildcard(@NotNull PsiType left, @NotNull PsiWildcardType rightWildcardType) {
     if (rightWildcardType.isSuper()) {
       final PsiClass aClass = PsiUtil.resolveClassInType(rightWildcardType.getSuperBound());
       if (aClass instanceof PsiTypeParameter) {
@@ -845,14 +846,14 @@
     return isAssignable(left, rightWildcardType.getExtendsBound());
   }
 
-  private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) {
+  private static boolean isAssignableToWildcard(@NotNull PsiWildcardType wildcardType, @NotNull PsiType right) {
     if (wildcardType.isSuper()) {
       return isAssignable(wildcardType.getSuperBound(), right);
     }
     return isAssignable(wildcardType.getExtendsBound(), right);
   }
 
-  private static boolean isUnboxable(final PsiPrimitiveType left, final PsiClassType right) {
+  private static boolean isUnboxable(@NotNull PsiPrimitiveType left, @NotNull PsiClassType right) {
     final PsiPrimitiveType rightUnboxedType = PsiPrimitiveType.getUnboxedType(right);
     return rightUnboxedType != null && isAssignable(left, rightUnboxedType);
   }
@@ -869,7 +870,7 @@
 
   private static final Key<CachedValue<Set<String>>> POSSIBLE_BOXED_HOLDER_TYPES = Key.create("Types that may be possibly assigned from primitive ones");
 
-  private static boolean isBoxable(final PsiClassType left, final PsiPrimitiveType right) {
+  private static boolean isBoxable(@NotNull PsiClassType left, @NotNull PsiPrimitiveType right) {
     if (!left.getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_5)) return false;
     final PsiClass psiClass = left.resolve();
     if (psiClass == null) return false;
@@ -883,7 +884,8 @@
     return rightBoxed != null && isAssignable(left, rightBoxed);
   }
 
-  private static Set<String> getAllBoxedTypeSupers(PsiClass psiClass) {
+  @NotNull
+  private static Set<String> getAllBoxedTypeSupers(@NotNull PsiClass psiClass) {
     PsiManager manager = psiClass.getManager();
     final Project project = psiClass.getProject();
     CachedValue<Set<String>> boxedHolderTypes = project.getUserData(POSSIBLE_BOXED_HOLDER_TYPES);
@@ -908,12 +910,11 @@
       }, false));
     }
 
-    final Set<String> boxedHolders = boxedHolderTypes.getValue();
-    return boxedHolders;
+    return boxedHolderTypes.getValue();
   }
 
-  private static boolean isClassAssignable(PsiClassType.ClassResolveResult leftResult,
-                                           PsiClassType.ClassResolveResult rightResult,
+  private static boolean isClassAssignable(@NotNull PsiClassType.ClassResolveResult leftResult,
+                                           @NotNull PsiClassType.ClassResolveResult rightResult,
                                            boolean allowUncheckedConversion) {
     final PsiClass leftClass = leftResult.getElement();
     final PsiClass rightClass = rightResult.getElement();
@@ -923,8 +924,8 @@
            && typeParametersAgree(leftResult, rightResult, allowUncheckedConversion);
   }
 
-  private static boolean typeParametersAgree(PsiClassType.ClassResolveResult leftResult,
-                                             PsiClassType.ClassResolveResult rightResult,
+  private static boolean typeParametersAgree(@NotNull PsiClassType.ClassResolveResult leftResult,
+                                             @NotNull PsiClassType.ClassResolveResult rightResult,
                                              boolean allowUncheckedConversion) {
     PsiSubstitutor rightSubstitutor = rightResult.getSubstitutor();
     PsiClass leftClass = leftResult.getElement();
@@ -962,7 +963,7 @@
 
   private static final RecursionGuard ourGuard = RecursionManager.createGuard("isAssignable");
 
-  public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, final boolean allowUncheckedConversion) {
+  public static boolean typesAgree(@NotNull PsiType typeLeft, @NotNull PsiType typeRight, final boolean allowUncheckedConversion) {
     if (typeLeft instanceof PsiWildcardType) {
       final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft;
       final PsiType leftBound = leftWildcard.getBound();
@@ -986,7 +987,7 @@
                 return isAssignable(rightWildcard.getBound(), leftBound, allowUncheckedConversion);
               }
             });
-            if (assignable != null && assignable.booleanValue()) {
+            if (assignable != null && assignable) {
               return true;
             }
           }
@@ -1022,7 +1023,7 @@
   @Nullable
   public static PsiSubstitutor getClassSubstitutor(@NotNull PsiClass superClassCandidate,
                                                    @NotNull PsiClass derivedClassCandidate,
-                                                   PsiSubstitutor derivedSubstitutor) {
+                                                   @NotNull PsiSubstitutor derivedSubstitutor) {
     if (superClassCandidate.getManager().areElementsEquivalent(superClassCandidate, derivedClassCandidate)) {
       PsiTypeParameter[] baseParams = superClassCandidate.getTypeParameters();
       PsiTypeParameter[] derivedParams = derivedClassCandidate.getTypeParameters();
@@ -1031,8 +1032,7 @@
       }
       return derivedSubstitutor;
     }
-    if (!derivedClassCandidate.isInheritor(superClassCandidate, true)) return null;
-    return getSuperClassSubstitutor(superClassCandidate, derivedClassCandidate, derivedSubstitutor);
+    return getMaybeSuperClassSubstitutor(superClassCandidate, derivedClassCandidate, derivedSubstitutor, null);
   }
 
   private static final Set<String> ourReportedSuperClassSubstitutorExceptions = new ConcurrentHashSet<String>();
@@ -1042,42 +1042,21 @@
    * values that they have in <code>derivedClass</code>, given that type parameters in
    * <code>derivedClass</code> are bound by <code>derivedSubstitutor</code>.
    * <code>superClass</code> must be a super class/interface of <code>derivedClass</code> (as in
-   * <code>InheritanceUtil.isInheritor(derivedClass, superClass, true)</code>
+   * <code>InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true)</code>
    *
    * @return substitutor (never returns <code>null</code>)
    * @see PsiClass#isInheritor(PsiClass, boolean)
+   * @see InheritanceUtil#isInheritorOrSelf(com.intellij.psi.PsiClass, com.intellij.psi.PsiClass, boolean)
    */
   @NotNull
   public static PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass superClass,
                                                         @NotNull PsiClass derivedClass,
                                                         @NotNull PsiSubstitutor derivedSubstitutor) {
-    // [dsl] assertion commented out since we no longer cache isInheritor
-    //LOG.assertTrue(derivedClass.isInheritor(superClass, true), "Not inheritor: " + derivedClass + " super: " + superClass);
+    if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) return PsiSubstitutor.EMPTY; //optimization and protection against EJB queer hierarchy
 
-    if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) return PsiSubstitutor.EMPTY; //optimization
+    Set<PsiClass> visited = new THashSet<PsiClass>();
+    PsiSubstitutor substitutor = getMaybeSuperClassSubstitutor(superClass, derivedClass, derivedSubstitutor, visited);
 
-    final PsiManager manager = superClass.getManager();
-    if (PsiUtil.isRawSubstitutor(derivedClass, derivedSubstitutor)) {
-      return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(superClass);
-    }
-
-    final PsiClass objectClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, superClass.getResolveScope());
-    if (manager.areElementsEquivalent(superClass, objectClass)) {
-      return PsiSubstitutor.EMPTY;
-    }
-
-    PsiSubstitutor substitutor;
-    final Set<PsiClass> visited = new THashSet<PsiClass>();
-    if (derivedClass instanceof PsiAnonymousClass) {
-      final PsiClassType baseType = ((PsiAnonymousClass)derivedClass).getBaseClassType();
-      final JavaResolveResult result = baseType.resolveGenerics();
-      if (result.getElement() == null) return PsiSubstitutor.UNKNOWN;
-      substitutor = getSuperClassSubstitutorInner(superClass, (PsiClass)result.getElement(),
-                                                  derivedSubstitutor.putAll(result.getSubstitutor()), visited, manager);
-    }
-    else {
-      substitutor = getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited, manager);
-    }
     if (substitutor == null) {
       if (ourReportedSuperClassSubstitutorExceptions.add(derivedClass.getQualifiedName() + "/" + superClass.getQualifiedName())) {
         reportHierarchyInconsistency(superClass, derivedClass, visited);
@@ -1087,7 +1066,37 @@
     return substitutor;
   }
 
-  private static void reportHierarchyInconsistency(PsiClass superClass, PsiClass derivedClass, Set<PsiClass> visited) {
+  // the same as getSuperClassSubstitutor() but can return null, which means that classes were not inheritors
+  @Nullable
+  public static PsiSubstitutor getMaybeSuperClassSubstitutor(@NotNull PsiClass superClass,
+                                                             @NotNull PsiClass derivedClass,
+                                                             @NotNull PsiSubstitutor derivedSubstitutor,
+                                                             @Nullable Set<PsiClass> visited) {
+    if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) {
+      return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? PsiSubstitutor.EMPTY : null; //optimization
+    }
+
+    final PsiManager manager = superClass.getManager();
+    if (PsiUtil.isRawSubstitutor(derivedClass, derivedSubstitutor)) {
+      return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(superClass) : null;
+    }
+
+    if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(superClass.getName()) &&
+        manager.areElementsEquivalent(superClass, JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, superClass.getResolveScope()))) {
+      return PsiSubstitutor.EMPTY;
+    }
+
+    if (derivedClass instanceof PsiAnonymousClass) {
+      final PsiClassType baseType = ((PsiAnonymousClass)derivedClass).getBaseClassType();
+      final JavaResolveResult result = baseType.resolveGenerics();
+      if (result.getElement() == null) return PsiSubstitutor.UNKNOWN;
+      derivedClass = (PsiClass)result.getElement();
+      derivedSubstitutor = derivedSubstitutor.putAll(result.getSubstitutor());
+    }
+    return getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited == null ? new THashSet<PsiClass>() : visited, manager);
+  }
+
+  private static void reportHierarchyInconsistency(@NotNull PsiClass superClass, @NotNull PsiClass derivedClass, @NotNull Set<PsiClass> visited) {
     final StringBuilder msg = new StringBuilder("Super: " + classInfo(superClass));
     msg.append("visited:\n");
     for (PsiClass aClass : visited) {
@@ -1105,7 +1114,8 @@
     LOG.error(msg.toString());
   }
 
-  private static String classInfo(PsiClass aClass) {
+  @NotNull
+  private static String classInfo(@NotNull PsiClass aClass) {
     String s = aClass.getQualifiedName() + "(" + aClass.getClass().getName() + "; " + PsiUtilCore.getVirtualFile(aClass) + ");\n";
     s += "extends: ";
     for (PsiClassType type : aClass.getExtendsListTypes()) {
@@ -1124,12 +1134,14 @@
       return getSuperClassSubstitutor(superClass, classResolveResult.getElement(), classResolveResult.getSubstitutor());
   }
 
-  private static PsiSubstitutor getSuperClassSubstitutorInner(PsiClass base,
-                                                              PsiClass candidate,
-                                                              PsiSubstitutor candidateSubstitutor,
-                                                              Set<PsiClass> visited,
-                                                              PsiManager manager) {
+  @Nullable
+  private static PsiSubstitutor getSuperClassSubstitutorInner(@NotNull PsiClass base,
+                                                              @NotNull PsiClass candidate,
+                                                              @NotNull PsiSubstitutor candidateSubstitutor,
+                                                              @NotNull Set<PsiClass> visited,
+                                                              @NotNull PsiManager manager) {
     if (!visited.add(candidate)) return null;
+    assert candidateSubstitutor.isValid();
 
     if (base == candidate) return candidateSubstitutor;
     if (manager.areElementsEquivalent(base, candidate)) {
@@ -1148,19 +1160,18 @@
       }
     }
 
-    PsiSubstitutor substitutor = checkReferenceList(candidate.getExtendsListTypes(), candidateSubstitutor, base, visited,
-                                                    manager);
+    PsiSubstitutor substitutor = checkReferenceList(candidate.getExtendsListTypes(), candidateSubstitutor, base, visited, manager);
     if (substitutor == null) {
       substitutor = checkReferenceList(candidate.getImplementsListTypes(), candidateSubstitutor, base, visited, manager);
     }
     return substitutor;
   }
 
-  private static PsiSubstitutor checkReferenceList(final PsiClassType[] types, PsiSubstitutor candidateSubstitutor,
-                                                   PsiClass base,
-                                                   Set<PsiClass> set,
-                                                   PsiManager manager) {
-    assert candidateSubstitutor.isValid();
+  private static PsiSubstitutor checkReferenceList(@NotNull PsiClassType[] types,
+                                                   @NotNull PsiSubstitutor candidateSubstitutor,
+                                                   @NotNull PsiClass base,
+                                                   @NotNull Set<PsiClass> set,
+                                                   @NotNull PsiManager manager) {
     for (final PsiClassType type : types) {
       final PsiType substitutedType = candidateSubstitutor.substitute(type);
       //if (!(substitutedType instanceof PsiClassType)) return null;
@@ -1170,8 +1181,7 @@
       final PsiElement newCandidate = result.getElement();
       if (newCandidate != null) {
         final PsiSubstitutor substitutor = result.getSubstitutor();
-        final PsiSubstitutor newSubstitutor = getSuperClassSubstitutorInner(base, (PsiClass)newCandidate,
-                                                                            substitutor, set, manager);
+        final PsiSubstitutor newSubstitutor = getSuperClassSubstitutorInner(base, (PsiClass)newCandidate, substitutor, set, manager);
         if (newSubstitutor != null) {
           return type.isRaw() ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(base) : newSubstitutor;
         }
@@ -1183,6 +1193,7 @@
   /**
    * see JLS 5.6.2
    */
+  @NotNull
   public static PsiType binaryNumericPromotion(PsiType type1, PsiType type2) {
     if (isDoubleType(type1)) return unbox(type1);
     if (isDoubleType(type2)) return unbox(type2);
@@ -1194,7 +1205,8 @@
     return PsiType.INT;
   }
 
-  private static PsiType unbox(PsiType type) {
+  @NotNull
+  private static PsiType unbox(@NotNull PsiType type) {
     if (type instanceof PsiPrimitiveType) return type;
     if (type instanceof PsiClassType) {
       type = PsiPrimitiveType.getUnboxedType(type);
@@ -1393,6 +1405,7 @@
     return value;
   }
 
+  @NotNull
   public static PsiType unboxAndBalanceTypes(PsiType type1, PsiType type2) {
     if (type1 instanceof PsiClassType) type1 = PsiPrimitiveType.getUnboxedType(type1);
     if (type2 instanceof PsiClassType) type2 = PsiPrimitiveType.getUnboxedType(type2);
@@ -1442,7 +1455,7 @@
   }
 
   @Nullable
-  public static PsiType calcTypeForBinaryExpression(PsiType lType, PsiType rType, IElementType sign, boolean accessLType) {
+  public static PsiType calcTypeForBinaryExpression(PsiType lType, PsiType rType, @NotNull IElementType sign, boolean accessLType) {
     if (sign == JavaTokenType.PLUS) {
       // evaluate right argument first, since '+-/*%' is left associative and left operand tends to be bigger
       if (rType == null) return null;
@@ -1512,321 +1525,371 @@
   }
 
   private interface Caster {
-    Object cast(Object operand);
+    @NotNull
+    Object cast(@NotNull Object operand);
   }
 
   private static final Caster[][] caster = {
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
+        public Object cast(@NotNull Object operand) {
           return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Number)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Number)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Number) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Number)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf(((Number)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return ((Number)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf(((Number)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)((Number)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Number) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (float)((Number)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Number) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)((Number)operand).intValue();
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Short)operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Short)operand).shortValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf(((Short)operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Short) operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Short)operand).shortValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf(((Short)operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (int)(Short)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf(((Short)operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)(Short)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Short) operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (float)(Short)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Short) operand).shortValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)(Short)operand;
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Character)operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Character)operand).charValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Character)operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Character)operand).charValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character(((Character) operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf(((Character)operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (int)(Character)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf(((Character)operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)(Character)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Character) operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (float)(Character)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Character) operand).charValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)(Character)operand;
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Integer)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Integer)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Integer)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Integer)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Integer) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Integer)operand).intValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf(((Integer)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf(((Integer)operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)(Integer)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Integer) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (float)(Integer)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Integer) operand).intValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)(Integer)operand;
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Long)operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Long)operand).longValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Long)operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Long)operand).longValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Long) operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Long)operand).longValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf((int)((Long)operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (int)((Long)operand).longValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf(((Long)operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Long) operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (float)(Long)operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Long) operand).longValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)(Long)operand;
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Float)operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Float)operand).floatValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Float)operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Float)operand).floatValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Float) operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Float)operand).floatValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf((int)((Float)operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (int)((Float)operand).floatValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf((long)((Float)operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)((Float)operand).floatValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Float) operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Float) operand).floatValue());
+        public Object cast(@NotNull Object operand) {
+          return (double)(Float)operand;
         }
       }
     }
     ,
     {
       new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Byte.valueOf((byte)((Double)operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return (byte)((Double)operand).doubleValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Short.valueOf((short)((Double)operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return (short)((Double)operand).doubleValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Character((char) ((Double) operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return (char)((Double)operand).doubleValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Integer.valueOf((int)((Double)operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return (int)((Double)operand).doubleValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return Long.valueOf((long)((Double)operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return (long)((Double)operand).doubleValue();
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Float(((Double) operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return new Float((Double)operand);
         }
       }
       , new Caster() {
+        @NotNull
         @Override
-        public Object cast(Object operand) {
-          return new Double(((Double) operand).doubleValue());
+        public Object cast(@NotNull Object operand) {
+          return operand;
         }
       }
     }
@@ -1844,7 +1907,7 @@
     WRAPPER_TO_PRIMITIVE.put(Double.class, PsiType.DOUBLE);
   }
 
-  private static PsiType wrapperToPrimitive(Object o) {
+  private static PsiType wrapperToPrimitive(@NotNull Object o) {
     return WRAPPER_TO_PRIMITIVE.get(o.getClass());
   }
 
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java b/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java
new file mode 100644
index 0000000..7678390
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java
@@ -0,0 +1,13 @@
+package com.intellij.codeInsight;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class CustomExceptionHandler {
+  public static final ExtensionPointName<CustomExceptionHandler> KEY = ExtensionPointName.create("com.intellij.custom.exception.handler");
+
+  public abstract boolean isHandled(@Nullable PsiElement element, @NotNull PsiClassType exceptionType, PsiElement topElement);
+}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
index 552c7e2..bb4e322 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.codeInsight;
 
+import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.controlFlow.*;
@@ -675,6 +676,10 @@
         // exceptions thrown in field initializers should be thrown in all class constructors
         return areAllConstructorsThrow(aClass, exceptionType);
       }
+    } else {
+      for (CustomExceptionHandler exceptionHandler : Extensions.getExtensions(CustomExceptionHandler.KEY)) {
+        if (exceptionHandler.isHandled(element, exceptionType, topElement)) return true;
+      }
     }
     return isHandled(parent, exceptionType, topElement);
   }
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
index 5e008af..e2de5a5 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
@@ -598,9 +598,15 @@
 
     Document document = method.getContainingFile().getViewProvider().getDocument();
     PsiCodeBlock body = method.getBody();
-    if (body == null || document == null) {
+    PsiIdentifier nameIdentifier = method.getNameIdentifier();
+    if (body == null || document == null || nameIdentifier == null) {
       return false;
     }
+    if (document.getLineNumber(nameIdentifier.getTextRange().getStartOffset()) !=
+        document.getLineNumber(method.getParameterList().getTextRange().getEndOffset())) {
+      return false;
+    }
+
     PsiJavaToken lBrace = body.getLBrace();
     PsiJavaToken rBrace = body.getRBrace();
     PsiStatement[] statements = body.getStatements();
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
index aca4357..a8b2b40 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
@@ -39,7 +39,8 @@
     Couple.of("first", "last"),
     Couple.of("first", "second"),
     Couple.of("from", "to"),
-    Couple.of("key", "value")
+    Couple.of("key", "value"),
+    Couple.of("min", "max")
   );
 
   private final PsiCallExpression myCallExpression;
@@ -58,7 +59,8 @@
     if (callArgument instanceof PsiPrefixExpression) {
       PsiPrefixExpression expr = (PsiPrefixExpression)callArgument;
       IElementType tokenType = expr.getOperationTokenType();
-      return JavaTokenType.MINUS.equals(tokenType) && expr.getOperand() instanceof PsiLiteralExpression;
+      return (JavaTokenType.MINUS.equals(tokenType)
+              || JavaTokenType.PLUS.equals(tokenType)) && expr.getOperand() instanceof PsiLiteralExpression;
     }
 
     return false;
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
index f709442..ac2fe33 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,10 +17,10 @@
 
 import com.intellij.psi.*;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
 import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
-import java.lang.reflect.Field;
 
 /**
  * @author spleaner
@@ -98,14 +98,12 @@
           if (reference != null) {
             final PsiElement psiElement = reference.resolve();
             if (psiElement instanceof PsiField) {
-              final PsiClass psiClass = ((PsiField) psiElement).getContainingClass();
+              PsiField psiField = (PsiField)psiElement;
+              final PsiClass psiClass = psiField.getContainingClass();
               if (psiClass != null && "java.awt.Color".equals(psiClass.getQualifiedName())) {
-                try {
-                  Field field = Class.forName("java.awt.Color").getField(((PsiField)psiElement).getName());
-                  final Color c = (Color) field.get(null);
+                Color c = ReflectionUtil.getField(Color.class, null, Color.class, psiField.getName());
+                if (c != null) {
                   buffer.append(generatePreviewHtml(c));
-                } catch (Exception e) {
-                  // nothing
                 }
               }
             }
diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
index e111689..5f3eee5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
@@ -34,6 +34,7 @@
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.VisibilityUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -253,8 +254,9 @@
                                                  PsiTypeParameter[] params,
                                                  PsiJavaCodeReferenceElement reference) {
     final StringBuilder buf = new StringBuilder();
-    buf.append(constructor != null ? constructor.getModifierList().getText() : containingClass.getModifierList().getText());
-    if (buf.length() > 0) {
+    final String modifier = VisibilityUtil.getVisibilityModifier(constructor != null ? constructor.getModifierList() : containingClass.getModifierList());
+    if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
+      buf.append(modifier);
       buf.append(" ");
     }
     buf.append("static ");
@@ -262,8 +264,20 @@
     buf.append(StringUtil.join(params, new Function<PsiTypeParameter, String>() {
       @Override
       public String fun(PsiTypeParameter psiTypeParameter) {
-        final String extendsList = psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE) ? psiTypeParameter.getExtendsList().getText() : null;
-        return psiTypeParameter.getName() + (StringUtil.isEmpty(extendsList) ? "" : " " + extendsList);
+        String extendsList = "";
+        if (psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
+          final PsiClassType[] extendsListTypes = psiTypeParameter.getExtendsListTypes();
+          if (extendsListTypes.length > 0) {
+            final Function<PsiClassType, String> canonicalTypePresentationFun = new Function<PsiClassType, String>() {
+              @Override
+              public String fun(PsiClassType type) {
+                return type.getCanonicalText();
+              }
+            };
+            extendsList = " extends " + StringUtil.join(extendsListTypes, canonicalTypePresentationFun, "&");
+          }
+        }
+        return psiTypeParameter.getName() + extendsList;
       }
     }, ", "));
     buf.append(">");
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
index f958555..9427551 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
@@ -25,9 +25,7 @@
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiModificationTracker;
 import com.intellij.util.containers.ConcurrentWeakHashMap;
-import com.intellij.util.containers.HashSet;
 import gnu.trove.THashSet;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -39,10 +37,12 @@
 
   public static boolean isInheritor(@NotNull final PsiClass candidateClass, @NotNull PsiClass baseClass, final boolean checkDeep) {
     if (baseClass instanceof PsiAnonymousClass) return false;
-    if (!checkDeep) return isInheritor(candidateClass, baseClass, false, null);
+    if (!checkDeep) {
+      return isInheritor(candidateClass.getManager(), candidateClass, baseClass, false, null);
+    }
 
-    if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(candidateClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(candidateClass.getQualifiedName())) return false;
-    if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) return true;
+    if (hasObjectQualifiedName(candidateClass)) return false;
+    if (hasObjectQualifiedName(baseClass)) return true;
     Map<PsiClass, Boolean> map = CachedValuesManager.
       getCachedValue(candidateClass, new CachedValueProvider<Map<PsiClass, Boolean>>() {
         @Nullable
@@ -55,18 +55,29 @@
 
     Boolean computed = map.get(baseClass);
     if (computed == null) {
-      computed = isInheritor(candidateClass, baseClass, true, null);
+      computed = isInheritor(candidateClass.getManager(), candidateClass, baseClass, true, null);
       map.put(baseClass, computed);
     }
     return computed;
   }
 
-  private static boolean isInheritor(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
+  public static boolean hasObjectQualifiedName(@NotNull PsiClass candidateClass) {
+    if (!CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(candidateClass.getName())) {
+      return false;
+    }
+    PsiElement parent = candidateClass.getParent();
+    return parent instanceof PsiJavaFile && CommonClassNames.DEFAULT_PACKAGE.equals(((PsiJavaFile)parent).getPackageName());
+  }
+
+  private static boolean isInheritor(@NotNull PsiManager manager,
+                                     @NotNull PsiClass candidateClass,
+                                     @NotNull PsiClass baseClass,
+                                     boolean checkDeep,
+                                     @Nullable Set<PsiClass> checkedClasses) {
     if (candidateClass instanceof PsiAnonymousClass) {
       final PsiClass baseCandidateClass = ((PsiAnonymousClass)candidateClass).getBaseClassType().resolve();
       return baseCandidateClass != null && InheritanceUtil.isInheritorOrSelf(baseCandidateClass, baseClass, checkDeep);
     }
-    PsiManager manager = candidateClass.getManager();
     /* //TODO fix classhashprovider so it doesn't use class qnames only
     final ClassHashProvider provider = getHashProvider((PsiManagerImpl) manager);
     if (checkDeep && provider != null) {
@@ -81,8 +92,7 @@
       LOG.debug("Using uncached version for " + candidateClass.getQualifiedName() + " and " + baseClass);
     }
 
-    @NonNls final String baseName = baseClass.getName();
-    if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseName)) {
+    if (hasObjectQualifiedName(baseClass)) {
       PsiClass objectClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, candidateClass.getResolveScope());
       if (manager.areElementsEquivalent(baseClass, objectClass)) {
         if (manager.areElementsEquivalent(candidateClass, objectClass)) return false;
@@ -103,6 +113,7 @@
         if (cInt == bInt && checkReferenceListWithQualifiedNames(baseQName, candidateClass.getExtendsList(), manager, scope)) return true;
         return bInt && !cInt && checkReferenceListWithQualifiedNames(baseQName, candidateClass.getImplementsList(), manager, scope);
       }
+      String baseName = baseClass.getName();
       if (cInt == bInt) {
         for (PsiClassType type : candidateClass.getExtendsListTypes()) {
           if (Comparing.equal(type.getClassName(), baseName)) {
@@ -125,7 +136,7 @@
       return false;
     }
 
-    return isInheritorWithoutCaching(candidateClass, baseClass, checkDeep, checkedClasses);
+    return isInheritorWithoutCaching(manager, candidateClass, baseClass, checkedClasses);
   }
 
   private static boolean checkReferenceListWithQualifiedNames(final String baseQName, final PsiReferenceList extList, final PsiManager manager,
@@ -141,63 +152,50 @@
     return false;
   }
 
-  private static boolean isInheritorWithoutCaching(PsiClass aClass, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
-    PsiManager manager = aClass.getManager();
+  private static boolean isInheritorWithoutCaching(@NotNull PsiManager manager,
+                                                   @NotNull PsiClass aClass,
+                                                   @NotNull PsiClass baseClass,
+                                                   @Nullable Set<PsiClass> checkedClasses) {
     if (manager.areElementsEquivalent(aClass, baseClass)) return false;
 
     if (aClass.isInterface() && !baseClass.isInterface()) {
       return false;
     }
 
-    //if (PsiUtil.hasModifierProperty(baseClass, PsiModifier.FINAL)) {
-    //  return false;
-    //}
-
-    if (checkDeep) {
-      if (checkedClasses == null) {
-        checkedClasses = new THashSet<PsiClass>();
-      }
-      checkedClasses.add(aClass);
+    if (checkedClasses == null) {
+      checkedClasses = new THashSet<PsiClass>();
     }
+    checkedClasses.add(aClass);
 
-    if (!aClass.isInterface() && baseClass.isInterface()) {
-      if (checkDeep && checkInheritor(aClass.getSuperClass(), baseClass, checkDeep, checkedClasses)) {
-        return true;
-      }
-      return checkInheritor(aClass.getInterfaces(), baseClass, checkDeep, checkedClasses);
-
-    }
-    else {
-      return checkInheritor(aClass.getSupers(), baseClass, checkDeep, checkedClasses);
-    }
+    return checkInheritor(manager, aClass.getExtendsListTypes(), baseClass, checkedClasses) ||
+           checkInheritor(manager, aClass.getImplementsListTypes(), baseClass, checkedClasses);
   }
 
-  private static boolean checkInheritor(PsiClass[] supers, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
-    for (PsiClass aSuper : supers) {
-      if (checkInheritor(aSuper, baseClass, checkDeep, checkedClasses)) {
+  private static boolean checkInheritor(@NotNull PsiManager manager,
+                                        @NotNull PsiClassType[] supers,
+                                        @NotNull PsiClass baseClass,
+                                        @NotNull Set<PsiClass> checkedClasses) {
+    for (PsiClassType aSuper : supers) {
+      PsiClass aClass = aSuper.resolve();
+      if (aClass != null && checkInheritor(manager, aClass, baseClass, checkedClasses)) {
         return true;
       }
     }
     return false;
   }
 
-  private static boolean checkInheritor(PsiClass aClass, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
+  private static boolean checkInheritor(@NotNull PsiManager manager,
+                                        @NotNull PsiClass aClass,
+                                        @NotNull PsiClass baseClass,
+                                        @NotNull Set<PsiClass> checkedClasses) {
     ProgressIndicatorProvider.checkCanceled();
-    if (aClass != null) {
-      PsiManager manager = baseClass.getManager();
-      if (manager.areElementsEquivalent(baseClass, aClass)) {
-        return true;
-      }
-      if (checkedClasses != null && checkedClasses.contains(aClass)) { // to prevent infinite recursion
-        return false;
-      }
-      if (checkDeep) {
-        if (isInheritor(aClass, baseClass, checkDeep, checkedClasses)) {
-          return true;
-        }
-      }
+    if (manager.areElementsEquivalent(baseClass, aClass)) {
+      return true;
     }
-    return false;
+    if (checkedClasses.contains(aClass)) { // to prevent infinite recursion
+      return false;
+    }
+    return isInheritor(manager, aClass, baseClass, true, checkedClasses);
   }
 
   public static boolean isInheritorDeep(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, @Nullable final PsiClass classToByPass) {
@@ -207,9 +205,9 @@
 
     Set<PsiClass> checkedClasses = null;
     if (classToByPass != null) {
-      checkedClasses = new HashSet<PsiClass>();
+      checkedClasses = new THashSet<PsiClass>();
       checkedClasses.add(classToByPass);
     }
-    return isInheritor(candidateClass, baseClass, true, checkedClasses);
+    return isInheritor(candidateClass.getManager(), candidateClass, baseClass, true, checkedClasses);
   }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index 5140874..938b40f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi.impl;
 
+import com.intellij.codeInsight.AnnotationTargetUtil;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
@@ -51,7 +52,6 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -60,22 +60,6 @@
 public class PsiImplUtil {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiImplUtil");
 
-  private static final Set<TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet(
-    TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE,
-    TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR,
-    TargetType.PARAMETER, TargetType.LOCAL_VARIABLE));
-
-  private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE};
-  private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE};
-  private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE};
-  private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE};
-  private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE};
-  private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE};
-  private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE};
-  private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE};
-  private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE};
-  private static final TargetType[] LOCAL_VARIABLE_TARGETS ={TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE};
-
   private PsiImplUtil() { }
 
   @NotNull
@@ -376,93 +360,14 @@
     PsiModifierList modifierList = annotationType.getModifierList();
     if (modifierList == null) return null;
     PsiAnnotation target = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_TARGET);
-    if (target == null) return DEFAULT_TARGETS;  // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets
+    if (target == null) return AnnotationTargetUtil.DEFAULT_TARGETS;  // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets
 
-    PsiAnnotationMemberValue value = target.findAttributeValue(null);
-    if (value instanceof PsiReference) {
-      TargetType targetType = translateTargetRef((PsiReference)value);
-      if (targetType != null) {
-        return Collections.singleton(targetType);
-      }
-    }
-    else if (value instanceof PsiArrayInitializerMemberValue) {
-      Set <TargetType> targets = ContainerUtil.newHashSet();
-      for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
-        if (initializer instanceof PsiReference) {
-          TargetType targetType = translateTargetRef((PsiReference)initializer);
-          if (targetType != null) {
-            targets.add(targetType);
-          }
-        }
-      }
-      return targets;
-    }
-
-    return null;
-  }
-
-  @Nullable
-  private static TargetType translateTargetRef(PsiReference reference) {
-    PsiElement field = reference.resolve();
-    if (field instanceof PsiEnumConstant) {
-      String name = ((PsiEnumConstant)field).getName();
-      try {
-        return TargetType.valueOf(name);
-      }
-      catch (IllegalArgumentException e) {
-        LOG.warn("Unknown target: " + name);
-      }
-    }
-    return null;
+    return AnnotationTargetUtil.extractRequiredAnnotationTargets(target.findAttributeValue(null));
   }
 
   @NotNull
   public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
-    if (owner == null) {
-      return TargetType.EMPTY_ARRAY;
-    }
-
-    if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
-      return TYPE_USE_TARGETS;
-    }
-
-    if (owner instanceof PsiTypeParameter) {
-      return TYPE_PARAMETER_TARGETS;
-    }
-
-    if (owner instanceof PsiModifierList) {
-      PsiElement element = ((PsiModifierList)owner).getParent();
-      if (element instanceof PsiPackageStatement) {
-        return PACKAGE_TARGETS;
-      }
-      if (element instanceof PsiClass) {
-        if (((PsiClass)element).isAnnotationType()) {
-          return ANNOTATION_TARGETS;
-        }
-        else {
-          return TYPE_TARGETS;
-        }
-      }
-      if (element instanceof PsiMethod) {
-        if (((PsiMethod)element).isConstructor()) {
-          return CONSTRUCTOR_TARGETS;
-        }
-        else {
-          return METHOD_TARGETS;
-        }
-      }
-      if (element instanceof PsiField) {
-        return FIELD_TARGETS;
-      }
-      if (element instanceof PsiParameter) {
-        return PARAMETER_TARGETS;
-      }
-      if (element instanceof PsiLocalVariable) {
-        return LOCAL_VARIABLE_TARGETS;
-      }
-    }
-
-    return TargetType.EMPTY_ARRAY;
+    return AnnotationTargetUtil.getTargetsForLocation(owner);
   }
 
   @Nullable
@@ -782,4 +687,33 @@
     return element instanceof LeafElement && tokenSet.contains(((LeafElement)element).getElementType());
   }
 
+  public static PsiType buildTypeFromTypeString(@NotNull final String typeName, @NotNull final PsiElement context, @NotNull final PsiFile psiFile) {
+    PsiType resultType;
+    final PsiManager psiManager = psiFile.getManager();
+
+    if (typeName.indexOf('<') != -1 || typeName.indexOf('[') != -1 || typeName.indexOf('.') == -1) {
+      try {
+        return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createTypeFromText(typeName, context);
+      } catch(Exception ex) {} // invalid syntax will produce unresolved class type
+    }
+
+    PsiClass aClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(typeName, context.getResolveScope());
+
+    if (aClass == null) {
+      final LightClassReference ref = new LightClassReference(
+        psiManager,
+        PsiNameHelper.getShortClassName(typeName),
+        typeName,
+        PsiSubstitutor.EMPTY,
+        psiFile
+      );
+      resultType = new PsiClassReferenceType(ref, null);
+    } else {
+      PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
+      PsiSubstitutor substitutor = factory.createRawSubstitutor(aClass);
+      resultType = factory.createType(aClass, substitutor);
+    }
+
+    return resultType;
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
index f1d847c..e0db770 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootModificationTracker;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
@@ -370,7 +371,12 @@
         if (result == null) {
           result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY));
         }
-        return CachedValueProvider.Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+
+        Project project = aClass == null ? method.getProject() : aClass.getProject();
+        // cache Cls method hierarchy until root changed
+        Object dependency = method instanceof PsiCompiledElement ? ProjectRootModificationTracker.getInstance(project) :
+                            PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT;
+        return CachedValueProvider.Result.create(result, dependency);
       }
     };
 
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
index d2a6627..b356698 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
@@ -84,7 +84,8 @@
 
   @Override
   public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-    String fqn, shortName;
+    String fqn;
+    String shortName;
     if (myShortName != null && name.endsWith(myShortName)) {
       shortName = myShortName;
       fqn = name.length() == shortName.length()
@@ -338,7 +339,8 @@
     if (fqn == null) return true;  // impossible case, just ignore
     if (fqn.length() != signature.length()) return false;
 
-    int p = 0, dot;
+    int p = 0;
+    int dot;
     while ((dot = fqn.indexOf('.', p)) >= 0) {
       if (!signature.regionMatches(p, fqn, p, dot - p)) {
         return false;
@@ -428,24 +430,10 @@
     List<String> args = new ArrayList<String>();
     List<String> throwables = exceptions != null ? new ArrayList<String>() : null;
 
-    final PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, StringRef.fromString(canonicalMethodName), flags, null);
+    int modifiersMask = packMethodFlags(access, myResult.isInterface());
+    final PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, StringRef.fromString(canonicalMethodName), flags, signature, args, throwables, desc, modifiersMask);
 
-    final PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packMethodFlags(access, myResult.isInterface()));
-
-    String returnType = null;
-    boolean parsedViaGenericSignature = false;
-    if (signature != null) {
-      try {
-        returnType = parseMethodViaGenericSignature(signature, stub, args, throwables);
-        parsedViaGenericSignature = true;
-      }
-      catch (ClsFormatException ignored) { }
-    }
-    if (returnType == null) {
-      returnType = parseMethodViaDescription(desc, stub, args);
-    }
-
-    stub.setReturnType(TypeInfo.fromString(returnType));
+    PsiModifierListStub modList = (PsiModifierListStub)stub.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST);
 
     if (isEnum && isConstructor && signature == null && args.size() >= 2 && JAVA_LANG_STRING.equals(args.get(0)) && "int".equals(args.get(1))) {
       // exclude synthetic enum constructor parameters
@@ -454,6 +442,7 @@
 
     final boolean isNonStaticInnerClassConstructor =
       isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0;
+    boolean parsedViaGenericSignature = stub.isParsedViaGenericSignature();
     final boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor;
 
     final PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub);
@@ -502,7 +491,8 @@
     }
   }
 
-  private static String parseMethodViaDescription(final String desc, final PsiMethodStubImpl stub, final List<String> args) {
+  @NotNull
+  public static String parseMethodViaDescription(@NotNull String desc, @NotNull PsiMethodStubImpl stub, @NotNull List<String> args) {
     final String returnType = getTypeText(Type.getReturnType(desc));
     final Type[] argTypes = Type.getArgumentTypes(desc);
     for (Type argType : argTypes) {
@@ -512,10 +502,11 @@
     return returnType;
   }
 
-  private static String parseMethodViaGenericSignature(final String signature,
-                                                       final PsiMethodStubImpl stub,
-                                                       final List<String> args,
-                                                       final List<String> throwables) throws ClsFormatException {
+  @NotNull
+  public static String parseMethodViaGenericSignature(@NotNull String signature,
+                                                       @NotNull PsiMethodStubImpl stub,
+                                                       @NotNull List<String> args,
+                                                       @Nullable List<String> throwables) throws ClsFormatException {
     StringCharacterIterator iterator = new StringCharacterIterator(signature);
     SignatureParsing.parseTypeParametersDeclaration(iterator, stub);
 
@@ -651,12 +642,12 @@
     private int myUsedParamSize = 0;
     private int myUsedParamCount = 0;
 
-    private AnnotationParamCollectingVisitor(final PsiMethodStub owner,
-                                             final PsiModifierListStub modList,
+    private AnnotationParamCollectingVisitor(@NotNull PsiMethodStub owner,
+                                             @NotNull PsiModifierListStub modList,
                                              final int ignoreCount,
                                              final int paramIgnoreCount,
                                              final int paramCount,
-                                             final PsiParameterStubImpl[] paramStubs) {
+                                             @NotNull PsiParameterStubImpl[] paramStubs) {
       super(ASM_API);
       myOwner = owner;
       myModList = modList;
@@ -758,7 +749,7 @@
     }
 
     if (value instanceof Double) {
-      final double d = ((Double)value).doubleValue();
+      final double d = (Double)value;
       if (Double.isInfinite(d)) {
         return d > 0 ? DOUBLE_POSITIVE_INF : DOUBLE_NEGATIVE_INF;
       }
@@ -769,7 +760,7 @@
     }
 
     if (value instanceof Float) {
-      final float v = ((Float)value).floatValue();
+      final float v = (Float)value;
 
       if (Float.isInfinite(v)) {
         return v > 0 ? FLOAT_POSITIVE_INF : FLOAT_NEGATIVE_INF;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
index 1463355..13487c5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -21,19 +21,23 @@
 
 import com.intellij.psi.PsiMethod;
 import com.intellij.psi.impl.cache.TypeInfo;
+import com.intellij.psi.impl.compiled.StubBuildingVisitor;
 import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
 import com.intellij.psi.impl.java.stubs.PsiMethodStub;
 import com.intellij.psi.impl.java.stubs.PsiParameterListStub;
 import com.intellij.psi.impl.java.stubs.PsiParameterStub;
 import com.intellij.psi.stubs.StubBase;
 import com.intellij.psi.stubs.StubElement;
+import com.intellij.util.BitUtil;
+import com.intellij.util.cls.ClsFormatException;
 import com.intellij.util.io.StringRef;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
 public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodStub {
-  private TypeInfo myReturnType;
+  private final TypeInfo myReturnType;
   private final byte myFlags;
   private final StringRef myName;
   private StringRef myDefaultValueText;
@@ -43,15 +47,40 @@
   private static final int ANNOTATION = 0x04;
   private static final int DEPRECATED = 0x08;
   private static final int DEPRECATED_ANNOTATION = 0x10;
+  private static final int PARSED_VIA_GENERIC_SIGNATURE = 0x20;
 
-  public PsiMethodStubImpl(StubElement parent, StringRef name, byte flags, StringRef defaultValueText) {
+  public PsiMethodStubImpl(StubElement parent,
+                           StringRef name,
+                           byte flags,
+                           String signature,
+                           @NotNull List<String> args,
+                           @Nullable List<String> throwables,
+                           String desc,
+                           int modifiersMask) {
     super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD);
-    myFlags = flags;
     myName = name;
-    myDefaultValueText = defaultValueText;
+    myDefaultValueText = null;
+
+    new PsiModifierListStubImpl(this, modifiersMask);
+
+    String returnType = null;
+    boolean parsedViaGenericSignature = false;
+    if (signature != null) {
+      try {
+        returnType = StubBuildingVisitor.parseMethodViaGenericSignature(signature, this, args, throwables);
+        parsedViaGenericSignature = true;
+      }
+      catch (ClsFormatException ignored) { }
+    }
+    if (returnType == null) {
+      returnType = StubBuildingVisitor.parseMethodViaDescription(desc, this, args);
+    }
+
+    myReturnType = TypeInfo.fromString(returnType);
+    myFlags = (byte)(flags | (parsedViaGenericSignature ? PARSED_VIA_GENERIC_SIGNATURE : 0));
   }
 
-  public PsiMethodStubImpl(StubElement parent, StringRef name, TypeInfo returnType, byte flags, StringRef defaultValueText) {
+  public PsiMethodStubImpl(StubElement parent, StringRef name, @NotNull TypeInfo returnType, byte flags, StringRef defaultValueText) {
     super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD);
     myReturnType = returnType;
     myFlags = flags;
@@ -59,10 +88,6 @@
     myDefaultValueText = defaultValueText;
   }
 
-  public void setReturnType(TypeInfo returnType) {
-    myReturnType = returnType;
-  }
-
   @Override
   public boolean isConstructor() {
     return (myFlags & CONSTRUCTOR) != 0;
@@ -73,6 +98,9 @@
     return (myFlags & VARARGS) != 0;
   }
 
+  public boolean isParsedViaGenericSignature() {
+    return BitUtil.isSet(myFlags, PARSED_VIA_GENERIC_SIGNATURE);
+  }
   @Override
   public boolean isAnnotationMethod() {
     return isAnnotationMethod(myFlags);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index 58b1e22..b2c934e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -86,12 +86,13 @@
 
   @Nullable
   public <T extends PsiExpression> PsiType getType(@NotNull T expr, @NotNull Function<T, PsiType> f) {
-    PsiType type = getCachedType(expr);
+    final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck();
+    PsiType type = !isOverloadCheck ? getCachedType(expr) : null;
     if (type == null) {
       final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack();
       final RecursionGuard.StackStamp gStackStamp = PsiResolveHelper.ourGraphGuard.markStack();
       type = f.fun(expr);
-      if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow() || !MethodCandidateInfo.ourOverloadGuard.currentStack().isEmpty()) {
+      if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow() || isOverloadCheck) {
         return type;
       }
       if (type == null) type = TypeConversionUtil.NULL_TYPE;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 6098199..7d6166a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -349,13 +349,17 @@
   }
 
   public boolean initBounds(PsiTypeParameter... typeParameters) {
+    return initBounds(myContext, typeParameters);
+  }
+
+  public boolean initBounds(PsiElement context, PsiTypeParameter... typeParameters) {
     boolean sameMethodCall = false;
     for (PsiTypeParameter parameter : typeParameters) {
       if (myInferenceVariables.containsKey(parameter)) {
         sameMethodCall = true;
         continue;
       }
-      InferenceVariable variable = new InferenceVariable(parameter);
+      InferenceVariable variable = new InferenceVariable(context, parameter);
       boolean added = false;
       final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
       for (PsiType classType : extendsListTypes) {
@@ -415,7 +419,7 @@
           for (int i = 0; i < typeParameters.length; i++) {
             PsiTypeParameter typeParameter = typeParameters[i];
             copy[i] = elementFactory.createTypeParameterFromText("rCopy" + typeParameter.getName(), null);
-            initBounds(copy[i]);
+            initBounds(myContext, copy[i]);
             subst = subst.put(typeParameter, elementFactory.createType(copy[i]));
           }
           final PsiType substitutedCapture = PsiUtil.captureToplevelWildcards(subst.substitute(returnType), myContext);
@@ -446,7 +450,7 @@
   }
   
   private static boolean hasPrimitiveWrapperBound(InferenceVariable inferenceVariable) {
-    final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER};
+    final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER, InferenceBound.EQ};
     for (InferenceBound inferenceBound : boundTypes) {
       final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
       for (PsiType bound : bounds) {
@@ -701,7 +705,7 @@
         final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
         final PsiType lub = getLowerBound(var, substitutor);
         final PsiType glb = getUpperBound(var, substitutor);
-        final InferenceVariable zVariable = new InferenceVariable(copy);
+        final InferenceVariable zVariable = new InferenceVariable(var.getCallContext(), copy);
         zVariable.addBound(glb, InferenceBound.UPPER);
         if (lub != PsiType.NULL) {
           if (!TypeConversionUtil.isAssignable(glb, lub)) {
@@ -1026,7 +1030,7 @@
                                        boolean varargs) {
     final InferenceSession session = new InferenceSession(PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, m2.getManager(), context);
     for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) {
-      session.initBounds(param);
+      session.initBounds(context, param);
     }
 
     final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
@@ -1250,14 +1254,17 @@
     return myIncorporationPhase.hasCaptureConstraints(Arrays.asList(inferenceVariable));
   }
 
-  public void liftBounds(Collection<InferenceVariable> variables) {
+  public void liftBounds(PsiElement context, Collection<InferenceVariable> variables) {
     for (InferenceVariable variable : variables) {
       final PsiTypeParameter parameter = variable.getParameter();
       final InferenceVariable inferenceVariable = getInferenceVariable(parameter);
       if (inferenceVariable != null) {
-        for (InferenceBound boundType : InferenceBound.values()) {
-          for (PsiType bound : variable.getBounds(boundType)) {
-            inferenceVariable.addBound(bound, boundType);
+        final PsiElement callContext = inferenceVariable.getCallContext();
+        if (context.equals(callContext) || myContext.equals(callContext)) {
+          for (InferenceBound boundType : InferenceBound.values()) {
+            for (PsiType bound : variable.getBounds(boundType)) {
+              inferenceVariable.addBound(bound, boundType);
+            }
           }
         }
       } else {
@@ -1270,4 +1277,8 @@
     final Boolean erased = call.getUserData(ERASED);
     return erased != null && erased.booleanValue();
   }
+
+  public PsiElement getContext() {
+    return myContext;
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
index a606e90..a19961f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
@@ -26,6 +26,8 @@
  * User: anna
  */
 public class InferenceVariable extends LightTypeParameter {
+  private PsiElement myContext;
+
   public PsiTypeParameter getParameter() {
     return getDelegate();
   }
@@ -35,8 +37,9 @@
 
   private PsiType myInstantiation = PsiType.NULL;
 
-  InferenceVariable(PsiTypeParameter parameter) {
+  InferenceVariable(PsiElement context, PsiTypeParameter parameter) {
     super(parameter);
+    myContext = context;
   }
 
   public PsiType getInstantiation() {
@@ -129,4 +132,8 @@
   public String toString() {
     return getDelegate().toString();
   }
+
+  public PsiElement getCallContext() {
+    return myContext;
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index c33e2c3..82b320a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -110,7 +110,7 @@
         if (typeParams != null) {
 
           final Set<PsiTypeParameter> oldBounds = ContainerUtil.newHashSet(session.getParamsToInfer());
-          final boolean sameMethodCall = session.initBounds(typeParams);
+          final boolean sameMethodCall = session.initBounds(myExpression, typeParams);
           PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
           final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
           session.collectDependencies(returnType, variables);
@@ -138,8 +138,8 @@
           }
 
           final Collection<PsiTypeParameter> params1 = session.getTypeParams();
-          final InferenceSession callSession = new InferenceSession(params1.toArray(new PsiTypeParameter[params1.size()]), substitutor, myExpression.getManager(), myExpression);
-          callSession.initBounds(params);
+          final InferenceSession callSession = new InferenceSession(params, substitutor, myExpression.getManager(), myExpression);
+          callSession.initBounds(session.getContext(), params1.toArray(new PsiTypeParameter[params1.size()]));
           if (method != null) {
             final PsiExpression[] args = argumentList.getExpressions();
             final PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -163,7 +163,7 @@
                 }
               }
             }
-            session.liftBounds(inferenceVariables);
+            session.liftBounds(myExpression, inferenceVariables);
           } else {
             return false;
           }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
index 18d0c49..9516265 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
@@ -91,7 +91,7 @@
       }
       final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY;
       if (targetParameters.length == parameters.length + 1) {
-        specialCase(session, constraints, substitutor, targetParameters);
+        specialCase(session, constraints, substitutor, targetParameters, true);
         for (int i = 1; i < targetParameters.length; i++) {
           constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), substitutor.substitute(targetParameters[i].getType())));
         }
@@ -198,7 +198,7 @@
       final PsiParameter[] parameters = method.getParameterList().getParameters();
       if (targetParameters.length == parameters.length + 1 && !method.isVarArgs() && 
           PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) { //todo specification bug?
-        specialCase(session, constraints, substitutor, targetParameters);
+        specialCase(session, constraints, substitutor, targetParameters, false);
       }
       constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(referencedMethodReturnType)));
     }
@@ -209,7 +209,8 @@
   private void specialCase(InferenceSession session,
                            List<ConstraintFormula> constraints,
                            PsiSubstitutor substitutor,
-                           PsiParameter[] targetParameters) {
+                           PsiParameter[] targetParameters,
+                           boolean ignoreRaw) {
     final PsiElement qualifier = myExpression.getQualifier();
     PsiType qualifierType = null;
     if (qualifier instanceof PsiTypeElement) {
@@ -226,8 +227,7 @@
         final PsiElement res = resolveResult.getElement();
         if (res instanceof PsiClass) {
           PsiClass containingClass = (PsiClass)res;
-          final boolean isRawSubst = !myExpression.isConstructor() &&
-                                     PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
+          final boolean isRawSubst = !ignoreRaw && !myExpression.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
           qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
         }
       }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
index e2af7b0..d4d0f3f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.DummyHolder;
 import com.intellij.psi.impl.source.SourceJavaCodeReference;
 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
@@ -142,4 +143,41 @@
     TreeUtil.clearCaches(TreeUtil.getFileElement(parenthExpr));
     return parenthExpr;
   }
+
+  public static void deleteSeparatingComma(@NotNull CompositeElement element, @NotNull ASTNode child) {
+    assert child.getElementType() != JavaTokenType.COMMA : child;
+
+    ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
+    if (next != null && next.getElementType() == JavaTokenType.COMMA) {
+      element.deleteChildInternal(next);
+    }
+    else {
+      ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
+      if (prev != null && prev.getElementType() == JavaTokenType.COMMA) {
+        element.deleteChildInternal(prev);
+      }
+    }
+  }
+
+  public static void addSeparatingComma(@NotNull CompositeElement element, @NotNull ASTNode child, @NotNull TokenSet listTypes) {
+    assert child.getElementType() != JavaTokenType.COMMA : child;
+
+    scanChildren(element, child, listTypes, true);
+    scanChildren(element, child, listTypes, false);
+  }
+
+  private static void scanChildren(CompositeElement element, ASTNode node, TokenSet listTypes, boolean forward) {
+    ASTNode child = node;
+    while (true) {
+      child = (forward ? child.getTreeNext() : child.getTreePrev());
+      if (child == null || child.getElementType() == JavaTokenType.COMMA) break;
+      if (listTypes.contains(child.getElementType())) {
+        CharTable charTable = SharedImplUtil.findCharTableByTree(element);
+        PsiManager manager = element.getPsi().getManager();
+        TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, charTable, manager);
+        element.addInternal(comma, comma, (forward ? node : child), Boolean.FALSE);
+        break;
+      }
+    }
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
index 4953bd2..e1ffc8b 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -19,8 +19,9 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.tree.*;
-import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.CharTable;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
@@ -28,47 +29,29 @@
 /**
  * @author ven
  */
-public class AnnotationParamListElement extends PsiCommaSeparatedListImpl implements PsiAnnotationParameterList {
+public class AnnotationParamListElement extends CompositeElement {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.AnnotationParamListElement");
-  private volatile PsiNameValuePair[] myCachedMembers = null;
+  private static final TokenSet NAME_VALUE_PAIR_BIT_SET = TokenSet.create(JavaElementType.NAME_VALUE_PAIR);
 
   public AnnotationParamListElement() {
-    super(ANNOTATION_PARAMETER_LIST, NAME_VALUE_PAIR_BIT_SET);
-  }
-
-  @Override
-  public void clearCaches() {
-    super.clearCaches();
-    myCachedMembers = null;
-  }
-
-  @Override
-  @NotNull
-  public PsiNameValuePair[] getAttributes() {
-    PsiNameValuePair[] cachedMembers = myCachedMembers;
-    if (cachedMembers == null) {
-      myCachedMembers = cachedMembers = getChildrenAsPsiElements(NAME_VALUE_PAIR_BIT_SET, PsiNameValuePair.ARRAY_FACTORY);
-    }
-
-    return cachedMembers;
+    super(JavaElementType.ANNOTATION_PARAMETER_LIST);
   }
 
   @Override
   public int getChildRole(ASTNode child) {
     IElementType i = child.getElementType();
-    if (i == COMMA) {
+    if (i == JavaTokenType.COMMA) {
       return ChildRole.COMMA;
     }
-    else if (i == LPARENTH) {
+    else if (i == JavaTokenType.LPARENTH) {
       return ChildRole.LPARENTH;
     }
-    else if (i == RPARENTH) {
+    else if (i == JavaTokenType.RPARENTH) {
       return ChildRole.RPARENTH;
     }
-    else if (ANNOTATION_MEMBER_VALUE_BIT_SET.contains(child.getElementType())
-             || (i == NAME_VALUE_PAIR && child.getFirstChildNode() != null
-                 && child.getFirstChildNode().getElementType() == ANNOTATION_ARRAY_INITIALIZER))
-    {
+    else if (ElementType.ANNOTATION_MEMBER_VALUE_BIT_SET.contains(i) ||
+             (i == JavaElementType.NAME_VALUE_PAIR && child.getFirstChildNode() != null &&
+              child.getFirstChildNode().getElementType() == JavaElementType.ANNOTATION_ARRAY_INITIALIZER)) {
       return ChildRole.ANNOTATION_VALUE;
     }
     else {
@@ -83,65 +66,69 @@
         LOG.assertTrue(false);
         return null;
       case ChildRole.LPARENTH:
-        return findChildByType(LPARENTH);
+        return findChildByType(JavaTokenType.LPARENTH);
 
       case ChildRole.RPARENTH:
-        return findChildByType(RPARENTH);
-    }
-  }
-
-  public String toString() {
-    return "PsiAnnotationParameterList";
-  }
-
-  @Override
-  public void accept(@NotNull PsiElementVisitor visitor) {
-    if (visitor instanceof JavaElementVisitor) {
-      ((JavaElementVisitor)visitor).visitAnnotationParameterList(this);
-    }
-    else {
-      visitor.visitElement(this);
+        return findChildByType(JavaTokenType.RPARENTH);
     }
   }
 
   @Override
   public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
-    if (first.getElementType() == NAME_VALUE_PAIR && last.getElementType() == NAME_VALUE_PAIR) {
-      final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
-      ASTNode lparenth = findChildByRole(ChildRole.LPARENTH);
+    if (first.getElementType() == JavaElementType.NAME_VALUE_PAIR && last.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
+      ASTNode lparenth = findChildByType(JavaTokenType.LPARENTH);
       if (lparenth == null) {
-        LeafElement created = Factory.createSingleLeafElement(LPARENTH, "(", 0, 1, treeCharTab, getManager());
+        CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
+        LeafElement created = Factory.createSingleLeafElement(JavaTokenType.LPARENTH, "(", 0, 1, treeCharTab, getManager());
         super.addInternal(created, created, getFirstChildNode(), true);
       }
-      ASTNode rparenth = findChildByRole(ChildRole.RPARENTH);
+
+      ASTNode rparenth = findChildByType(JavaTokenType.RPARENTH);
       if (rparenth == null) {
-        LeafElement created = Factory.createSingleLeafElement(RPARENTH, ")", 0, 1, treeCharTab, getManager());
+        CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
+        LeafElement created = Factory.createSingleLeafElement(JavaTokenType.RPARENTH, ")", 0, 1, treeCharTab, getManager());
         super.addInternal(created, created, getLastChildNode(), false);
       }
 
-      final ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
+      ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
       if (nodes.length == 1) {
-        final ASTNode node = nodes[0];
+        ASTNode node = nodes[0];
         if (node instanceof PsiNameValuePair) {
-          final PsiNameValuePair pair = (PsiNameValuePair)node;
+          PsiNameValuePair pair = (PsiNameValuePair)node;
           if (pair.getName() == null) {
-            final String text = pair.getValue().getText();
-            try {
-              final PsiAnnotation annotation = JavaPsiFacade.getInstance(getProject()).getElementFactory().createAnnotationFromText("@AAA(value = " + text + ")", null);
-              replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
-            }
-            catch (IncorrectOperationException e) {
-              LOG.error(e);
+            PsiAnnotationMemberValue value = pair.getValue();
+            if (value != null) {
+              try {
+                PsiElementFactory factory = JavaPsiFacade.getInstance(getPsi().getProject()).getElementFactory();
+                PsiAnnotation annotation = factory.createAnnotationFromText("@AAA(value = " + value.getText() + ")", null);
+                replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
+              }
+              catch (IncorrectOperationException e) {
+                LOG.error(e);
+              }
             }
           }
         }
       }
 
       if (anchor == null && before != null) {
-        anchor = findChildByRole(before.booleanValue() ? ChildRole.RPARENTH : ChildRole.LPARENTH);
+        anchor = findChildByType(before ? JavaTokenType.RPARENTH : JavaTokenType.LPARENTH);
       }
+
+      TreeElement firstAdded = super.addInternal(first, last, anchor, before);
+      JavaSourceUtil.addSeparatingComma(this, first, NAME_VALUE_PAIR_BIT_SET);
+      return firstAdded;
     }
 
     return super.addInternal(first, last, anchor, before);
   }
+
+  @Override
+  public void deleteChildInternal(@NotNull ASTNode child) {
+    if (child.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
+      JavaSourceUtil.deleteSeparatingComma(this, child);
+    }
+
+    super.deleteChildInternal(child);
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
index 712b32c..14d72a9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -34,6 +34,15 @@
 public class ClassElement extends CompositeElement implements Constants {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ClassElement");
 
+  private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET = TokenSet.create(
+    PUBLIC_KEYWORD, ABSTRACT_KEYWORD, STATIC_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD);
+  private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET_18_METHOD = TokenSet.create(
+    PUBLIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD);
+  private static final TokenSet MODIFIERS_TO_REMOVE_IN_ENUM_BIT_SET = TokenSet.create(
+    PUBLIC_KEYWORD, FINAL_KEYWORD);
+  private static final TokenSet ENUM_CONSTANT_LIST_ELEMENTS_BIT_SET = TokenSet.create(
+    ENUM_CONSTANT, COMMA, SEMICOLON);
+
   public ClassElement(IElementType type) {
     super(type);
   }
@@ -181,19 +190,8 @@
 
   @Override
   public void deleteChildInternal(@NotNull ASTNode child) {
-    if (isEnum()) {
-      if (child.getElementType() == ENUM_CONSTANT) {
-        ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-        if (next != null && next.getElementType() == COMMA) {
-          deleteChildInternal(next);
-        }
-        else {
-          ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-          if (prev != null && prev.getElementType() == COMMA) {
-            deleteChildInternal(prev);
-          }
-        }
-      }
+    if (isEnum() && child.getElementType() == ENUM_CONSTANT) {
+      JavaSourceUtil.deleteSeparatingComma(this, child);
     }
 
     if (child.getElementType() == FIELD) {
@@ -233,27 +231,6 @@
     return findChildByRole(ChildRole.AT) != null;
   }
 
-  private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET = TokenSet.create(
-    PUBLIC_KEYWORD, ABSTRACT_KEYWORD,
-    STATIC_KEYWORD, FINAL_KEYWORD,
-    NATIVE_KEYWORD
-  );
-
-  private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET_18_METHOD = TokenSet.create(
-    PUBLIC_KEYWORD, ABSTRACT_KEYWORD,
-    FINAL_KEYWORD,
-    NATIVE_KEYWORD
-  );
-
-  private static final TokenSet MODIFIERS_TO_REMOVE_IN_ENUM_BIT_SET = TokenSet.create(
-    PUBLIC_KEYWORD, FINAL_KEYWORD
-  );
-
-  private static final TokenSet ENUM_CONSTANT_LIST_ELEMENTS_BIT_SET = TokenSet.create(
-    ENUM_CONSTANT, COMMA, SEMICOLON
-  );
-
-
   @Override
   public ASTNode findChildByRole(int role) {
     assert ChildRole.isUnique(role);
@@ -266,10 +243,7 @@
         return PsiImplUtil.findDocComment(this);
 
       case ChildRole.ENUM_CONSTANT_LIST_DELIMITER:
-        if (!isEnum()) {
-          return null;
-        }
-        return findEnumConstantListDelimiter();
+        return isEnum() ? findEnumConstantListDelimiter() : null;
 
       case ChildRole.MODIFIER_LIST:
         return findChildByType(MODIFIER_LIST);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
index a5e32e9..20d504d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,18 +18,21 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.tree.*;
+import com.intellij.psi.impl.source.tree.ChildRole;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.JavaSourceUtil;
+import com.intellij.psi.impl.source.tree.TreeElement;
 import com.intellij.psi.tree.ChildRoleBase;
 import com.intellij.psi.tree.IElementType;
-import com.intellij.util.CharTable;
+import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ParameterListElement extends CompositeElement implements Constants {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ParameterListElement");
+  private static final TokenSet PARAMETER_SET = TokenSet.create(PARAMETER);
 
   public ParameterListElement() {
     super(PARAMETER_LIST);
@@ -49,23 +52,7 @@
     }
     TreeElement firstAdded = super.addInternal(first, last, anchor, before);
     if (first == last && first.getElementType() == PARAMETER) {
-      final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
-      for (ASTNode child = ((ASTNode)first).getTreeNext(); child != null; child = child.getTreeNext()) {
-        if (child.getElementType() == COMMA) break;
-        if (child.getElementType() == PARAMETER) {
-          TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, first, Boolean.FALSE);
-          break;
-        }
-      }
-      for (ASTNode child = ((ASTNode)first).getTreePrev(); child != null; child = child.getTreePrev()) {
-        if (child.getElementType() == COMMA) break;
-        if (child.getElementType() == PARAMETER) {
-          TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, child, Boolean.FALSE);
-          break;
-        }
-      }
+      JavaSourceUtil.addSeparatingComma(this, first, PARAMETER_SET);
     }
 
     //todo[max] hack?
@@ -83,16 +70,7 @@
     final TreeElement oldLastNodeInsideParens = getLastNodeInsideParens();
     final TreeElement oldFirstNodeInsideParens = getFirstNodeInsideParens();
     if (child.getElementType() == PARAMETER) {
-      ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-      if (next != null && next.getElementType() == COMMA) {
-        deleteChildInternal(next);
-      }
-      else {
-        ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-        if (prev != null && prev.getElementType() == COMMA) {
-          deleteChildInternal(prev);
-        }
-      }
+      JavaSourceUtil.deleteSeparatingComma(this, child);
     }
     super.deleteChildInternal(child);
 
@@ -135,20 +113,12 @@
         return null;
 
       case ChildRole.LPARENTH:
-        if (getFirstChildNode().getElementType() == LPARENTH) {
-          return getFirstChildNode();
-        }
-        else {
-          return null;
-        }
+        TreeElement firstNode = getFirstChildNode();
+        return firstNode.getElementType() == LPARENTH ? firstNode : null;
 
       case ChildRole.RPARENTH:
-        if (getLastChildNode().getElementType() == RPARENTH) {
-          return getLastChildNode();
-        }
-        else {
-          return null;
-        }
+        TreeElement lastNode = getLastChildNode();
+        return lastNode.getElementType() == RPARENTH ? lastNode : null;
     }
   }
 
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
index 5a3ccb2..0923d7c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -16,20 +16,20 @@
 package com.intellij.psi.impl.source.tree.java;
 
 import com.intellij.lang.ASTNode;
+import com.intellij.psi.JavaElementVisitor;
 import com.intellij.psi.PsiAnnotationParameterList;
+import com.intellij.psi.PsiElementVisitor;
 import com.intellij.psi.PsiNameValuePair;
 import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
 import com.intellij.psi.impl.java.stubs.PsiAnnotationParameterListStub;
 import com.intellij.psi.impl.source.JavaStubPsiElement;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Dmitry Avdeev
- *         Date: 7/27/12
+ * @since 27.07.2012
  */
-public class PsiAnnotationParamListImpl extends JavaStubPsiElement<PsiAnnotationParameterListStub> implements
-                                                                                                       PsiAnnotationParameterList {
+public class PsiAnnotationParamListImpl extends JavaStubPsiElement<PsiAnnotationParameterListStub> implements PsiAnnotationParameterList {
   public PsiAnnotationParamListImpl(@NotNull PsiAnnotationParameterListStub stub) {
     super(stub, JavaStubElementTypes.ANNOTATION_PARAMETER_LIST);
   }
@@ -44,8 +44,18 @@
     return getStubOrPsiChildren(JavaStubElementTypes.NAME_VALUE_PAIR, PsiNameValuePair.ARRAY_FACTORY);
   }
 
-  @NonNls
-  public String toString(){
-    return "PsiAnnotationParameterList:" + getText();
+  @Override
+  public void accept(@NotNull PsiElementVisitor visitor) {
+    if (visitor instanceof JavaElementVisitor) {
+      ((JavaElementVisitor)visitor).visitAnnotationParameterList(this);
+    }
+    else {
+      visitor.visitElement(this);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "PsiAnnotationParameterList";
   }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
index dd64ed7..b03766f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,68 +17,84 @@
 
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.JavaElementVisitor;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiArrayInitializerMemberValue;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.impl.source.tree.ChildRole;
-import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.*;
 import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author ven
  */
-public class PsiArrayInitializerMemberValueImpl extends PsiCommaSeparatedListImpl implements PsiArrayInitializerMemberValue {
-  private static final Logger LOG = Logger.getInstance("com.intellij.psi.impl.source.tree.java.PsiArrayInitializerMemberValueImpl");
+public class PsiArrayInitializerMemberValueImpl extends CompositePsiElement implements PsiArrayInitializerMemberValue {
+  private static final Logger LOG = Logger.getInstance(PsiArrayInitializerMemberValueImpl.class);
+  private static final TokenSet MEMBER_SET = ElementType.ANNOTATION_MEMBER_VALUE_BIT_SET;
+
   public PsiArrayInitializerMemberValueImpl() {
-    super(ANNOTATION_ARRAY_INITIALIZER, ANNOTATION_MEMBER_VALUE_BIT_SET);
+    super(JavaElementType.ANNOTATION_ARRAY_INITIALIZER);
   }
 
   @Override
   @NotNull
   public PsiAnnotationMemberValue[] getInitializers() {
-    return getChildrenAsPsiElements(ANNOTATION_MEMBER_VALUE_BIT_SET, PsiAnnotationMemberValue.ARRAY_FACTORY);
+    return getChildrenAsPsiElements(MEMBER_SET, PsiAnnotationMemberValue.ARRAY_FACTORY);
   }
 
   @Override
   public ASTNode findChildByRole(int role) {
     LOG.assertTrue(ChildRole.isUnique(role));
-    switch(role){
+
+    switch (role) {
       default:
         return null;
 
       case ChildRole.LBRACE:
-        return findChildByType(LBRACE);
+        return findChildByType(JavaTokenType.LBRACE);
 
       case ChildRole.RBRACE:
-        return findChildByType(RBRACE);
+        return findChildByType(JavaTokenType.RBRACE);
     }
   }
 
   @Override
   public int getChildRole(ASTNode child) {
     LOG.assertTrue(child.getTreeParent() == this);
+
     IElementType i = child.getElementType();
-    if (i == COMMA) {
+    if (i == JavaTokenType.COMMA) {
       return ChildRole.COMMA;
     }
-    else if (i == LBRACE) {
+    else if (i == JavaTokenType.LBRACE) {
       return ChildRole.LBRACE;
     }
-    else if (i == RBRACE) {
+    else if (i == JavaTokenType.RBRACE) {
       return ChildRole.RBRACE;
     }
-    else {
-      if (ANNOTATION_MEMBER_VALUE_BIT_SET.contains(child.getElementType())) {
-        return ChildRole.ANNOTATION_VALUE;
-      }
-      return ChildRoleBase.NONE;
+    else if (MEMBER_SET.contains(child.getElementType())) {
+      return ChildRole.ANNOTATION_VALUE;
     }
+    return ChildRoleBase.NONE;
   }
 
-  public String toString(){
-    return "PsiArrayInitializerMemberValue:" + getText();
+  @Override
+  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
+    if (MEMBER_SET.contains(first.getElementType()) && MEMBER_SET.contains(last.getElementType())) {
+      TreeElement firstAdded = super.addInternal(first, last, anchor, before);
+      JavaSourceUtil.addSeparatingComma(this, first, MEMBER_SET);
+      return firstAdded;
+    }
+
+    return super.addInternal(first, last, anchor, before);
+  }
+
+  @Override
+  public void deleteChildInternal(@NotNull ASTNode child) {
+    if (MEMBER_SET.contains(child.getElementType())) {
+      JavaSourceUtil.deleteSeparatingComma(this, child);
+    }
+
+    super.deleteChildInternal(child);
   }
 
   @Override
@@ -90,4 +106,9 @@
       visitor.visitElement(this);
     }
   }
+
+  @Override
+  public String toString() {
+    return "PsiArrayInitializerMemberValue:" + getText();
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java
deleted file mode 100644
index 475542f..0000000
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2000-2009 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.psi.impl.source.tree.java;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.psi.impl.PsiImplUtil;
-import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.tree.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.CharTable;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Adds or removes comma
- *
- * @author ven
- */
-public abstract class PsiCommaSeparatedListImpl extends CompositePsiElement implements Constants {
-  private final TokenSet myTypesOfElements;
-
-  protected PsiCommaSeparatedListImpl(IElementType type, final TokenSet typeOfElements) {
-    super(type);
-    myTypesOfElements = typeOfElements;
-  }
-
-  @Override
-  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
-    if (myTypesOfElements.contains(first.getElementType()) && myTypesOfElements.contains(last.getElementType())) {
-      final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
-      final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
-      for (ASTNode child = ((ASTNode)first).getTreeNext(); child != null; child = child.getTreeNext()) {
-        if (child.getElementType() == COMMA) break;
-        if (myTypesOfElements.contains(child.getElementType())) {
-          TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, first, Boolean.FALSE);
-          break;
-        }
-      }
-
-      for (ASTNode child = ((ASTNode)first).getTreePrev(); child != null; child = child.getTreePrev()) {
-        if (child.getElementType() == COMMA) break;
-        if (myTypesOfElements.contains(child.getElementType())) {
-          TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, child, Boolean.FALSE);
-          break;
-        }
-      }
-      return firstAdded;
-    }
-
-    return super.addInternal(first, last, anchor, before);
-  }
-
-  @Override
-  public void deleteChildInternal(@NotNull ASTNode child) {
-    if (myTypesOfElements.contains(child.getElementType())) {
-      ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-      if (next != null && next.getElementType() == COMMA) {
-        deleteChildInternal(next);
-      }
-      else {
-        ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-        if (prev != null && prev.getElementType() == COMMA) {
-          deleteChildInternal(prev);
-        }
-      }
-    }
-    super.deleteChildInternal(child);
-  }
-}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
index ae45273..98df0ba 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -18,7 +18,6 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.tree.*;
 import com.intellij.psi.tree.ChildRoleBase;
 import com.intellij.psi.tree.IElementType;
@@ -123,7 +122,8 @@
     }
     TreeElement firstAdded = super.addInternal(first, last, anchor, before);
     if (ElementType.EXPRESSION_BIT_SET.contains(first.getElementType())) {
-      ASTNode element = first;
+      JavaSourceUtil.addSeparatingComma(this, first, ElementType.EXPRESSION_BIT_SET);
+      /*ASTNode element = first;
       for (ASTNode child = element.getTreeNext(); child != null; child = child.getTreeNext()) {
         if (child.getElementType() == JavaTokenType.COMMA) break;
         if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
@@ -140,7 +140,7 @@
           super.addInternal(comma, comma, child, Boolean.FALSE);
           break;
         }
-      }
+      }*/
     }
     return firstAdded;
   }
@@ -148,17 +148,9 @@
   @Override
   public void deleteChildInternal(@NotNull ASTNode child) {
     if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
-      ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-      if (next != null && next.getElementType() == JavaTokenType.COMMA) {
-        deleteChildInternal(next);
-      }
-      else {
-        ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-        if (prev != null && prev.getElementType() == JavaTokenType.COMMA) {
-          deleteChildInternal(prev);
-        }
-      }
+      JavaSourceUtil.deleteSeparatingComma(this, child);
     }
+
     super.deleteChildInternal(child);
   }
 
@@ -172,6 +164,7 @@
     }
   }
 
+  @Override
   public String toString() {
     return "PsiExpressionList";
   }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
index 95171ba..32ed1aa 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
@@ -25,6 +25,7 @@
 import com.intellij.psi.impl.source.resolve.ResolveCache;
 import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
 import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
 import com.intellij.psi.impl.source.tree.ChildRole;
 import com.intellij.psi.impl.source.tree.FileElement;
 import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -39,13 +40,12 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.*;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
@@ -153,7 +153,8 @@
         if (arrayClass == containingClass) {
           final PsiType componentType = qualifierResolveResult.getSubstitutor().substitute(arrayClass.getTypeParameters()[0]);
           LOG.assertTrue(componentType != null, qualifierResolveResult.getSubstitutor());
-          methods = new PsiMethod[] {factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this)};
+          //15.13.1 A method reference expression of the form ArrayType :: new is always exact.
+          return factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this);
         } else {
           methods = containingClass.getConstructors();
         }
@@ -172,25 +173,38 @@
           if (psiMethod.getTypeParameters().length > 0) {
             final PsiReferenceParameterList parameterList = getParameterList();
             return parameterList != null && parameterList.getTypeParameterElements().length > 0 ? psiMethod : null;
-          }
-        }
-        if (containingClass.isPhysical() && containingClass.hasTypeParameters()) {
-          final PsiElement qualifier = getQualifier();
-          if (qualifier instanceof PsiTypeElement) {
-            final PsiJavaCodeReferenceElement referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
-            if (referenceElement != null) {
-              final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
-              if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
-                return null;
+          } else {
+            final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiMethod.getContainingClass(), containingClass, PsiSubstitutor.EMPTY);
+            final Set<PsiType> signature = new HashSet<PsiType>(Arrays.asList(psiMethod.getSignature(PsiSubstitutor.EMPTY).getParameterTypes()));
+            signature.add(psiMethod.getReturnType());
+            boolean free = true;
+            for (PsiType type : signature) {
+              if (classSubstitutor != null) {
+                type = classSubstitutor.substitute(type);
+              }
+              if (type != null && PsiPolyExpressionUtil.mentionsTypeParameters(type, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) {
+                free = false;
+                break;
               }
             }
+            if (free) return psiMethod;
+          }
+        }
+        if (containingClass.hasTypeParameters()) {
+          final PsiElement qualifier = getQualifier();
+          PsiJavaCodeReferenceElement referenceElement = null;
+          if (qualifier instanceof PsiTypeElement) {
+            referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
           } else if (qualifier instanceof PsiReferenceExpression) {
             final PsiReferenceExpression expression = (PsiReferenceExpression)qualifier;
             if (qualifierResolveResult.isReferenceTypeQualified()) {
-              final PsiReferenceParameterList parameterList = expression.getParameterList();
-              if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
-                return null;
-              }
+              referenceElement = expression;
+            }
+          }
+          if (referenceElement != null) {
+            final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
+            if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
+              return null;
             }
           }
         }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
index e85e81c..743bd36 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
 import com.intellij.psi.impl.source.tree.*;
 import com.intellij.psi.tree.ChildRoleBase;
 import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.CharTable;
 import org.jetbrains.annotations.NotNull;
 
@@ -30,6 +31,7 @@
  */
 public class PsiReferenceParameterListImpl extends CompositePsiElement implements PsiReferenceParameterList {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiReferenceParameterListImpl");
+  private static final TokenSet TYPE_SET = TokenSet.create(JavaElementType.TYPE);
 
   public PsiReferenceParameterListImpl() {
     super(JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -124,23 +126,8 @@
 
     final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
 
-    if (first == last && first.getElementType() == JavaElementType.TYPE){
-      for(ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()){
-        if (child.getElementType() == JavaTokenType.COMMA) break;
-        if (child.getElementType() == JavaElementType.TYPE){
-          TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, first, Boolean.FALSE);
-          break;
-        }
-      }
-      for(ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()){
-        if (child.getElementType() == JavaTokenType.COMMA) break;
-        if (child.getElementType() == JavaElementType.TYPE){
-          TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, child, Boolean.FALSE);
-          break;
-        }
-      }
+    if (first == last && first.getElementType() == JavaElementType.TYPE) {
+      JavaSourceUtil.addSeparatingComma(this, first, TYPE_SET);
     }
 
     return firstAdded;
@@ -148,17 +135,8 @@
 
   @Override
   public void deleteChildInternal(@NotNull ASTNode child) {
-    if (child.getElementType() == JavaElementType.TYPE){
-      ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-      if (next != null && next.getElementType() == JavaTokenType.COMMA){
-        deleteChildInternal(next);
-      }
-      else{
-        ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-        if (prev != null && prev.getElementType() == JavaTokenType.COMMA){
-          deleteChildInternal(prev);
-        }
-      }
+    if (child.getElementType() == JavaElementType.TYPE) {
+      JavaSourceUtil.deleteSeparatingComma(this, child);
     }
 
     super.deleteChildInternal(child);
@@ -186,6 +164,7 @@
     }
   }
 
+  @Override
   public String toString() {
     return "PsiReferenceParameterList";
   }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
index 43d9d80..2a3bdba 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
 import com.intellij.psi.impl.source.tree.*;
 import com.intellij.psi.tree.ChildRoleBase;
 import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.CharTable;
 import org.jetbrains.annotations.NotNull;
 
@@ -30,6 +31,7 @@
  */
 public class TypeParameterListElement extends CompositeElement {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.TypeParameterListElement");
+  private static final TokenSet TYPE_PARAMETER_SET = TokenSet.create(JavaElementType.TYPE_PARAMETER);
 
   public TypeParameterListElement() {
     super(JavaElementType.TYPE_PARAMETER_LIST);
@@ -82,25 +84,9 @@
       }
     }
 
-    final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
-
+    TreeElement firstAdded = super.addInternal(first, last, anchor, before);
     if (first == last && first.getElementType() == JavaElementType.TYPE_PARAMETER) {
-      for(ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()){
-        if (child.getElementType() == JavaTokenType.COMMA) break;
-        if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
-          final TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, first, Boolean.FALSE);
-          break;
-        }
-      }
-      for(ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()){
-        if (child.getElementType() == JavaTokenType.COMMA) break;
-        if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
-          final TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
-          super.addInternal(comma, comma, child, Boolean.FALSE);
-          break;
-        }
-      }
+      JavaSourceUtil.addSeparatingComma(this, first, TYPE_PARAMETER_SET);
     }
     return firstAdded;
   }
@@ -108,18 +94,11 @@
   @Override
   public void deleteChildInternal(@NotNull final ASTNode child) {
     if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
-      final ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
-      if (next != null && next.getElementType() == JavaTokenType.COMMA){
-        deleteChildInternal(next);
-      }
-      else{
-        final ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
-        if (prev != null && prev.getElementType() == JavaTokenType.COMMA){
-          deleteChildInternal(prev);
-        }
-      }
+      JavaSourceUtil.deleteSeparatingComma(this, child);
     }
+
     super.deleteChildInternal(child);
+
     if (child.getElementType() == JavaElementType.TYPE_PARAMETER) {
       final ASTNode lt = findChildByRole(ChildRole.LT_IN_TYPE_LIST);
       final ASTNode next = PsiImplUtil.skipWhitespaceAndComments(lt.getTreeNext());
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
index 59083c6..3d9ea08 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
@@ -316,7 +316,8 @@
 
         // prefer derived class
         signatures.put(signature, info);
-      } else {
+      }
+      else {
         final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class);
         if (methodCallExpression != null) {
           final PsiReferenceExpression expression = methodCallExpression.getMethodExpression();
@@ -324,14 +325,16 @@
           PsiClass currentClass;
           if (qualifierExpression != null) {
             currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType());
-          } else {
+          }
+          else {
             currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
           }
 
-          if (currentClass != null && InheritanceUtil.isInheritorOrSelf(currentClass, class1, true) && InheritanceUtil.isInheritorOrSelf(currentClass, existingClass, true)) {
-            final PsiSubstitutor eSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(existingClass, currentClass, PsiSubstitutor.EMPTY);
-            final PsiSubstitutor cSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(class1, currentClass, PsiSubstitutor.EMPTY);
-            if (MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
+          if (currentClass != null) {
+            final PsiSubstitutor eSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(existingClass, currentClass, PsiSubstitutor.EMPTY, null);
+            final PsiSubstitutor cSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(class1, currentClass, PsiSubstitutor.EMPTY, null);
+            if (eSubstitutor != null && cSubstitutor != null &&
+                MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
               final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType());
               final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType());
               if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
index 2b36a9c..c12972d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
@@ -83,7 +83,7 @@
       public PsiType[] getArgumentTypes() {
         if (myExpressionTypes == null && argumentList != null) {
           final PsiType[] expressionTypes = getExpressionTypes(argumentList);
-          if (!MethodCandidateInfo.ourOverloadGuard.currentStack().isEmpty()) {
+          if (MethodCandidateInfo.isOverloadCheck()) {
             return expressionTypes;
           }
           myExpressionTypes = expressionTypes;
diff --git a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
index c1afbee..6690801 100644
--- a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
+++ b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
@@ -51,12 +51,12 @@
     final PsiMethod element = getElement();
     if (element == null || element instanceof SyntheticElement) return result;
 
-    final TextRange range = element.getTextRange();
-    if (range == null) return result;
-
     final PsiFile psiFile = element.getContainingFile();
     if (psiFile == null || psiFile instanceof PsiCompiledElement) return result;
 
+    final TextRange range = element.getTextRange();
+    if (range == null) return result;
+
     final String fileText = psiFile.getText();
     if (fileText == null) return result;
 
diff --git a/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java b/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java
new file mode 100644
index 0000000..08713f8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java
@@ -0,0 +1,9 @@
+import a.A;
+
+class IDEA127714 {
+  {
+    A<E, String> strings = new A<>(E.class);
+  }
+}
+
+enum E {}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar b/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar
new file mode 100644
index 0000000..915d3a0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar
Binary files differ
diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java
new file mode 100644
index 0000000..d8ea619
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java
@@ -0,0 +1,12 @@
+
+class Foo {
+    {
+        try
+        {
+
+        } catch (Ex<caret>ception e)
+        {
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java
new file mode 100644
index 0000000..f4874b4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java
@@ -0,0 +1,12 @@
+
+class Foo {
+    {
+        try
+        {
+
+        } catch (Exception e)
+        {
+            <caret>
+        }
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java
new file mode 100644
index 0000000..077ff80
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java
@@ -0,0 +1,4 @@
+class Foo {{
+  System.<caret>
+  System.<caret>
+}}
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java
new file mode 100644
index 0000000..41f3d57
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java
@@ -0,0 +1,16 @@
+class Main {
+  void foo(List<? extends Number> list) {
+    list.forEach(new Consumer<Number>() {
+        @Override
+        public void consume(Number number) {
+            <caret>
+        }
+    });
+  }
+}
+
+class List<T> {
+  void forEach(Consumer<? super T> consumer);
+}
+
+interface Consumer<T> { void consume(T t); }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java
new file mode 100644
index 0000000..b1d1890
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java
@@ -0,0 +1,11 @@
+class Main {
+  void foo(List<? extends Number> list) {
+    list.forEach(new <caret>);
+  }
+}
+
+class List<T> {
+  void forEach(Consumer<? super T> consumer);
+}
+
+interface Consumer<T> { void consume(T t); }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java
new file mode 100644
index 0000000..2b47bb5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java
@@ -0,0 +1,17 @@
+public class Foo {
+
+  private LocalDate dateField;
+
+  void foo(LocalDate date) {
+
+  }
+
+  void bar() {
+    foo(<caret>)
+  }
+}
+
+class LocalDate {
+  public static final LocalDate MAX;
+  public static final LocalDate MIN;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
index 8be16fc..8ba3ea4 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
@@ -94,4 +94,96 @@
   void asLongs(Integer i) {
       long l = (long) i;
   }
+
+  void foo(Object o) {}
+  public void cast2(Byte operand) {
+    foo((<warning descr="Casting 'operand' to 'byte' is redundant">byte</warning>)operand);
+    foo((short)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Byte' to 'char'">(char)operand</error>);
+    foo((int)operand);
+    foo((long)operand);
+    foo((float)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Byte' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Short operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'byte'">(byte)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'short' is redundant">short</warning>)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'char'">(char)operand</error>);
+    foo((int)operand);
+    foo((long)operand);
+    foo((float)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Character operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'short'">(short)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'char' is redundant">char</warning>)operand);
+    foo((int)operand);
+    foo((long)operand);
+    foo((float)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Integer operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'short'">(short)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'char'">(char)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'int' is redundant">int</warning>)operand);
+    foo((long)operand);
+    foo((float)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Long operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'short'">(short)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'char'">(char)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'int'">(int)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'long' is redundant">long</warning>)operand);
+    foo((float)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Float operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'short'">(short)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'char'">(char)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'int'">(int)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'long'">(long)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'float' is redundant">float</warning>)operand);
+    foo((double)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Double operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'short'">(short)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'char'">(char)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'int'">(int)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'long'">(long)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'float'">(float)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'double' is redundant">double</warning>)operand);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'boolean'">(boolean)operand</error>);
+  }
+  public void cast2(Boolean operand) {
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'byte'">(byte)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'short'">(short)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'char'">(char)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'int'">(int)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'long'">(long)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'float'">(float)operand</error>);
+    foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'double'">(double)operand</error>);
+    foo((<warning descr="Casting 'operand' to 'boolean' is redundant">boolean</warning>)operand);
+  }
+  public void cast2(Object operand) {
+    foo((<warning descr="Casting 'operand' to 'byte' is redundant">byte</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'short' is redundant">short</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'char' is redundant">char</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'int' is redundant">int</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'long' is redundant">long</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'float' is redundant">float</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'double' is redundant">double</warning>)operand);
+    foo((<warning descr="Casting 'operand' to 'boolean' is redundant">boolean</warning>)operand);
+  }
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java
new file mode 100644
index 0000000..42be49b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java
@@ -0,0 +1,29 @@
+class TestIDEA128101 {
+
+  static class Attribute<Y> {};
+  static class Path<X> {};
+
+  static Attribute<Integer> integerAttribute;
+  static Attribute<String> stringAttribute;
+
+  static <Y> Path<Y> createPath(Attribute<Y> attribute) {
+    return new Path<>();
+  }
+  static <Y> Path<Y> createPath1(Attribute<Y> attribute) {
+    return new Path<>();
+  }
+  static <T> void construct(Class<T> aClass, Path<?>... paths) {}
+  static <T, K> void construct1(Class<T> aClass, Path<K>... paths) {}
+  static <T, K> void construct2(Class<T> aClass, Path<? extends K>... paths) {}
+  static <T, K> void construct3(Class<T> aClass, Path<? super K>... paths) {}
+  static <T, K> void construct4(Class<T> aClass, Path<? super K> path1, Path<? super K> path2) {}
+
+  public static void test() {
+    construct(String.class, createPath(integerAttribute), createPath(stringAttribute));
+    construct1<error descr="Cannot resolve method 'construct1(java.lang.Class<java.lang.String>, TestIDEA128101.Path<java.lang.Integer>, TestIDEA128101.Path<java.lang.String>)'">(String.class, createPath(integerAttribute), createPath(stringAttribute))</error>;
+    construct2(String.class, createPath(integerAttribute), createPath(stringAttribute));
+    <error descr="Type parameter K has incompatible upper bounds: Integer and String">construct3(String.class, createPath(integerAttribute), createPath(stringAttribute));</error>
+    <error descr="Type parameter K has incompatible upper bounds: Integer and String">construct4(String.class, createPath(integerAttribute), createPath(stringAttribute));</error>
+  }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java
new file mode 100644
index 0000000..650114b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java
@@ -0,0 +1,24 @@
+import java.util.Collection;
+import java.util.List;
+
+class Test {
+
+  {
+    Matcher<? super List<String>> m = not(empty());
+  }
+
+  static <E> Matcher<Collection<E>> empty() {
+    return null;
+  }
+
+  static <T> Matcher<T> not(Matcher<T> matcher) {
+    return null;
+  }
+
+  static <T> Matcher<T> not(T value) {
+    return null;
+  }
+
+  static class Matcher<K> {}
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java
new file mode 100644
index 0000000..8fad96c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java
@@ -0,0 +1,14 @@
+class Test {
+  static class TKey<T> {
+  }
+
+  public interface Getter {
+    <T> T getValue(TKey<T> key);
+  }
+
+  static final TKey<Boolean> KEY_B = new TKey<>();
+
+  public static void f(Getter getter) {
+    String name = getter.getValue(KEY_B) ? "foo" : "bar";
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java
new file mode 100644
index 0000000..6788a98
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java
@@ -0,0 +1,15 @@
+class Test {
+  static class TKey<T> {
+  }
+
+  public interface Getter {
+    <T> T getValue(TKey<T> key);
+  }
+
+  static final TKey<Integer> KEY_I = null;
+
+
+  public static void f(Getter getter, TKey<Integer> key) {
+    double d1 = getter.getValue (key);
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
index 254ec71..92b2683 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
@@ -39,7 +39,7 @@
      void m3(int x, boolean cond) {
          int y;
          if (cond) y = 1;
-         foo(() -> x+<error descr="Variable used in lambda expression should be effectively final">y</error>);
+         foo(() -> x+<error descr="Variable 'y' might not have been initialized">y</error>);
      }
  
      void m4(int x, boolean cond) {
@@ -128,3 +128,17 @@
     };
   }
 }
+
+class IDEA128196 {
+  void a() {
+    int value;
+
+    try {
+      value = 1;
+    } catch (Exception e) {
+      return;
+    }
+
+    new Thread(() -> System.out.println(value));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java
new file mode 100644
index 0000000..095448e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java
@@ -0,0 +1,19 @@
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+class IDEA127765 {
+  void a(final Map<String, Optional<Double>> allValues, final Function<Optional<Double>, Double> get) {
+    final Map<String, Double> presentValues = transformValues(filterValues(allValues, Optional::isPresent), get);
+  }
+
+  public static <K, V1, V2> Map<K, V2> transformValues(Map<K, V1> fromMap, Function<? super V1, V2> function) {
+    return null;
+  }
+
+  public static <K, V> Map<K, V> filterValues(Map<K, V> unfiltered, Predicate<? super V> valuePredicate) {
+    return null;
+  }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java
new file mode 100644
index 0000000..82e3cc9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java
@@ -0,0 +1,10 @@
+// "Replace with lambda" "true"
+class Test2 {
+
+  void f(Runnable... rs){}
+  {
+    f(null, () -> {
+
+    });
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java
new file mode 100644
index 0000000..af9db77
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java
@@ -0,0 +1,13 @@
+// "Replace with lambda" "true"
+class Test2 {
+
+  void f(Runnable... rs){}
+  {
+    f(null, new Run<caret>nable() {
+      @Override
+      public void run() {
+
+      }
+    });
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java
new file mode 100644
index 0000000..1af8cd0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java
@@ -0,0 +1,5 @@
+public class Foo {
+  void m(Object o) {
+    !.null<caret>
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java
new file mode 100644
index 0000000..1334be6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+  void m(Object o) {
+    !.null  <caret>
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java
new file mode 100644
index 0000000..08b2afd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java
@@ -0,0 +1,7 @@
+class Foo {
+  public static void main(String[] args) {
+    String s = "";
+    s.replaceAll("\\<caret>");
+    System.out.println();
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java
new file mode 100644
index 0000000..bee6f10
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java
@@ -0,0 +1,7 @@
+class Foo {
+  public static void main(String[] args) {
+    String s = "";
+    s.replaceAll("<caret>");
+    System.out.println();
+  }
+}
diff --git a/java/java-tests/testData/find/findInEditor/BasicFind.gold b/java/java-tests/testData/find/findInEditor/BasicFind.gold
index 14e4182..4648676 100644
--- a/java/java-tests/testData/find/findInEditor/BasicFind.gold
+++ b/java/java-tests/testData/find/findInEditor/BasicFind.gold
@@ -3,8 +3,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -22,6 +21,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
diff --git a/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold b/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
index a2168ba..bfda616 100644
--- a/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
+++ b/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
@@ -3,8 +3,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -22,6 +21,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
@@ -37,8 +37,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -56,6 +55,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
@@ -70,8 +70,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -89,6 +88,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
diff --git a/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold b/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
index 478eb64..a4d44cb 100644
--- a/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
+++ b/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
@@ -3,8 +3,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -22,6 +21,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
@@ -33,8 +33,7 @@
 myStringToReplace =
 isReplaceState =false
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -52,6 +51,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
@@ -65,8 +65,7 @@
 myStringToReplace =
 isReplaceState =true
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -84,6 +83,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 Replacement Preview: <Empty string>
@@ -99,8 +99,7 @@
 myStringToReplace =
 isReplaceState =true
 isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
 isFromCursor =true
 isForward =true
 isGlobal =true
@@ -118,6 +117,7 @@
 fileFilter =null
 moduleName =null
 customScopeName =null
+searchInProjectFiles =false
 
 --
 
diff --git a/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java b/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
index 4a0a690..4f0586d 100644
--- a/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
+++ b/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
@@ -19,6 +19,6 @@
    }
 
    public static void bar() throws CheckedException {
-     throw new CheckedException();
+     if (new Random().nextInt() > 2) throw new CheckedException();
    }
  }
diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
index bb6256f..4a08821 100644
--- a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
+++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
@@ -7,7 +7,7 @@
   </problem>
   <problem>
     <file>IDEADEV10489.java</file>
-    <line>12</line>
+    <line>8</line>
     <description>Method invocation 's.length()' may produce NullPointerException</description>
   </problem>
 </problems>
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
index 6025947..ee41e58 100644
--- a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
+++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
@@ -1,7 +1,5 @@
 class IDEADEV10489 {
-    static String getS() {
-        return null;
-    }
+    static native String getS();
 
     static void f() {
         String s = getS();
@@ -17,7 +15,5 @@
         }
     }
 
-    private static boolean foo() {
-      return false;
-    }
+    private static native boolean foo();
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java b/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
index 93fcf6d..55c7c2b 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
@@ -18,7 +18,5 @@
     }
   }
 
-  private static @NotNull String createString() {
-    throw new NullPointerException();
-  }
+  private static native @NotNull String createString();
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
index ecb9b26..a30d934 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
@@ -1,3 +1,5 @@
+import java.util.Random;
+
 class BrokenAlignment {
 
   public static void main(String[] args) {
@@ -20,7 +22,7 @@
   }
 
   public static void doSomething() {
-    throw new RuntimeException("dummy");
+    if (new Random().nextInt() > 2) throw new RuntimeException("dummy");
   }
 
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java
new file mode 100644
index 0000000..006c2e3
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java
@@ -0,0 +1,24 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class Doo {
+
+  @NotNull
+  public String doSomething() {
+    String s = getSomeString();
+    if (s == null) {
+      throwSomeError();
+    }
+    return s;
+  }
+
+  private static void throwSomeError() {
+    throw new RuntimeException();
+  }
+
+  @Nullable
+  public String getSomeString() {
+    return Math.random() > 0.5 ? null : "Yeah";
+  }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java
new file mode 100644
index 0000000..e9ec6b1
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java
@@ -0,0 +1,25 @@
+import foo.*;
+import org.jetbrains.annotations.NotNull;
+
+class Some {
+  void foo(@NotNull String s) {
+    NotNullClass.foo(null);
+    if (<warning descr="Condition 'NotNullClass.foo(s) == null' is always 'false'">NotNullClass.foo(s) == null</warning>) {}
+    
+    NullableClass.foo(null);
+    if (NullableClass.foo("a") == null) {}
+    
+    AnotherPackageNotNull.foo(null);
+    if (<warning descr="Condition 'AnotherPackageNotNull.foo(s) == null' is always 'false'">AnotherPackageNotNull.foo(s) == null</warning>) {}
+  }
+
+}
+
+@bar.MethodsAreNotNullByDefault
+class NotNullClass {
+  static native Object foo(String s);
+
+}
+class NullableClass {
+  static native Object foo(String s);
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java b/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java
new file mode 100644
index 0000000..5c553bc
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java
@@ -0,0 +1,7 @@
+class Test {
+  public static void testFunc(final float width, final float height) {
+    if (width < 0f || height < 0f) {
+      throw new IllegalArgumentException("Size must be non-negative");
+    }
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java
new file mode 100644
index 0000000..dd81513
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java
@@ -0,0 +1,9 @@
+class Test {
+
+  static void f<caret>oo() {}
+  static void foo2(int i) {}
+
+  {
+    Runnable r = Test :: foo;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after
new file mode 100644
index 0000000..8dab080
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after
@@ -0,0 +1,9 @@
+class Test {
+
+  static void foo2() {}
+  static void foo2(int i) {}
+
+  {
+    Runnable r = Test ::foo2;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
index ae0ec20..8383550 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
@@ -20,6 +20,8 @@
 public class ClsGenerics18HighlightingTest extends ClsGenericsHighlightingTest {
   public void testIDEA121866() { doTest(); }
 
+  public void testIDEA127714() { doTest(); }
+
   @Override
   protected LanguageLevel getLanguageLevel() {
     return LanguageLevel.JDK_1_8;
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
index 2eecdaa..3f199d4 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
@@ -17,9 +17,6 @@
 
 import com.intellij.JavaTestUtil;
 import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
@@ -54,6 +51,18 @@
   
   public void testCompleteCatchLParen() throws Exception { doTest(); }
 
+  public void testAlreadyCompleteCatch() throws Exception {
+    CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
+    int old = settings.BRACE_STYLE;
+    settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
+    try {
+      doTest();
+    }
+    finally {
+      settings.BRACE_STYLE = old;
+    }
+  }
+
   public void testCompleteCatchWithExpression() throws Exception { doTest(); }
 
   public void testCompleteCatchBody() throws Exception { doTest(); }
@@ -171,8 +180,6 @@
   }
 
   public void testSCR36110() throws Exception {
-    JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
-    LanguageLevel old = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
     doTest();
   }
 
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
index f59162a..9ca3b60 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
@@ -16,6 +16,7 @@
 package com.intellij.codeInsight;
 
 import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.psi.PsiDocumentManager;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
 
@@ -65,6 +66,14 @@
     myFixture.checkResultByFile(getTestName(true) + "_after.java");
   }
 
+  public void testInvalidInitialSyntax() {
+    myFixture.configureByFile(getTestName(true) + "_before.java");
+    myFixture.type('\\');
+    PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // emulates background commit after typing first character
+    myFixture.type('\\');
+    myFixture.checkResultByFile(getTestName(true) + "_after.java");
+  }
+
   private void doTest(char c) {
     myFixture.configureByFile(getTestName(true) + "_before.java");
     myFixture.type(c);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
index 77b4c0c..f5fc390 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -1423,6 +1423,11 @@
     checkResult()
   }
 
+  public void testMulticaretCompletionFromNonPrimaryCaret() {
+    configure()
+    myFixture.assertPreferredCompletionItems(0, "arraycopy")
+  }
+
   public void "test complete lowercase class name"() {
     myFixture.addClass("package foo; public class myClass {}")
     myFixture.configureByText "a.java", """
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
index 1d258fe..f37b90e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
@@ -160,6 +160,10 @@
     checkPreferredItems(0, "myVersion", "getVersion", "getSelectedVersion", "calculateVersion");
   }
 
+  public void testPreferFieldsToConstants() {
+    checkPreferredItems(0, "dateField", "LocalDate.MAX", "LocalDate.MIN");
+  }
+
   public void testPreferParametersToGetters() throws Throwable {
     checkPreferredItems(0, "a", "I._1", "getLastI", "valueOf");
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
index d2e8825..5153f19 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
@@ -716,7 +716,7 @@
   public void testMethodColon() throws Exception { doFirstItemTest(':'); }
   public void testVariableColon() throws Exception { doFirstItemTest(':'); }
 
-  private void doFirstItemTest(char c) throws Exception {
+  private void doFirstItemTest(char c) {
     configureByTestName();
     select(c);
     checkResultByTestName();
@@ -824,6 +824,8 @@
     doActionTest();
   }
 
+  public void testDontSuggestWildcardGenerics() { doItemTest(); }
+
   public void testCastWith2TypeParameters() throws Throwable { doTest(); }
   public void testClassLiteralInArrayAnnoInitializer() throws Throwable { doTest(); }
   public void testClassLiteralInArrayAnnoInitializer2() throws Throwable { doTest(); }
@@ -1141,7 +1143,7 @@
     checkResultByTestName();
   }
 
-  private void doItemTest() throws Exception {
+  private void doItemTest() {
     doFirstItemTest('\n');
   }
 
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
index 7950628..6ccefa3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
@@ -188,6 +188,22 @@
     doTest();
   }
 
+  public void testInferFromConditionalExpressionCondition() throws Exception {
+    doTest();
+  }
+
+  public void testPrimitiveWrapperConditionInReturnConstraint() throws Exception {
+    doTest();
+  }
+
+  public void testIDEA128174() throws Exception {
+    doTest();
+  }
+
+  public void testIDEA128101() throws Exception {
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
index fbf8036..156aac5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
@@ -106,6 +106,10 @@
     doTest();
   }
 
+  public void testIDEA127765() throws Exception {
+    doTest();
+  }
+
   private void doTest() {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java
new file mode 100644
index 0000000..b94e54d
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.folding;
+
+import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.FoldingModelEx;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
+
+public class JavaFoldingGotoTest extends JavaCodeInsightFixtureTestCase {
+
+  public void testIDEA127145() {
+    PsiFile file = myFixture.addFileToProject("Program.java",
+                                              "import java.io.InputStream;\n" +
+                                              "import java.util.HashMap;\n" +
+                                              "import java.util.Map;\n" +
+                                              "\n" +
+                                              "class Program {\n" +
+                                              "  private static InputStream getFile(String name, Map<String, Object> args) {\n" +
+                                              "    return Program.class.getResourceAsStream(name);\n" +
+                                              "  }\n" +
+                                              "\n" +
+                                              "  public static void main(String[] args) {\n" +
+                                              "    // Ctrl + B or Ctrl + Left Mouse Button work correctly for following string:\n" +
+                                              "    final String name = \"file.sql\";\n" +
+                                              "    // But it jumps only to folder in following case:\n" +
+                                              "    final InputStream inputStream = getFile(\"dir/fil<caret>e.sql\", new HashMap<String, Object>());\n" +
+                                              "  }\n" +
+                                              "}");
+
+    PsiFile fileSql = myFixture.addFileToProject("dir/file.sql", "select 1;");
+    myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
+
+    Editor editor = myFixture.getEditor();
+    CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(editor);
+    FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel();
+    foldingModel.rebuild();
+    myFixture.doHighlighting();
+
+    PsiElement element = GotoDeclarationAction.findTargetElement(getProject(), editor, editor.getCaretModel().getOffset());
+    assertTrue("Should navigate to: file.sql instead of " + element, element != null && element.equals(fileSql));
+  }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
index 5d823e0..095de51 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
@@ -568,14 +568,20 @@
 
   public void "test fold one-line methods"() {
     configure """class Foo {
+ @Override
  int someMethod() {
    return 0;
  }
 
+ int someOtherMethod(
+   int param) {
+   return 0;
+ }
+
 }"""
     PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
     def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
-    assert regions.size() == 2
+    assert regions.size() == 3
     checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
   }
 
@@ -792,13 +798,14 @@
     assert regions[3].placeholderText == 'seq: "Hi!"'
   }
 
-  public void "test inline negative numbers (IDEA-126753)"() {
+  public void "test inline negative and positive numbers"() {
     def text = """
 public class CharSymbol {
 
   public void main() {
     Object obj = new Object();
     count(-1, obj);
+    count(+1, obj);
   }
 
   public void count(int test, Object obj) {
@@ -809,10 +816,13 @@
 """
     configure text
     def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
-    assert regions.size() == 3
+    assert regions.size() == 4
 
     checkRangeOffsetByPositionInText(regions[1], text, "-1")
     assert regions[1].placeholderText == "test: -1"
+
+    checkRangeOffsetByPositionInText(regions[2], text, "+1")
+    assert regions[2].placeholderText == "test: +1"
   }
 
   public void "test inline constructor literal arguments names"() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
index 7f47795..70061e5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
@@ -38,4 +38,9 @@
   public void testSecondStatement() {
     doTest();
   }
+
+
+  public void testSingleExclamationIgnored() {
+    doTest();
+  }
 }
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
index 23eac58..89762ef 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
@@ -228,6 +228,34 @@
     assert c == []
   }
 
+  public void "test boolean autoboxing in delegation"() {
+    def c = inferContracts("""
+    static Boolean test04(String s) {
+        return test03(s);
+    }
+    static boolean test03(String s) {
+        return s == null;
+    }
+    """)
+    assert c == []
+  }
+
+  public void "test boolean auto-unboxing"() {
+    def c = inferContracts("""
+      static boolean test02(String s) {
+          return test01(s);
+      }
+
+      static Boolean test01(String s) {
+          if (s == null)
+              return new Boolean(false);
+          else
+             return null;
+      }
+    """)
+    assert c == []
+  }
+
   public void "test non-returning delegation"() {
     def c = inferContracts("""
     static void test2(Object o) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
index 4cba2ab..33eb32e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
@@ -18,6 +18,7 @@
 import com.intellij.JavaTestUtil;
 import com.intellij.codeInspection.dataFlow.DataFlowInspection;
 import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
 import org.jetbrains.annotations.NotNull;
 
@@ -251,15 +252,17 @@
   public void testRootThrowableCause() { doTest(); }
 
   public void testUseInferredContracts() { doTest(); }
+  public void testContractWithNoArgs() { doTest(); }
   public void testContractInferenceBewareOverriding() { doTest(); }
 
   public void testNumberComparisonsWhenValueIsKnown() { doTest(); }
+  public void testFloatComparisons() { doTest(); }
 
   public void testAccessingSameArrayElements() { doTest(); }
 
   public void testParametersAreNonnullByDefault() {
-    myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
-    myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}");
+    addJavaxNullabilityAnnotations(myFixture);
+    addJavaxDefaultNullabilityAnnotations(myFixture);
     
     myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}");
     myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
@@ -267,6 +270,37 @@
     doTest(); 
   }
 
+  public static void addJavaxDefaultNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
+    fixture.addClass("package javax.annotation;" +
+                     "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " +
+                     "public @interface ParametersAreNonnullByDefault {}");
+    fixture.addClass("package javax.annotation;" +
+                     "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " +
+                     "public @interface ParametersAreNullableByDefault {}");
+  }
+
+  public static void addJavaxNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
+    fixture.addClass("package javax.annotation;" +
+                     "public @interface Nonnull {}");
+    fixture.addClass("package javax.annotation;" +
+                     "public @interface Nullable {}");
+    fixture.addClass("package javax.annotation.meta;" +
+                     "public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}");
+  }
+
+  public void testCustomTypeQualifierDefault() {
+    addJavaxNullabilityAnnotations(myFixture);
+    myFixture.addClass("package bar;" +
+                       "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.METHOD) @javax.annotation.Nonnull " +
+                       "public @interface MethodsAreNotNullByDefault {}");
+
+    myFixture.addClass("package foo; public class AnotherPackageNotNull { public static native Object foo(String s); }");
+    myFixture.addFileToProject("foo/package-info.java", "@bar.MethodsAreNotNullByDefault package foo;");
+
+    myFixture.enableInspections(new DataFlowInspection());
+    myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
+  }
+
   public void testTrueOrEqualsSomething() {
     doTest();
     myFixture.launchAction(myFixture.findSingleIntention("Remove redundant assignment"));
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
index e925dd4..3520ec0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
@@ -40,8 +40,8 @@
   }
 
   public void testHonorSuperParameterDefault() {
-    myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
-    myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+    DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+    DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
     myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
 
     myFixture.addClass("import javax.annotation.*; package foo; public interface NullableFunction { void fun(@Nullable Object o); }");
@@ -51,7 +51,8 @@
   }
 
   public void testHonorThisParameterDefault() {
-    myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+    DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+    DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
     myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
 
     myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
@@ -60,8 +61,8 @@
   }
 
   public void testHonorParameterDefaultInSetters() {
-    myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
-    myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+    DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+    DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
     myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
 
     myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
index 09fa87f..9d26fd8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
@@ -183,7 +183,7 @@
 
   private void checkCompoundId(Method method, PsiMethod psiMethod, boolean noKey) throws IOException {
     Direction direction = new Out();
-    int psiKey = myBytecodeAnalysisConverter.mkPsiKey(psiMethod, direction);
+    long psiKey = myBytecodeAnalysisConverter.mkPsiKey(psiMethod, direction);
     if (noKey) {
       assertTrue(-1 == psiKey);
       return;
@@ -192,7 +192,7 @@
       assertFalse(-1 == psiKey);
     }
 
-    int asmKey = myBytecodeAnalysisConverter.mkAsmKey(new Key(method, direction, true));
+    long asmKey = myBytecodeAnalysisConverter.mkAsmKey(new Key(method, direction, true));
 
     Assert.assertEquals(asmKey, psiKey);
   }
diff --git a/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java b/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
index 02f8c58..3cc6c19 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
@@ -19,7 +19,9 @@
 import com.intellij.openapi.actionSystem.ActionPlaces;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.impl.EditorImpl;
 import com.intellij.openapi.util.Getter;
+import com.intellij.testFramework.fixtures.EditorMouseFixture;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
 
 import javax.swing.text.JTextComponent;
@@ -58,7 +60,7 @@
     assertNull(getEditorSearchComponent());
   }
 
-  public void testActionsWorkFromEditor() throws IOException {
+  public void testActionsInEditorWorkIndependently() throws IOException {
     init("abc\n" +
          "abc\n" +
          "abc");
@@ -67,27 +69,29 @@
     checkResultByText("a<selection>b<caret></selection>c\n" +
                       "abc\n" +
                       "abc");
+    new EditorMouseFixture((EditorImpl)myFixture.getEditor()).clickAt(0, 1);
     addOccurrenceFromEditor();
-    checkResultByText("a<selection>b<caret></selection>c\n" +
-                      "a<selection>b<caret></selection>c\n" +
+    addOccurrenceFromEditor();
+    checkResultByText("<selection>a<caret>bc</selection>\n" +
+                      "<selection>a<caret>bc</selection>\n" +
                       "abc");
     nextOccurrenceFromEditor();
-    checkResultByText("a<selection>b<caret></selection>c\n" +
+    checkResultByText("<selection>a<caret>bc</selection>\n" +
                       "abc\n" +
-                      "a<selection>b<caret></selection>c");
+                      "<selection>a<caret>bc</selection>");
     prevOccurrenceFromEditor();
-    checkResultByText("a<selection>b<caret></selection>c\n" +
-                      "a<selection>b<caret></selection>c\n" +
+    checkResultByText("<selection>a<caret>bc</selection>\n" +
+                      "<selection>a<caret>bc</selection>\n" +
                       "abc");
     removeOccurrenceFromEditor();
-    checkResultByText("a<selection>b<caret></selection>c\n" +
+    checkResultByText("<selection>a<caret>bc</selection>\n" +
                       "abc\n" +
                       "abc");
     allOccurrencesFromEditor();
-    checkResultByText("a<selection>b<caret></selection>c\n" +
-                      "a<selection>b<caret></selection>c\n" +
-                      "a<selection>b<caret></selection>c");
-    assertNull(getEditorSearchComponent());
+    checkResultByText("<selection>a<caret>bc</selection>\n" +
+                      "<selection>a<caret>bc</selection>\n" +
+                      "<selection>a<caret>bc</selection>");
+    assertNotNull(getEditorSearchComponent());
   }
 
   public void testCloseRetainsMulticaretSelection() throws IOException {
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index 92caad0..f83d836 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -579,7 +579,7 @@
     FindModel findModel = FindManagerTestUtils.configureFindModel("done");
     String text = "/** done done done */";
 
-    findModel.setInCommentsOnly(true);
+    findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
     FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text);
 
     findModel.setRegularExpressions(true);
@@ -592,7 +592,7 @@
     String prefix = "/*";
     String text = prefix + "done*/";
 
-    findModel.setInCommentsOnly(true);
+    findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
     LightVirtualFile file = new LightVirtualFile("A.java", text);
 
     FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
@@ -615,8 +615,7 @@
     FindModel findModel = FindManagerTestUtils.configureFindModel("^done$");
 
     findModel.setRegularExpressions(true);
-    findModel.setInStringLiteralsOnly(true);
-    findModel.setInCommentsOnly(false);
+    findModel.setSearchContext(FindModel.SearchContext.IN_STRING_LITERALS);
     String text = "\"done\"; 'done'; 'done' \"done2\"";
     FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java");
 
@@ -633,7 +632,7 @@
 
     String text = "/** do ne do ne do ne */";
 
-    findModel.setInCommentsOnly(true);
+    findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
     FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java");
   }
 
@@ -651,4 +650,42 @@
     findModel.setWholeWordsOnly(true);
     assertSize(1, findUsages(findModel));
   }
+
+  public void testFindExceptComments() {
+    FindModel findModel = FindManagerTestUtils.configureFindModel("done");
+
+    String prefix = "/*";
+    String text = prefix + "done*/done";
+
+    findModel.setSearchContext(FindModel.SearchContext.EXCEPT_COMMENTS);
+    LightVirtualFile file = new LightVirtualFile("A.java", text);
+
+    FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prefix.length());
+
+    findModel.setRegularExpressions(true);
+    findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prefix.length());
+  }
+
+  public void testFindExceptLiterals() {
+    FindModel findModel = FindManagerTestUtils.configureFindModel("done");
+
+    String prefix = "\"";
+    String text = prefix + "done\"done";
+
+    findModel.setSearchContext(FindModel.SearchContext.EXCEPT_STRING_LITERALS);
+    LightVirtualFile file = new LightVirtualFile("A.java", text);
+
+    FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prefix.length());
+
+    findModel.setRegularExpressions(true);
+    findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prefix.length());
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
index dabe06b..9a97a82 100644
--- a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
@@ -24,7 +24,6 @@
 import com.intellij.util.Consumer
 import com.intellij.util.concurrency.Semaphore
 import org.jetbrains.annotations.NotNull
-
 /**
  * @author peter
  */
@@ -197,6 +196,33 @@
     assert getPopupElements(new GotoClassModel2(project), 'Bar:[2,3]') == [c]
   }
 
+  public void "test dollar"() {
+    def bar = myFixture.addClass("package foo; class Bar { class Foo {} }")
+    def foo = bar.innerClasses[0]
+    myFixture.addClass("package goo; class Goo { }")
+    assert getPopupElements(new GotoClassModel2(project), 'Bar$Foo') == [foo]
+    assert getPopupElements(new GotoClassModel2(project), 'foo.Bar$Foo') == [foo]
+    assert getPopupElements(new GotoClassModel2(project), 'foo.B$F') == [foo]
+    assert !getPopupElements(new GotoClassModel2(project), 'foo$Foo')
+    assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar')
+    assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar$Foo')
+    assert !getPopupElements(new GotoClassModel2(project), 'foo$Goo')
+  }
+
+  public void "test anonymous classes"() {
+    def goo = myFixture.addClass("package goo; class Goo { Runnable r = new Runnable() {}; }")
+    assert getPopupElements(new GotoClassModel2(project), 'Goo$1') == [goo]
+  }
+
+  public void "test qualified name matching"() {
+    def bar = myFixture.addClass("package foo.bar; class Bar { }")
+    def bar2 = myFixture.addClass("package goo.baz; class Bar { }")
+    assert getPopupElements(new GotoClassModel2(project), 'foo.Bar') == [bar]
+    assert getPopupElements(new GotoClassModel2(project), 'foo.bar.Bar') == [bar]
+    assert getPopupElements(new GotoClassModel2(project), 'goo.Bar') == [bar2]
+    assert getPopupElements(new GotoClassModel2(project), 'goo.baz.Bar') == [bar2]
+  }
+
   public void "test super method in jdk"() {
     def ourRun = myFixture.addClass("package foo.bar; class Goo implements Runnable { public void run() {} }").methods[0]
     def sdkRun
diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
index 1e3e08a..5662459 100644
--- a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
+++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
@@ -49,7 +49,7 @@
 public class DirectoryIndexTest extends IdeaTestCase {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.DirectoryIndexTest");
 
-  private DirectoryIndex myIndex;
+  private DirectoryIndexImpl myIndex;
 
   private Module myModule2, myModule3;
   private VirtualFile myRootVFile;
@@ -65,6 +65,7 @@
   private VirtualFile myModule1OutputDir;
   private VirtualFile myResDir, myTestResDir;
   private VirtualFile myExcludedLibSrcDir, myExcludedLibClsDir;
+  private ProjectFileIndex myFileIndex;
 
   @Override
   protected void setUp() throws Exception {
@@ -176,7 +177,8 @@
       }
     });
 
-    myIndex = DirectoryIndex.getInstance(myProject);
+    myIndex = (DirectoryIndexImpl)DirectoryIndex.getInstance(myProject);
+    myFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
     // to not interfere with previous test firing vfs events
     VirtualFileManager.getInstance().syncRefresh();
   }
@@ -221,12 +223,12 @@
 
     VirtualFile cvs = myPack1Dir.createChildDirectory(this, "CVS");
     assertNotInProject(cvs);
-    assertNull(ProjectRootManager.getInstance(myProject).getFileIndex().getPackageNameByDirectory(cvs));
+    assertNull(myFileIndex.getPackageNameByDirectory(cvs));
   }
 
   public void testDirsByPackageName() throws IOException {
-    checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibSrc, myFileLibCls, mySrcDir2, myLibSrcDir, myLibClsDir);
-    checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibCls, mySrcDir2, myLibClsDir);
+    checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibSrcDir, myLibClsDir);
+    checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibClsDir);
     
     checkPackage("pack1", true, myPack1Dir);
     checkPackage("pack1", false, myPack1Dir);
@@ -257,6 +259,18 @@
     checkPackage("pack1", true, myPack1Dir, myModule3Dir);
   }
 
+  public void testPackageDirectoriesWithDots() throws IOException {
+    VirtualFile fooBar = mySrcDir1.createChildDirectory(this, "foo.bar");
+    VirtualFile goo1 = fooBar.createChildDirectory(this, "goo");
+    VirtualFile foo = mySrcDir2.createChildDirectory(this, "foo");
+    VirtualFile bar = foo.createChildDirectory(this, "bar");
+    VirtualFile goo2 = bar.createChildDirectory(this, "goo");
+
+    checkPackage("foo", false, foo);
+    checkPackage("foo.bar", false, bar, fooBar);
+    checkPackage("foo.bar.goo", false, goo2, goo1);
+  }
+
   public void testCreateDir() throws Exception {
     String path = mySrcDir1.getPath().replace('/', File.separatorChar);
     assertTrue(new File(path + File.separatorChar + "dir1" + File.separatorChar + "dir2").mkdirs());
@@ -362,7 +376,8 @@
     VirtualFile ignoredFile = myModule1Dir.createChildData(this, "CVS");
     DirectoryInfo info = myIndex.getInfoForFile(ignoredFile);
     assertTrue(info.isIgnored());
-    assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(ignoredFile));
+    assertTrue(myFileIndex.isExcluded(ignoredFile));
+    assertTrue(myFileIndex.isUnderIgnored(ignoredFile));
   }
 
   public void testAddModule() throws Exception {
@@ -386,10 +401,12 @@
   public void testModuleUnderIgnoredDir() throws IOException {
     final VirtualFile ignored = myRootVFile.createChildDirectory(this, "RCS");
     assertTrue(FileTypeManager.getInstance().isFileIgnored(ignored));
-    assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(ignored));
+    assertTrue(myFileIndex.isExcluded(ignored));
+    assertTrue(myFileIndex.isUnderIgnored(ignored));
     final VirtualFile module4 = ignored.createChildDirectory(this, "module4");
     assertFalse(FileTypeManager.getInstance().isFileIgnored(module4));
-    assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(module4));
+    assertTrue(myFileIndex.isExcluded(module4));
+    assertTrue(myFileIndex.isUnderIgnored(module4));
 
     new WriteCommandAction.Simple(getProject()) {
       @Override
@@ -425,11 +442,12 @@
   }
 
   public void testExcludedDirsInLibraries() {
-    ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
-    assertFalse(index.isInLibraryClasses(myExcludedLibClsDir));
-    assertTrue(index.isExcluded(myExcludedLibClsDir));
-    assertFalse(index.isInLibrarySource(myExcludedLibSrcDir));
-    assertTrue(index.isExcluded(myExcludedLibSrcDir));
+    assertFalse(myFileIndex.isInLibraryClasses(myExcludedLibClsDir));
+    assertTrue(myFileIndex.isExcluded(myExcludedLibClsDir));
+    assertFalse(myFileIndex.isUnderIgnored(myExcludedLibClsDir));
+    assertFalse(myFileIndex.isInLibrarySource(myExcludedLibSrcDir));
+    assertTrue(myFileIndex.isExcluded(myExcludedLibSrcDir));
+    assertFalse(myFileIndex.isUnderIgnored(myExcludedLibSrcDir));
   }
 
   public void testExplicitExcludeOfInner() throws Exception {
@@ -469,12 +487,12 @@
     ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Collections.<String>emptyList(), Arrays.asList(mySrcDir1.getUrl()));
     
     checkInfo(mySrcDir1, myModule, false, true, "", JavaSourceRootType.SOURCE, myModule, myModule);
-    OrderEntry[] entries = myIndex.getInfoForFile(mySrcDir1).getOrderEntries();
+    OrderEntry[] entries = myIndex.getOrderEntries(myIndex.getInfoForFile(mySrcDir1));
     assertInstanceOf(entries[0], LibraryOrderEntry.class);
     assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
 
     checkInfo(myTestSrc1, myModule, false, true, "testSrc", JavaSourceRootType.TEST_SOURCE, myModule, myModule);
-    entries = myIndex.getInfoForFile(myTestSrc1).getOrderEntries();
+    entries = myIndex.getOrderEntries(myIndex.getInfoForFile(myTestSrc1));
     assertInstanceOf(entries[0], LibraryOrderEntry.class);
     assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
   }
@@ -482,7 +500,7 @@
   public void testModuleSourceAsLibraryClasses() throws Exception {
     ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Arrays.asList(mySrcDir1.getUrl()), Collections.<String>emptyList());
     checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertInstanceOf(assertOneElement(assertInProject(mySrcDir1).getOrderEntries()), ModuleSourceOrderEntry.class);
+    assertInstanceOf(assertOneElement(myIndex.getOrderEntries(assertInProject(mySrcDir1))), ModuleSourceOrderEntry.class);
   }
 
   public void testModulesWithSameSourceContentRoot() {
@@ -645,7 +663,7 @@
     checkInfo(myLibSrcDir, myModule, true, true, "", null, myModule, myModule3);
     
     checkInfo(myResDir, myModule, true, false, "", JavaResourceRootType.RESOURCE, myModule);
-    assertInstanceOf(assertOneElement(assertInProject(myResDir).getOrderEntries()), ModuleSourceOrderEntry.class);
+    assertInstanceOf(assertOneElement(myIndex.getOrderEntries(assertInProject(myResDir))), ModuleSourceOrderEntry.class);
 
     checkInfo(myExcludedLibSrcDir, null, true, false, "lib.src.exc", null, myModule3, myModule);
     checkInfo(myExcludedLibClsDir, null, true, false, "lib.cls.exc", null, myModule3);
@@ -661,10 +679,10 @@
   }
 
   public void testExcludeCompilerOutputOutsideOfContentRoot() throws Exception {
-    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-    assertTrue(fileIndex.isExcluded(myOutputDir));
-    assertTrue(fileIndex.isExcluded(myModule1OutputDir));
-    assertFalse(fileIndex.isExcluded(myOutputDir.getParent()));
+    assertTrue(myFileIndex.isExcluded(myOutputDir));
+    assertFalse(myFileIndex.isUnderIgnored(myOutputDir));
+    assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
+    assertFalse(myFileIndex.isExcluded(myOutputDir.getParent()));
     assertExcludedFromProject(myOutputDir);
     assertExcludedFromProject(myModule1OutputDir);
     String moduleOutputUrl = myModule1OutputDir.getUrl();
@@ -677,7 +695,7 @@
 
     assertExcludedFromProject(myOutputDir);
     assertExcludedFromProject(myModule1OutputDir);
-    assertTrue(fileIndex.isExcluded(myModule1OutputDir));
+    assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
 
     PsiTestUtil.setCompilerOutputPath(myModule, moduleOutputUrl, true);
     PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, false);
@@ -703,49 +721,47 @@
   }
 
   public void testFileContentAndSourceRoots() throws IOException {
-    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
     VirtualFile fileRoot = myRootVFile.createChildData(this, "fileRoot.txt");
     VirtualFile fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
     VirtualFile fileTestSourceRoot = myRootVFile.createChildData(this, "fileTestSourceRoot.txt");
 
     assertNotInProject(fileRoot);
-    assertFalse(fileIndex.isInContent(fileRoot));
-    assertIteratedContent(fileIndex, null, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot));
+    assertFalse(myFileIndex.isInContent(fileRoot));
+    assertIteratedContent(myFileIndex, null, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot));
 
     ContentEntry contentEntry = PsiTestUtil.addContentRoot(myModule, fileRoot);
     assertEquals(fileRoot, contentEntry.getFile());
     checkInfo(fileRoot, myModule, false, false, "", null);
-    assertTrue(fileIndex.isInContent(fileRoot));
-    assertFalse(fileIndex.isInSource(fileRoot));
+    assertTrue(myFileIndex.isInContent(fileRoot));
+    assertFalse(myFileIndex.isInSource(fileRoot));
  
     PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
     PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
  
     PsiTestUtil.addContentRoot(myModule, fileTestSourceRoot);
     PsiTestUtil.addSourceRoot(myModule, fileTestSourceRoot, true);
     checkInfo(fileTestSourceRoot, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileTestSourceRoot));
-    assertTrue(fileIndex.isInSource(fileTestSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileTestSourceRoot));
 
-    assertIteratedContent(fileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
+    assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
 
     // removing file source root
     PsiTestUtil.removeSourceRoot(myModule, fileTestSourceRoot);
     checkInfo(fileTestSourceRoot, myModule, false, false, "", null);
-    assertTrue(fileIndex.isInContent(fileTestSourceRoot));
-    assertFalse(fileIndex.isInSource(fileTestSourceRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
+    assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileTestSourceRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
  
     // removing file content root
-    PsiTestUtil.removeContentEntry(myModule, contentEntry);
+    PsiTestUtil.removeContentEntry(myModule, contentEntry.getFile());
     assertNotInProject(fileRoot);
-    assertFalse(fileIndex.isInContent(fileRoot));
-    assertFalse(fileIndex.isInSource(fileRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Arrays.asList(fileRoot));
+    assertFalse(myFileIndex.isInContent(fileRoot));
+    assertFalse(myFileIndex.isInSource(fileRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Arrays.asList(fileRoot));
   }
 
   private void assertIteratedContent(ProjectFileIndex fileIndex,
@@ -764,63 +780,57 @@
   }
 
   public void testFileSourceRootsUnderDirContentRoot() throws IOException {
-    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
     VirtualFile fileSourceRoot = myModule1Dir.createChildData(this, "fileSourceRoot.txt");
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
 
     PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
 
     // removing file source root
     PsiTestUtil.removeSourceRoot(myModule, fileSourceRoot);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
   }
 
   public void testFileModuleExcludeRootUnderDirectoryRoot() throws IOException {
-    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
     VirtualFile fileExcludeRoot = mySrcDir1.createChildData(this, "fileExcludeRoot.txt");
-    assertTrue(fileIndex.isInContent(fileExcludeRoot));
-    assertTrue(fileIndex.isInSource(fileExcludeRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileExcludeRoot), null);
+    assertTrue(myFileIndex.isInContent(fileExcludeRoot));
+    assertTrue(myFileIndex.isInSource(fileExcludeRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileExcludeRoot), null);
 
     PsiTestUtil.addExcludedRoot(myModule, fileExcludeRoot);
-    assertFalse(fileIndex.isInContent(fileExcludeRoot));
-    assertFalse(fileIndex.isInSource(fileExcludeRoot));
+    assertFalse(myFileIndex.isInContent(fileExcludeRoot));
+    assertFalse(myFileIndex.isInSource(fileExcludeRoot));
     assertExcluded(fileExcludeRoot, myModule);
-    assertIteratedContent(fileIndex, null, Arrays.asList(fileExcludeRoot));
+    assertIteratedContent(myFileIndex, null, Arrays.asList(fileExcludeRoot));
 
     // removing file exclude root
     PsiTestUtil.removeExcludedRoot(myModule, fileExcludeRoot);
-    assertTrue(fileIndex.isInContent(fileExcludeRoot));
-    assertTrue(fileIndex.isInSource(fileExcludeRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileExcludeRoot), null);
+    assertTrue(myFileIndex.isInContent(fileExcludeRoot));
+    assertTrue(myFileIndex.isInSource(fileExcludeRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileExcludeRoot), null);
   }
 
   public void testFileModuleExcludeRootUnderFileRoot() throws IOException {
-    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
     VirtualFile fileRoot = myRootVFile.createChildData(this, "fileRoot.txt");
     PsiTestUtil.addContentRoot(myModule, fileRoot);
     checkInfo(fileRoot, myModule, false, false, "", null);
-    assertTrue(fileIndex.isInContent(fileRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileRoot), null);
+    assertTrue(myFileIndex.isInContent(fileRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileRoot), null);
     
     PsiTestUtil.addExcludedRoot(myModule, fileRoot);
-    assertFalse(fileIndex.isInContent(fileRoot));
+    assertFalse(myFileIndex.isInContent(fileRoot));
     assertExcluded(fileRoot, myModule);
-    assertIteratedContent(fileIndex, null, Arrays.asList(fileRoot));
+    assertIteratedContent(myFileIndex, null, Arrays.asList(fileRoot));
  
     // removing file exclude root
     PsiTestUtil.removeExcludedRoot(myModule, fileRoot);
     checkInfo(fileRoot, myModule, false, false, "", null);
-    assertTrue(fileIndex.isInContent(fileRoot));
-    assertIteratedContent(fileIndex, Arrays.asList(fileRoot), null);
+    assertTrue(myFileIndex.isInContent(fileRoot));
+    assertIteratedContent(myFileIndex, Arrays.asList(fileRoot), null);
   }
 
   public void testFileLibraryInsideFolderLibrary() throws IOException {
@@ -835,8 +845,6 @@
   }
 
   public void testFileContentRootsModifications() throws IOException {
-    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
     VirtualFile temp = myRootVFile.createChildDirectory(this, "temp");
 
     VirtualFile fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
@@ -845,54 +853,54 @@
     PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
     PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
 
     // delete and recreate
     fileSourceRoot.delete(this);
     assertNotInProject(fileSourceRoot);
-    assertFalse(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertFalse(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
     fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
 
     // delete and move from another dir 
     fileSourceRoot.delete(this);
     assertNotInProject(fileSourceRoot);
-    assertFalse(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertFalse(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
     fileSourceRoot = temp.createChildData(this, "fileSourceRoot.txt");
     assertNotInProject(fileSourceRoot);
     fileSourceRoot.move(this, myRootVFile);
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
 
     // delete and copy from another dir 
     fileSourceRoot.delete(this);
     assertNotInProject(fileSourceRoot);
-    assertFalse(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertFalse(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
     fileSourceRoot = temp.createChildData(this, "fileSourceRoot.txt");
     assertNotInProject(fileSourceRoot);
     fileSourceRoot = fileSourceRoot.copy(this, myRootVFile, "fileSourceRoot.txt");
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
     
     // delete and rename from another file
     fileSourceRoot.delete(this);
     assertNotInProject(fileSourceRoot);
-    assertFalse(fileIndex.isInContent(fileSourceRoot));
-    assertFalse(fileIndex.isInSource(fileSourceRoot));
+    assertFalse(myFileIndex.isInContent(fileSourceRoot));
+    assertFalse(myFileIndex.isInSource(fileSourceRoot));
     fileSourceRoot = myRootVFile.createChildData(this, "temp_file.txt");
     assertNotInProject(fileSourceRoot);
     fileSourceRoot.rename(this, "fileSourceRoot.txt");
     checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
-    assertTrue(fileIndex.isInContent(fileSourceRoot));
-    assertTrue(fileIndex.isInSource(fileSourceRoot));
+    assertTrue(myFileIndex.isInContent(fileSourceRoot));
+    assertTrue(myFileIndex.isInSource(fileSourceRoot));
   }
 
   private void checkInfo(VirtualFile file,
@@ -914,15 +922,14 @@
     assertEquals(isInLibrary, info.hasLibraryClassRoot());
     assertEquals(isInLibrarySource, info.isInLibrarySource());
 
-    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
     if (file.isDirectory()) {
-      assertEquals(packageName, fileIndex.getPackageNameByDirectory(file));
+      assertEquals(packageName, myFileIndex.getPackageNameByDirectory(file));
     }
 
-    assertEquals(Arrays.toString(info.getOrderEntries()), modulesOfOrderEntries.length, info.getOrderEntries().length);
+    assertEquals(Arrays.toString(myIndex.getOrderEntries(info)), modulesOfOrderEntries.length, myIndex.getOrderEntries(info).length);
     for (Module aModule : modulesOfOrderEntries) {
-      OrderEntry found = info.findOrderEntryWithOwnerModule(aModule);
-      assertNotNull("not found: " + aModule + " in " + Arrays.toString(info.getOrderEntries()), found);
+      OrderEntry found = myIndex.findOrderEntryWithOwnerModule(info, aModule);
+      assertNotNull("not found: " + aModule + " in " + Arrays.toString(myIndex.getOrderEntries(info)), found);
     }
   }
 
@@ -941,7 +948,7 @@
   private DirectoryInfo assertInProject(VirtualFile file) {
     DirectoryInfo info = myIndex.getInfoForFile(file);
     assertTrue(file.toString(), info.isInProject());
-    info.assertConsistency();
+    myIndex.assertConsistency(info);
     return info;
   }
 
@@ -957,6 +964,11 @@
     VirtualFile[] actualDirs = myIndex.getDirectoriesByPackageName(packageName, includeLibrarySources).toArray(VirtualFile.EMPTY_ARRAY);
     assertNotNull(actualDirs);
     assertOrderedEquals(actualDirs, expectedDirs);
+
+    for (VirtualFile dir : expectedDirs) {
+      String actualName = myIndex.getPackageName(dir);
+      assertEquals("Invalid package name for dir " + dir + ": " + packageName, packageName, actualName);
+    }
   }
 
 }
diff --git a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
index 096547c..61414ab 100644
--- a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
@@ -260,4 +260,20 @@
     assertEquals("some.unknown.Foo<? extends String>", type.getCanonicalText());
   }
 
+  public void testNoPsiModificationsInUncommittedDocument() {
+    final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class A{}");
+    Document document = file.getViewProvider().getDocument();
+    document.insertString(0, " ");
+
+    PsiClass psiClass = file.getClasses()[0];
+    try {
+      psiClass.addBefore(PsiParserFacade.SERVICE.getInstance(getProject()).createWhiteSpaceFromText(" "), psiClass.getLBrace());
+      fail();
+    }
+    catch (IllegalStateException e) {
+      assertEquals("Attempt to modify PSI for non-committed Document!", e.getMessage());
+    }
+    assertEquals("class A{}", psiClass.getText());
+    assertEquals(" class A{}", document.getText());
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
index d11a34f..7b1861b 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
@@ -385,4 +385,28 @@
       ]
     )
   }
+  
+  void "test IDEA-128071"() {
+    doTest(
+      initial: '''
+public class FormatTest {
+    public int a = 3;
+    private static final String FACEBOOK_CLIENT_ID = "";
+    public static final String FACEBOOK_OAUTH_URL = "".concat(FACEBOOK_CLIENT_ID).concat("");
+}
+''',
+      expected: '''
+public class FormatTest {
+    private static final String FACEBOOK_CLIENT_ID = "";
+    public static final String FACEBOOK_OAUTH_URL = "".concat(FACEBOOK_CLIENT_ID).concat("");
+    public int a = 3;
+}
+''',
+      rules: [
+        rule(PUBLIC, STATIC, FINAL),
+        rule(PRIVATE, STATIC, FINAL),
+        rule(PUBLIC)
+      ]
+    )
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
index 204525c..e830594 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
@@ -208,6 +208,10 @@
     doTest("foo2");
   }
 
+  public void testRenameMethodNoCollisionWithOtherSignatureMethodRef() throws Exception {
+    doTest("foo2");
+  }
+
   public void testRenameNoStaticOverridingInInterfaces() throws Exception {
     doTest("foo");
   }
diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
index 514348e..0ad26a3 100644
--- a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
+++ b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
@@ -105,15 +105,21 @@
   }
 
   private Module addDependentModule(final Module moduleA, final DependencyScope scope) {
-    final Module moduleB = createModule("b.iml", StdModuleTypes.JAVA);
+    return addDependentModule("b", moduleA, scope, false);
+  }
+
+  private Module addDependentModule(final String name, final Module moduleA,
+                                    final DependencyScope scope,
+                                    final boolean exported) {
+    final Module moduleB = createModule(name + ".iml", StdModuleTypes.JAVA);
 
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
-        VirtualFile rootB = myFixture.findOrCreateDir("b");
+        VirtualFile rootB = myFixture.findOrCreateDir(name);
         VirtualFile outB = myFixture.findOrCreateDir("out");
 
-        ModuleRootModificationUtil.addDependency(moduleA, moduleB, scope, false);
+        ModuleRootModificationUtil.addDependency(moduleA, moduleB, scope, exported);
 
         PsiTestUtil.addSourceRoot(moduleB, rootB);
         PsiTestUtil.setCompilerOutputPath(moduleB, outB.getUrl(), false);
@@ -123,6 +129,25 @@
     return moduleB;
   }
 
+  public void testModuleTwiceInDependents() throws IOException {
+    Module m = createModule("m.iml", StdModuleTypes.JAVA);
+    Module a = createModule("a.iml", StdModuleTypes.JAVA);
+    Module b = createModule("b.iml", StdModuleTypes.JAVA);
+    Module c = createModule("c.iml", StdModuleTypes.JAVA);
+
+    ModuleRootModificationUtil.addDependency(a, m, DependencyScope.COMPILE, false);
+    ModuleRootModificationUtil.addDependency(b, m, DependencyScope.COMPILE, true);
+    ModuleRootModificationUtil.addDependency(a, b, DependencyScope.COMPILE, true);
+    ModuleRootModificationUtil.addDependency(c, a, DependencyScope.COMPILE, true);
+    
+    VirtualFile root = myFixture.findOrCreateDir("c");
+    PsiTestUtil.addSourceContentToRoots(c, root);
+    VirtualFile file = root.createChildData(this, "x.txt");
+
+    GlobalSearchScope deps = m.getModuleWithDependentsScope();
+    assertTrue(deps.contains(file));
+  }
+
   public void testTestOnlyLibraryDependency() throws IOException {
     Module m = createModule("a.iml", StdModuleTypes.JAVA);
     addLibrary(m, DependencyScope.TEST);
diff --git a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
index 6e34ebf..b6d8840 100644
--- a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
+++ b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
@@ -49,7 +49,8 @@
     SliceUsage usage = SliceUsage.createRootUsage(element, params);
 
 
-    SlicePanel panel = new SlicePanel(getProject(), true, new SliceRootNode(getProject(), new DuplicateMap(), usage), false, ToolWindowHeadlessManagerImpl.HEADLESS_WINDOW) {
+    ToolWindowHeadlessManagerImpl.MockToolWindow toolWindow = new ToolWindowHeadlessManagerImpl.MockToolWindow(myProject);
+    SlicePanel panel = new SlicePanel(getProject(), true, new SliceRootNode(getProject(), new DuplicateMap(), usage), false, toolWindow) {
       @Override
       protected void close() {
       }
diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
index 6eda197..6100c98 100644
--- a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
+++ b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
@@ -21,9 +21,6 @@
  * @author yole
  */
 public abstract class JavaJspElementVisitor extends JavaElementVisitor {
-  public void visitJspImplicitVariable(JspImplicitVariable variable){
-    visitImplicitVariable(variable);
-  }
 
   public void visitJspFile(JspFile jspFile) {
     visitFile(jspFile);    
diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java b/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java
deleted file mode 100644
index 921cc80..0000000
--- a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2000-2009 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.psi.jsp;
-
-import com.intellij.pom.Navigatable;
-import com.intellij.psi.ImplicitVariable;
-import com.intellij.psi.PsiElement;
-import com.intellij.navigation.NavigationItem;
-
-public interface JspImplicitVariable extends ImplicitVariable, NavigationItem {
-  JspImplicitVariable[] EMPTY_ARRAY = new JspImplicitVariable[0];
-  int INSIDE = 1;
-  int AFTER = 2;
-  int getDeclarationRange();
-
-  PsiElement getDeclaration();
-}
\ No newline at end of file
diff --git a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
index 05500e3..b93deaf 100644
--- a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
+++ b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
@@ -17,15 +17,20 @@
 package com.intellij.ui.classFilter;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.DefaultJDOMExternalizer;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizable;
+import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.util.xmlb.annotations.Attribute;
 import com.intellij.util.xmlb.annotations.Tag;
 import com.intellij.util.xmlb.annotations.Transient;
+import org.jdom.Element;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 @Tag("class-filter")
-public class ClassFilter implements Cloneable {
+public class ClassFilter implements JDOMExternalizable, Cloneable{
   private static final Logger LOG = Logger.getInstance("#com.intellij.ui.classFilter.ClassFilter");
   public static final ClassFilter[] EMPTY_ARRAY = new ClassFilter[0];
 
@@ -67,6 +72,16 @@
     return getPattern();
   }
 
+  @Override
+  public void readExternal(Element element) throws InvalidDataException {
+    DefaultJDOMExternalizer.readExternal(this, element);
+  }
+
+  @Override
+  public void writeExternal(Element element) throws WriteExternalException {
+    DefaultJDOMExternalizer.writeExternal(this, element);
+  }
+
   public boolean equals(Object o) {
     if (this == o) return true;
     if (!(o instanceof ClassFilter)) return false;
diff --git a/java/remote-servers/impl/remote-servers-java-impl.iml b/java/remote-servers/impl/remote-servers-java-impl.iml
index 6999e2d..1578147 100644
--- a/java/remote-servers/impl/remote-servers-java-impl.iml
+++ b/java/remote-servers/impl/remote-servers-java-impl.iml
@@ -15,6 +15,7 @@
     <orderEntry type="module" module-name="remote-servers-impl" />
     <orderEntry type="module" module-name="java-impl" />
     <orderEntry type="module" module-name="openapi" />
+    <orderEntry type="module" module-name="idea-ui" />
   </component>
 </module>
 
diff --git a/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml b/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
index 24a0776..692199e 100644
--- a/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
+++ b/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
@@ -2,7 +2,7 @@
 
   <extensionPoints>
     <extensionPoint qualifiedName="com.intellij.remoteServer.moduleBuilderContribution"
-                    interface="com.intellij.remoteServer.impl.module.CloudModuleBuilderContribution"/>
+                    interface="com.intellij.remoteServer.impl.module.CloudModuleBuilderContributionFactory"/>
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij">
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
index 14bd043..e235eee 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
@@ -15,152 +15,20 @@
  */
 package com.intellij.remoteServer.impl.module;
 
-import com.intellij.openapi.Disposable;
 import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
 import com.intellij.remoteServer.configuration.RemoteServer;
-import com.intellij.remoteServer.runtime.Deployment;
-import com.intellij.remoteServer.runtime.ServerConnection;
-import com.intellij.remoteServer.runtime.ServerConnector;
-import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
-import com.intellij.remoteServer.util.*;
-import com.intellij.util.concurrency.Semaphore;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import javax.swing.*;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
+import java.awt.*;
 
 
-public abstract class CloudApplicationConfigurable<
-  SC extends CloudConfigurationBase,
-  DC extends CloudDeploymentNameConfiguration,
-  SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>,
-  AC extends CloudApplicationConfiguration> {
+public abstract class CloudApplicationConfigurable {
 
-  private final Project myProject;
-  private final Disposable myParentDisposable;
+  public abstract Component getComponent();
 
-  private DelayedRunner myRunner;
+  public abstract void setAccount(RemoteServer<?> account);
 
-  private RemoteServer<?> myAccount;
-
-  public CloudApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
-    myProject = project;
-    myParentDisposable = parentDisposable;
-  }
-
-  public void setAccount(RemoteServer<?> account) {
-    myAccount = account;
-    clearCloudData();
-  }
-
-  protected RemoteServer<SC> getAccount() {
-    return (RemoteServer<SC>)myAccount;
-  }
-
-  public JComponent getComponent() {
-    JComponent result = getMainPanel();
-    if (myRunner == null) {
-      myRunner = new DelayedRunner(result) {
-
-        private RemoteServer<?> myPreviousAccount;
-
-        @Override
-        protected boolean wasChanged() {
-          boolean result = myPreviousAccount != myAccount;
-          if (result) {
-            myPreviousAccount = myAccount;
-          }
-          return result;
-        }
-
-        @Override
-        protected void run() {
-          loadCloudData();
-        }
-      };
-      Disposer.register(myParentDisposable, myRunner);
-    }
-    return result;
-  }
-
-  protected void clearCloudData() {
-    getExistingComboBox().removeAllItems();
-  }
-
-  protected void loadCloudData() {
-    new ConnectionTask<Collection<Deployment>>("Loading existing applications list") {
-
-      @Override
-      protected void run(final ServerConnection<DC> connection,
-                         final Semaphore semaphore,
-                         final AtomicReference<Collection<Deployment>> result) {
-        connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
-
-          @Override
-          public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
-            connection.computeDeployments(new Runnable() {
-
-              @Override
-              public void run() {
-                result.set(connection.getDeployments());
-                semaphore.up();
-                UIUtil.invokeLaterIfNeeded(new Runnable() {
-                  @Override
-                  public void run() {
-                    if (!Disposer.isDisposed(myParentDisposable)) {
-                      setupExistingApplications(result.get());
-                    }
-                  }
-                });
-              }
-            });
-          }
-
-          @Override
-          public void errorOccurred(@NotNull String errorMessage) {
-            runtimeErrorOccurred(errorMessage);
-            semaphore.up();
-          }
-        });
-      }
-
-      @Override
-      protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
-        return null;
-      }
-    }.performAsync();
-  }
-
-  private void setupExistingApplications(Collection<Deployment> deployments) {
-    JComboBox existingComboBox = getExistingComboBox();
-    existingComboBox.removeAllItems();
-    for (Deployment deployment : deployments) {
-      existingComboBox.addItem(deployment.getName());
-    }
-  }
-
-  protected Project getProject() {
-    return myProject;
-  }
-
-  protected abstract JComboBox getExistingComboBox();
-
-  protected abstract JComponent getMainPanel();
-
-  public abstract AC createConfiguration();
+  public abstract CloudApplicationConfiguration createConfiguration();
 
   public abstract void validate() throws ConfigurationException;
-
-  protected abstract class ConnectionTask<T> extends CloudConnectionTask<T, SC, DC, SR> {
-
-    public ConnectionTask(String title) {
-      super(myProject, title, CloudApplicationConfigurable.this.getAccount());
-    }
-  }
 }
 
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
index 9af0f1a..af9fa72 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
@@ -18,19 +18,4 @@
 
 public abstract class CloudApplicationConfiguration {
 
-  private boolean myExisting;
-  private final String myExistingAppName;
-
-  protected CloudApplicationConfiguration(boolean existing, String existingAppName) {
-    myExisting = existing;
-    myExistingAppName = existingAppName;
-  }
-
-  public boolean isExisting() {
-    return myExisting;
-  }
-
-  public String getExistingAppName() {
-    return myExistingAppName;
-  }
 }
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
index 4aa8d60..62e256c 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
@@ -16,6 +16,7 @@
 package com.intellij.remoteServer.impl.module;
 
 import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
 import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
 import com.intellij.ide.util.projectWizard.ModuleBuilderListener;
 import com.intellij.ide.util.projectWizard.ModuleWizardStep;
@@ -23,20 +24,42 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.module.JavaModuleType;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModifiableRootModel;
 import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remoteServer.ServerType;
 import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.util.containers.hash.HashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import java.util.Map;
 
 
 public class CloudModuleBuilder extends JavaModuleBuilder {
 
   private RemoteServer<?> myAccount;
   private CloudApplicationConfiguration myApplicationConfiguration;
+  private FrameworkSupportModelBase myFrameworkSupportModel;
+
+  private Map<ServerType<?>, CloudModuleBuilderContribution> myCloudType2Contribution;
+  private Project myProject;
 
   public CloudModuleBuilder() {
+    myCloudType2Contribution = new HashMap<ServerType<?>, CloudModuleBuilderContribution>();
+
+    ModuleConfigurationUpdater configurationUpdater = new ModuleConfigurationUpdater() {
+
+      public void update(@NotNull final Module module, @NotNull final ModifiableRootModel rootModel) {
+        preConfigureModule(module, rootModel);
+      }
+    };
+    addModuleConfigurationUpdater(configurationUpdater);
+
     addListener(new ModuleBuilderListener() {
 
       @Override
@@ -93,7 +116,8 @@
   @Nullable
   @Override
   public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
-    return new CloudModuleWizardStep(this, context.getProject(), parentDisposable);
+    myProject = context.getProject();
+    return new CloudModuleWizardStep(this, myProject, parentDisposable);
   }
 
   public void setAccount(RemoteServer<?> account) {
@@ -108,7 +132,43 @@
     myApplicationConfiguration = applicationConfiguration;
   }
 
+  public CloudApplicationConfiguration getApplicationConfiguration() {
+    return myApplicationConfiguration;
+  }
+
+  public CloudModuleBuilderContribution getContribution(ServerType<?> cloudType) {
+    CloudModuleBuilderContribution result = myCloudType2Contribution.get(cloudType);
+    if (result == null) {
+      result = CloudModuleBuilderContributionFactory.getInstanceByType(cloudType).createContribution(this);
+      myCloudType2Contribution.put(cloudType, result);
+    }
+    return result;
+  }
+
+  private CloudModuleBuilderContribution getContribution() {
+    return getContribution(myAccount.getType());
+  }
+
+  private void preConfigureModule(Module module, ModifiableRootModel model) {
+    getContribution().preConfigureModule(module, model);
+  }
+
   private void configureModule(final Module module) {
-    CloudModuleBuilderContribution.getInstanceByType(myAccount.getType()).configureModule(module, myAccount, myApplicationConfiguration);
+    getContribution().configureModule(module);
+  }
+
+  public FrameworkSupportModelBase getFrameworkSupportModel() {
+    if (myFrameworkSupportModel == null) {
+      final LibrariesContainer librariesContainer = LibrariesContainerFactory.createContainer(myProject);
+      myFrameworkSupportModel = new FrameworkSupportModelBase(myProject, this, librariesContainer) {
+
+        @NotNull
+        @Override
+        public String getBaseDirectoryForLibrariesPath() {
+          return StringUtil.notNullize(getContentEntryPath());
+        }
+      };
+    }
+    return myFrameworkSupportModel;
   }
 }
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
index 6643c89..dd2d9d9 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
@@ -16,33 +16,51 @@
 package com.intellij.remoteServer.impl.module;
 
 import com.intellij.openapi.Disposable;
-import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModifiableRootModel;
 import com.intellij.remoteServer.ServerType;
-import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import org.jetbrains.annotations.Nullable;
 
 
 public abstract class CloudModuleBuilderContribution {
 
-  public static final ExtensionPointName<CloudModuleBuilderContribution> EP_NAME
-    = ExtensionPointName.create("com.intellij.remoteServer.moduleBuilderContribution");
+  private final CloudModuleBuilder myModuleBuilder;
 
-  public abstract ServerType<?> getCloudType();
+  private final ServerType<?> myCloudType;
+  private CloudApplicationConfigurable myApplicationConfigurable;
 
-  public abstract CloudApplicationConfigurable createApplicationConfigurable(@Nullable Project project, Disposable parentDisposable);
+  public CloudModuleBuilderContribution(CloudModuleBuilder moduleBuilder, ServerType<?> cloudType) {
+    myModuleBuilder = moduleBuilder;
+    myCloudType = cloudType;
+  }
 
-  public abstract void configureModule(Module module,
-                                       RemoteServer<?> account,
-                                       CloudApplicationConfiguration configuration);
+  protected CloudModuleBuilder getModuleBuilder() {
+    return myModuleBuilder;
+  }
 
-  public static CloudModuleBuilderContribution getInstanceByType(ServerType<?> cloudType) {
-    for (CloudModuleBuilderContribution contribution : EP_NAME.getExtensions()) {
-      if (contribution.getCloudType() == cloudType) {
-        return contribution;
-      }
+  protected ServerType<?> getCloudType() {
+    return myCloudType;
+  }
+
+  public CloudApplicationConfigurable getApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
+    if (myApplicationConfigurable == null) {
+      myApplicationConfigurable = createApplicationConfigurable(project, parentDisposable);
     }
-    return null;
+    return myApplicationConfigurable;
+  }
+
+  public void preConfigureModule(Module module, ModifiableRootModel model) {
+
+  }
+
+  public abstract void configureModule(Module module);
+
+  protected abstract CloudApplicationConfigurable createApplicationConfigurable(@Nullable Project project, Disposable parentDisposable);
+
+  protected DeploymentConfiguration createDeploymentConfiguration(DeploymentSource deploymentSource) {
+    return myCloudType.createDeploymentConfigurator(null).createDefaultConfiguration(deploymentSource);
   }
 }
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java
deleted file mode 100644
index 6a927d9..0000000
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.remoteServer.impl.module;
-
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.execution.configurations.ConfigurationType;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModulePointer;
-import com.intellij.openapi.module.ModulePointerManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.MessageType;
-import com.intellij.remoteServer.ServerType;
-import com.intellij.remoteServer.configuration.RemoteServer;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
-import com.intellij.remoteServer.util.*;
-import com.intellij.remoteServer.util.ssh.SshKeyChecker;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-
-public abstract class CloudModuleBuilderContributionBase<
-  SC extends CloudConfigurationBase,
-  DC extends CloudDeploymentNameConfiguration,
-  AC extends CloudApplicationConfiguration,
-  SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>>
-  extends CloudModuleBuilderContribution {
-
-  @Override
-  public void configureModule(Module module,
-                              RemoteServer<?> account,
-                              CloudApplicationConfiguration applicationConfiguration) {
-    RemoteServer<SC> castedAccount = (RemoteServer<SC>)account;
-    final AC castedApplicationConfiguration = (AC)applicationConfiguration;
-
-    DC deploymentConfiguration = createDeploymentConfiguration();
-
-    if (applicationConfiguration.isExisting()) {
-      deploymentConfiguration.setDefaultDeploymentName(false);
-      deploymentConfiguration.setDeploymentName(applicationConfiguration.getExistingAppName());
-    }
-
-    final DeployToServerRunConfiguration<SC, DC> runConfiguration = createRunConfiguration(module, castedAccount, deploymentConfiguration);
-
-    final String cloudName = account.getType().getPresentableName();
-    final Project project = module.getProject();
-    new CloudConnectionTask<Object, SC, DC, SR>(project, CloudBundle.getText("cloud.support", cloudName), castedAccount) {
-
-      CloudNotifier myNotifier = new CloudNotifier(cloudName);
-
-      boolean myFirstAttempt = true;
-
-      @Override
-      protected Object run(SR serverRuntime) throws ServerRuntimeException {
-        doConfigureModule(castedApplicationConfiguration, runConfiguration, myFirstAttempt, serverRuntime);
-        myNotifier.showMessage(CloudBundle.getText("cloud.support.added", cloudName), MessageType.INFO);
-        return null;
-      }
-
-      @Override
-      protected void runtimeErrorOccurred(@NotNull String errorMessage) {
-        myFirstAttempt = false;
-        new SshKeyChecker().checkServerError(errorMessage, myNotifier, project, this);
-      }
-    }.performAsync();
-  }
-
-  private DeployToServerRunConfiguration<SC, DC> createRunConfiguration(Module module,
-                                                                        RemoteServer<SC> server,
-                                                                        DC deploymentConfiguration) {
-    Project project = module.getProject();
-
-    String serverName = server.getName();
-
-    String name = generateRunConfigurationName(serverName, module.getName());
-
-    final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
-    final RunnerAndConfigurationSettings runSettings
-      = runManager.createRunConfiguration(name, getRunConfigurationType().getConfigurationFactories()[0]);
-
-    final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
-
-    result.setServerName(serverName);
-
-    final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
-    result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
-
-    result.setDeploymentConfiguration(deploymentConfiguration);
-
-    runManager.addConfiguration(runSettings, false);
-    runManager.setSelectedConfiguration(runSettings);
-
-    return result;
-  }
-
-  private static String generateRunConfigurationName(String serverName, String moduleName) {
-    return CloudBundle.getText("run.configuration.name", serverName, moduleName);
-  }
-
-  private DeployToServerConfigurationType getRunConfigurationType() {
-    String id = DeployToServerConfigurationType.getId(getCloudType());
-    for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
-      if (configurationType instanceof DeployToServerConfigurationType) {
-        DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
-        if (deployConfigurationType.getId().equals(id)) {
-          return deployConfigurationType;
-        }
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public abstract ServerType<SC> getCloudType();
-
-  @Override
-  public abstract CloudApplicationConfigurable<SC, DC, SR, AC> createApplicationConfigurable(@Nullable Project project,
-                                                                                             Disposable parentDisposable);
-
-  protected abstract DC createDeploymentConfiguration();
-
-  protected abstract void doConfigureModule(AC applicationConfiguration,
-                                            DeployToServerRunConfiguration<SC, DC> runConfiguration,
-                                            boolean firstAttempt,
-                                            SR serverRuntime) throws ServerRuntimeException;
-}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java
new file mode 100644
index 0000000..20ebc29
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.remoteServer.ServerType;
+
+
+public abstract class CloudModuleBuilderContributionFactory {
+
+  public static final ExtensionPointName<CloudModuleBuilderContributionFactory> EP_NAME
+    = ExtensionPointName.create("com.intellij.remoteServer.moduleBuilderContribution");
+
+  public abstract ServerType<?> getCloudType();
+
+  public abstract CloudModuleBuilderContribution createContribution(CloudModuleBuilder moduleBuilder);
+
+  public static CloudModuleBuilderContributionFactory getInstanceByType(ServerType<?> cloudType) {
+    for (CloudModuleBuilderContributionFactory contribution : EP_NAME.getExtensions()) {
+      if (contribution.getCloudType() == cloudType) {
+        return contribution;
+      }
+    }
+    return null;
+  }
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java
new file mode 100644
index 0000000..b5fdcc3
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.ide.util.newProjectWizard.StepSequence;
+import com.intellij.ide.util.newProjectWizard.modes.CreateFromSourcesMode;
+import com.intellij.ide.util.projectWizard.AbstractStepWithProgress;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.util.projectWizard.ProjectBuilder;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.util.*;
+import com.intellij.remoteServer.util.ssh.SshKeyChecker;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+
+public abstract class CloudModuleBuilderSourceContribution<
+  SC extends CloudConfigurationBase,
+  DC extends CloudDeploymentNameConfiguration,
+  AC extends CloudSourceApplicationConfiguration,
+  SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>>
+  extends CloudModuleBuilderContribution {
+
+  private CloudNotifier myNotifier;
+
+  public CloudModuleBuilderSourceContribution(CloudModuleBuilder moduleBuilder, ServerType<SC> cloudType) {
+    super(moduleBuilder, cloudType);
+  }
+
+  @Override
+  public void configureModule(final Module module) {
+    final CloudModuleBuilder moduleBuilder = getModuleBuilder();
+    RemoteServer<SC> account = (RemoteServer<SC>)moduleBuilder.getAccount();
+    final AC applicationConfiguration = (AC)moduleBuilder.getApplicationConfiguration();
+
+    DC deploymentConfiguration = createDeploymentConfiguration();
+
+    if (applicationConfiguration.isExisting()) {
+      deploymentConfiguration.setDefaultDeploymentName(false);
+      deploymentConfiguration.setDeploymentName(applicationConfiguration.getExistingAppName());
+    }
+
+    final DeployToServerRunConfiguration<SC, DC> runConfiguration
+      = CloudRunConfigurationUtil.createRunConfiguration(account, module, deploymentConfiguration);
+
+    final ServerType<?> cloudType = account.getType();
+    final Project project = module.getProject();
+    new CloudConnectionTask<Object, SC, DC, SR>(project,
+                                                CloudBundle.getText("cloud.support", cloudType.getPresentableName()),
+                                                account) {
+
+      boolean myFirstAttempt = true;
+
+      @Override
+      protected Object run(SR serverRuntime) throws ServerRuntimeException {
+        doConfigureModule(applicationConfiguration, runConfiguration, myFirstAttempt, serverRuntime);
+        return null;
+      }
+
+      @Override
+      protected void runtimeErrorOccurred(@NotNull String errorMessage) {
+        myFirstAttempt = false;
+        new SshKeyChecker().checkServerError(errorMessage, getNotifier(), project, this);
+      }
+
+      @Override
+      protected void postPerform(Object result) {
+        detectModuleStructure(module, moduleBuilder.getContentEntryPath());
+      }
+
+      @Override
+      protected boolean shouldStartInBackground() {
+        return false;
+      }
+    }.performAsync();
+  }
+
+  private CloudNotifier getNotifier() {
+    if (myNotifier == null) {
+      myNotifier = new CloudNotifier(getCloudType().getPresentableName());
+    }
+    return myNotifier;
+  }
+
+  private void detectModuleStructure(Module module, final String contentPath) {
+    final Project project = module.getProject();
+
+    final CreateFromSourcesMode mode = new CreateFromSourcesMode() {
+
+      @Override
+      public boolean isAvailable(WizardContext context) {
+        return true;
+      }
+
+      @Override
+      public void addSteps(WizardContext context, ModulesProvider modulesProvider, StepSequence sequence, String specific) {
+        super.addSteps(context, modulesProvider, sequence, specific);
+        myProjectBuilder.setFileToImport(contentPath);
+      }
+    };
+
+    final WizardContext context = new WizardContext(project);
+
+    final StepSequence stepSequence = mode.getSteps(context, DefaultModulesProvider.createForProject(context.getProject()));
+    if (stepSequence == null) {
+      return;
+    }
+
+    Disposer.register(project, new Disposable() {
+
+      @Override
+      public void dispose() {
+        for (ModuleWizardStep step : stepSequence.getAllSteps()) {
+          step.disposeUIResources();
+        }
+      }
+    });
+
+    ProgressManager.getInstance()
+      .run(new Task.Backgroundable(project, CloudBundle.getText("detect.module.structure", getCloudType().getPresentableName()), false) {
+
+        @Override
+        public void run(@NotNull ProgressIndicator indicator) {
+          for (ModuleWizardStep step = ContainerUtil.getFirstItem(stepSequence.getSelectedSteps());
+               step != null;
+               step = stepSequence.getNextStep(step)) {
+            if (step instanceof AbstractStepWithProgress<?>) {
+              ((AbstractStepWithProgress)step).performStep();
+            }
+            else {
+              step.updateDataModel();
+            }
+          }
+          CloudAccountSelectionEditor.unsetAccountOnContext(context, getCloudType());
+        }
+
+        @Override
+        public boolean shouldStartInBackground() {
+          return false;
+        }
+
+        @Override
+        public void onSuccess() {
+          ProjectBuilder moduleBuilder = mode.getModuleBuilder();
+          if (moduleBuilder == null) {
+            return;
+          }
+          moduleBuilder.commit(project);
+          getNotifier().showMessage(CloudBundle.getText("cloud.support.added", getCloudType().getPresentableName()), MessageType.INFO);
+        }
+      });
+  }
+
+  @Override
+  protected abstract CloudSourceApplicationConfigurable<SC, DC, SR, AC> createApplicationConfigurable(@Nullable Project project,
+                                                                                                      Disposable parentDisposable);
+
+  protected abstract DC createDeploymentConfiguration();
+
+  protected abstract void doConfigureModule(AC applicationConfiguration,
+                                            DeployToServerRunConfiguration<SC, DC> runConfiguration,
+                                            boolean firstAttempt,
+                                            SR serverRuntime) throws ServerRuntimeException;
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
index cf0e283..79b307b 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
@@ -22,13 +22,13 @@
 import com.intellij.remoteServer.ServerType;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.util.CloudAccountSelectionEditor;
-import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.containers.HashSet;
 
 import javax.swing.*;
 import java.awt.*;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
+import java.util.Set;
 
 
 public class CloudModuleWizardStep extends ModuleWizardStep {
@@ -43,17 +43,17 @@
 
   private CloudAccountSelectionEditor myAccountSelectionPanel;
 
-  private Map<ServerType<?>, CloudApplicationConfigurable> myCloudType2ApplicationConfigurable;
+  private Set<ServerType<?>> myApplicationConfigurableTypes;
 
   public CloudModuleWizardStep(CloudModuleBuilder moduleBuilder, Project project, Disposable parentDisposable) {
     myModuleBuilder = moduleBuilder;
     myProject = project;
     myParentDisposable = parentDisposable;
 
-    myCloudType2ApplicationConfigurable = new HashMap<ServerType<?>, CloudApplicationConfigurable>();
+    myApplicationConfigurableTypes = new HashSet<ServerType<?>>();
 
     List<ServerType<?>> cloudTypes = new ArrayList<ServerType<?>>();
-    for (CloudModuleBuilderContribution contribution : CloudModuleBuilderContribution.EP_NAME.getExtensions()) {
+    for (CloudModuleBuilderContributionFactory contribution : CloudModuleBuilderContributionFactory.EP_NAME.getExtensions()) {
       cloudTypes.add(contribution.getCloudType());
     }
 
@@ -86,11 +86,8 @@
 
     ServerType<?> cloudType = account.getType();
     String cardName = cloudType.getId();
-    CloudApplicationConfigurable<?, ?, ?, ?> applicationConfigurable = getApplicationConfigurable();
-    if (applicationConfigurable == null) {
-      applicationConfigurable
-        = CloudModuleBuilderContribution.getInstanceByType(cloudType).createApplicationConfigurable(myProject, myParentDisposable);
-      myCloudType2ApplicationConfigurable.put(cloudType, applicationConfigurable);
+    CloudApplicationConfigurable applicationConfigurable = getApplicationConfigurable();
+    if (myApplicationConfigurableTypes.add(cloudType)) {
       myApplicationPanelPlaceHolder.add(applicationConfigurable.getComponent(), cardName);
     }
     applicationPlaceHolderLayout.show(myApplicationPanelPlaceHolder, cardName);
@@ -103,25 +100,25 @@
     return myMainPanel;
   }
 
-  private CloudApplicationConfigurable<?, ?, ?, ?> getApplicationConfigurable() {
+  private CloudApplicationConfigurable getApplicationConfigurable() {
     RemoteServer<?> account = getSelectedAccount();
     if (account == null) {
       return null;
     }
-    return myCloudType2ApplicationConfigurable.get(account.getType());
+    return myModuleBuilder.getContribution(account.getType()).getApplicationConfigurable(myProject, myParentDisposable);
   }
 
   @Override
   public void updateDataModel() {
     myModuleBuilder.setAccount(myAccountSelectionPanel.getSelectedAccount());
-    CloudApplicationConfigurable<?, ?, ?, ?> configurable = getApplicationConfigurable();
+    CloudApplicationConfigurable configurable = getApplicationConfigurable();
     myModuleBuilder.setApplicationConfiguration(configurable == null ? null : configurable.createConfiguration());
   }
 
   @Override
   public boolean validate() throws ConfigurationException {
     myAccountSelectionPanel.validate();
-    CloudApplicationConfigurable<?, ?, ?, ?> configurable = getApplicationConfigurable();
+    CloudApplicationConfigurable configurable = getApplicationConfigurable();
     if (configurable != null) {
       configurable.validate();
     }
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java
new file mode 100644
index 0000000..b6e0dfc
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.runtime.Deployment;
+import com.intellij.remoteServer.runtime.ServerConnection;
+import com.intellij.remoteServer.runtime.ServerConnector;
+import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
+import com.intellij.remoteServer.util.*;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+public abstract class CloudSourceApplicationConfigurable<
+  SC extends CloudConfigurationBase,
+  DC extends CloudDeploymentNameConfiguration,
+  SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>,
+  AC extends CloudApplicationConfiguration> extends CloudApplicationConfigurable {
+
+  private final Project myProject;
+  private final Disposable myParentDisposable;
+
+  private DelayedRunner myRunner;
+
+  private RemoteServer<?> myAccount;
+
+  public CloudSourceApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
+    myProject = project;
+    myParentDisposable = parentDisposable;
+  }
+
+  @Override
+  public void setAccount(RemoteServer<?> account) {
+    myAccount = account;
+    clearCloudData();
+  }
+
+  protected RemoteServer<SC> getAccount() {
+    return (RemoteServer<SC>)myAccount;
+  }
+
+  @Override
+  public JComponent getComponent() {
+    JComponent result = getMainPanel();
+    if (myRunner == null) {
+      myRunner = new DelayedRunner(result) {
+
+        private RemoteServer<?> myPreviousAccount;
+
+        @Override
+        protected boolean wasChanged() {
+          boolean result = myPreviousAccount != myAccount;
+          if (result) {
+            myPreviousAccount = myAccount;
+          }
+          return result;
+        }
+
+        @Override
+        protected void run() {
+          loadCloudData();
+        }
+      };
+      Disposer.register(myParentDisposable, myRunner);
+    }
+    return result;
+  }
+
+  protected void clearCloudData() {
+    getExistingComboBox().removeAllItems();
+  }
+
+  protected void loadCloudData() {
+    new ConnectionTask<Collection<Deployment>>("Loading existing applications list") {
+
+      @Override
+      protected void run(final ServerConnection<DC> connection,
+                         final Semaphore semaphore,
+                         final AtomicReference<Collection<Deployment>> result) {
+        connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
+
+          @Override
+          public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
+            connection.computeDeployments(new Runnable() {
+
+              @Override
+              public void run() {
+                result.set(connection.getDeployments());
+                semaphore.up();
+                UIUtil.invokeLaterIfNeeded(new Runnable() {
+                  @Override
+                  public void run() {
+                    if (!Disposer.isDisposed(myParentDisposable)) {
+                      setupExistingApplications(result.get());
+                    }
+                  }
+                });
+              }
+            });
+          }
+
+          @Override
+          public void errorOccurred(@NotNull String errorMessage) {
+            runtimeErrorOccurred(errorMessage);
+            semaphore.up();
+          }
+        });
+      }
+
+      @Override
+      protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
+        return null;
+      }
+    }.performAsync();
+  }
+
+  private void setupExistingApplications(Collection<Deployment> deployments) {
+    JComboBox existingComboBox = getExistingComboBox();
+    existingComboBox.removeAllItems();
+    for (Deployment deployment : deployments) {
+      existingComboBox.addItem(deployment.getName());
+    }
+  }
+
+  protected Project getProject() {
+    return myProject;
+  }
+
+  protected abstract JComboBox getExistingComboBox();
+
+  protected abstract JComponent getMainPanel();
+
+  @Override
+  public abstract AC createConfiguration();
+
+  protected abstract class ConnectionTask<T> extends CloudConnectionTask<T, SC, DC, SR> {
+
+    public ConnectionTask(String title) {
+      super(myProject, title, CloudSourceApplicationConfigurable.this.getAccount());
+    }
+  }
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java
new file mode 100644
index 0000000..b1a3df6
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package com.intellij.remoteServer.impl.module;
+
+
+public abstract class CloudSourceApplicationConfiguration extends CloudApplicationConfiguration {
+
+  private boolean myExisting;
+  private final String myExistingAppName;
+
+  protected CloudSourceApplicationConfiguration(boolean existing, String existingAppName) {
+    myExisting = existing;
+    myExistingAppName = existingAppName;
+  }
+
+  public boolean isExisting() {
+    return myExisting;
+  }
+
+  public String getExistingAppName() {
+    return myExistingAppName;
+  }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
index 49db796..7e3c5f9 100644
--- a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
+++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
@@ -184,23 +184,24 @@
         for(int i = 0; i < tree.getRowCount(); i++) {
           final TreeNode treeNode = (TreeNode)tree.getPathForRow(i).getLastPathComponent();
           if(tree.isCollapsed(i) && !treeNode.isLeaf()) {
+            NodeDescriptor nodeDescriptor = null;
             if (treeNode instanceof DebuggerTreeNodeImpl) {
-              final NodeDescriptor nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor();
-              boolean shouldExpand = filter == null || filter.shouldExpand(treeNode);
-              if (shouldExpand) {
-                // additional checks to prevent infinite expand
-                if (nodeDescriptor instanceof ValueDescriptor) {
-                  final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
-                  shouldExpand = !alreadyExpanded.contains(value);
-                  if (shouldExpand) {
-                    alreadyExpanded.add(value);
-                  }
+              nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor();
+            }
+            boolean shouldExpand = filter == null || filter.shouldExpand(treeNode);
+            if (shouldExpand) {
+              // additional checks to prevent infinite expand
+              if (nodeDescriptor instanceof ValueDescriptor) {
+                final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
+                shouldExpand = !alreadyExpanded.contains(value);
+                if (shouldExpand) {
+                  alreadyExpanded.add(value);
                 }
               }
-              if (shouldExpand) {
-                anyCollapsed = true;
-                tree.expandRow(i);
-              }
+            }
+            if (shouldExpand) {
+              anyCollapsed = true;
+              tree.expandRow(i);
             }
           }
         }
diff --git a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
index 087180b..b65b58b 100644
--- a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
+++ b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
@@ -24,12 +24,10 @@
   }
 
   public static void runFindInCommentsAndLiterals(FindManager findManager, FindModel findModel, String text, String ext) {
-    findModel.setInStringLiteralsOnly(true);
-    findModel.setInCommentsOnly(false);
+    findModel.setSearchContext(FindModel.SearchContext.IN_STRING_LITERALS);
     runFindForwardAndBackward(findManager, findModel, text, ext);
 
-    findModel.setInStringLiteralsOnly(false);
-    findModel.setInCommentsOnly(true);
+    findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
     runFindForwardAndBackward(findManager, findModel, text, ext);
   }
 
diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml
index 565691f..993bfad 100644
--- a/jps/jps-builders/jps-builders.iml
+++ b/jps/jps-builders/jps-builders.iml
@@ -35,7 +35,6 @@
     <orderEntry type="module" module-name="jps-model-api" />
     <orderEntry type="module" module-name="jps-model-serialization" />
     <orderEntry type="module" module-name="jps-model-impl" />
-    <orderEntry type="library" scope="TEST" name="Groovy" level="project" />
     <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
     <orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
   </component>
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
index 16a3da4..18419a3 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
@@ -29,6 +29,7 @@
 
   public interface Backend {
     void associate(String classFileName, String sourceFileName, ClassReader cr);
+    void associate(String classFileName, Collection<String> sources, ClassReader cr);
     void registerImports(String className, Collection<String> imports, Collection<String> staticImports);
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
index b5415ce..7699e20 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
@@ -28,7 +28,7 @@
  * @author: db
  * Date: 03.11.11
  */
-abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable {
+abstract class IntObjectMultiMaplet<V> implements Streamable {
   abstract boolean containsKey(final int key);
 
   abstract Collection<V> get(final int key);
@@ -78,12 +78,17 @@
       final List<String> list = new LinkedList<String>();
 
       for (final V value : b) {
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        final PrintStream s = new PrintStream(baos);
+        if (value instanceof Streamable) {
+          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+          final PrintStream s = new PrintStream(baos);
 
-        value.toStream(context, s);
+          ((Streamable)value).toStream(context, s);
 
-        list.add(baos.toString());
+          list.add(baos.toString());
+        }
+        else {
+          list.add(value.toString());
+        }
       }
 
       Collections.sort(list);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
index 3dd4d44..39fbd5b 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
@@ -32,7 +32,7 @@
  * @author: db
  * Date: 08.03.11
  */
-class IntObjectPersistentMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+class IntObjectPersistentMultiMaplet<V> extends IntObjectMultiMaplet<V> {
   private static final Collection NULL_COLLECTION = Collections.emptySet();
   private static final int CACHE_SIZE = 128;
   private final PersistentHashMap<Integer, Collection<V>> myMap;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
index 2f58180..f19bcfd 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
@@ -24,7 +24,7 @@
  * @author: db
  * Date: 08.03.11
  */
-class IntObjectTransientMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+class IntObjectTransientMultiMaplet<V> extends IntObjectMultiMaplet<V> {
 
   private final TIntObjectHashMap<Collection<V>> myMap = new TIntObjectHashMap<Collection<V>>();
   private final CollectionFactory<V> myCollectionFactory;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
index a397d4b..3e3a479 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
@@ -85,7 +85,7 @@
   */
   private IntIntMultiMaplet myClassToClassDependency;
   private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
-  private IntObjectMaplet<File> myClassToSourceFile;
+  private IntObjectMultiMaplet<File> myClassToSourceFile;
   /**
    * [short className] -> list of FQ names
    */
@@ -138,12 +138,17 @@
     myRemovedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
     myAddedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
 
+    final CollectionFactory<File> fileCollectionFactory = new CollectionFactory<File>() {
+      public Collection<File> create() {
+        return new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); // todo: do we really need set and not a list here?
+      }
+    };
     if (myIsDelta && myDeltaIsTransient) {
       myClassToSubclasses = new IntIntTransientMultiMaplet();
       myClassToClassDependency = new IntIntTransientMultiMaplet();
       myShortClassNameIndex = null;
       mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
-      myClassToSourceFile = new IntObjectTransientMaplet<File>();
+      myClassToSourceFile = new IntObjectTransientMultiMaplet<File>(fileCollectionFactory);
     }
     else {
       if (myIsDelta) {
@@ -156,7 +161,7 @@
         DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
         ourClassSetConstructor
       );
-      myClassToSourceFile = new IntObjectPersistentMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), new FileKeyDescriptor());
+      myClassToSourceFile = new IntObjectPersistentMultiMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR, new FileKeyDescriptor(), fileCollectionFactory);
     }
   }
 
@@ -190,17 +195,17 @@
   }
 
   @Nullable
-  private ClassRepr getReprByName(@Nullable File source, final int name) {
-    if (source == null) {
-      source = myClassToSourceFile.get(name);
-    }
-    if (source != null) {
-      final Collection<ClassRepr> reprs = mySourceFileToClasses.get(source);
+  private ClassRepr getReprByName(final @Nullable File source, final int qName) {
+    final Collection<File> sources = source != null? Collections.singleton(source) : myClassToSourceFile.get(qName);
+    if (sources != null) {
+      for (File src : sources) {
+        final Collection<ClassRepr> reprs = mySourceFileToClasses.get(src);
 
-      if (reprs != null) {
-        for (ClassRepr repr : reprs) {
-          if (repr.name == name) {
-            return repr;
+        if (reprs != null) {
+          for (ClassRepr repr : reprs) {
+            if (repr.name == qName) {
+              return repr;
+            }
           }
         }
       }
@@ -556,14 +561,19 @@
     void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages, final Collection<File> alreadyCompiledFiles) {
       debug("Affecting subclasses of class: ", className);
 
-      final File fileName = myClassToSourceFile.get(className);
-      if (fileName == null) {
+      final Collection<File> allSources = myClassToSourceFile.get(className);
+      if (allSources == null || allSources.isEmpty()) {
         debug("No source file detected for class ", className);
         debug("End of affectSubclasses");
         return;
       }
 
-      debug("Source file name: ", fileName);
+      for (File fName : allSources) {
+        debug("Source file name: ", fName);
+        if (!alreadyCompiledFiles.contains(fName)) {
+          affectedFiles.add(fName);
+        }
+      }
 
       if (usages) {
         debug("Class usages affection requested");
@@ -579,9 +589,6 @@
       if (depClasses != null) {
         addAll(dependants, depClasses);
       }
-      if (!alreadyCompiledFiles.contains(fileName)) {
-        affectedFiles.add(fileName);
-      }
 
       final TIntHashSet directSubclasses = myClassToSubclasses.get(className);
       if (directSubclasses != null) {
@@ -701,10 +708,14 @@
       dependants.forEach(new TIntProcedure() {
         @Override
         public boolean execute(int depClass) {
-          final File depFile = myClassToSourceFile.get(depClass);
-          if (depFile != null && !FileUtil.filesEqual(depFile, sourceFile)) {
-            if (filter == null || filter.accept(depFile)) {
-              affectedFiles.add(depFile);
+          final Collection<File> allSources = myClassToSourceFile.get(depClass);
+          if (allSources != null) {
+            for (File depFile : allSources) {
+              if (!FileUtil.filesEqual(depFile, sourceFile)) {
+                if (filter == null || filter.accept(depFile)) {
+                  affectedFiles.add(depFile);
+                }
+              }
             }
           }
           return true;
@@ -757,6 +768,8 @@
       return false;
     }
 
+    final THashSet<File> toRecompile = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
     // Protected branch
     if (member.isProtected()) {
       debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
@@ -766,10 +779,12 @@
       propagated.forEach(new TIntProcedure() {
         @Override
         public boolean execute(int className) {
-          final File fileName = myClassToSourceFile.get(className);
-          if (fileName != null && !currentlyCompiled.contains(fileName)) {
-            debug("Adding ", fileName);
-            affectedFiles.add(fileName);
+          final Collection<File> fileNames = myClassToSourceFile.get(className);
+          if (fileNames != null) {
+            for (File fileName : fileNames) {
+              debug("Adding ", fileName);
+            }
+            toRecompile.addAll(fileNames);
           }
           return true;
         }
@@ -782,19 +797,32 @@
     debug("Package name: ", packageName);
 
     // Package-local branch
-    myClassToSourceFile.forEachEntry(new TIntObjectProcedure<File>() {
+    myClassToSourceFile.forEachEntry(new TIntObjectProcedure<Collection<File>>() {
       @Override
-      public boolean execute(int className, File fileName) {
+      public boolean execute(int className, Collection<File> fileNames) {
         if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
-          if ((filter == null || filter.accept(fileName)) && !currentlyCompiled.contains(fileName)) {
-            debug("Adding: ", fileName);
-            affectedFiles.add(fileName);
+          for (File fileName : fileNames) {
+            if (filter == null || filter.accept(fileName)) {
+              debug("Adding: ", fileName);
+              toRecompile.add(fileName);
+            }
           }
         }
         return true;
       }
     });
 
+    // filtering already compiled and non-existing paths
+    toRecompile.removeAll(currentlyCompiled);
+    for (Iterator<File> it = toRecompile.iterator(); it.hasNext(); ) {
+      final File file = it.next();
+      if (!file.exists()) {
+        it.remove();
+      }
+    }
+
+    affectedFiles.addAll(toRecompile);
+
     return true;
   }
 
@@ -1094,12 +1122,14 @@
             if (overrides.satisfy(method) && isInheritor) {
               debug("Current method overrides that found");
 
-              final File file = myClassToSourceFile.get(methodClass.name);
-
-              if (file != null) {
-                myAffectedFiles.add(file);
-                debug("Affecting file ", file);
+              final Collection<File> files = myClassToSourceFile.get(methodClass.name);
+              if (files != null) {
+                myAffectedFiles.addAll(files);
+                for (File file : files) {
+                  debug("Affecting file ", file);
+                }
               }
+
             }
             else {
               debug("Current method does not override that found");
@@ -1128,12 +1158,15 @@
             @Override
             public boolean execute(int subClass) {
               final ClassRepr r = myFuture.reprByName(subClass);
-              if (r != null) {
-                final File sourceFileName = myClassToSourceFile.get(subClass);
-                if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
-                  final int outerClass = r.getOuterClassName();
-                  if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
-                    myAffectedFiles.add(sourceFileName);
+              if (r == null) {
+                return true;
+              }
+              final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
+              if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
+                final int outerClass = r.getOuterClassName();
+                if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
+                  myAffectedFiles.addAll(sourceFileNames);
+                  for (File sourceFileName : sourceFileNames) {
                     debug("Affecting file due to local overriding: ", sourceFileName);
                   }
                 }
@@ -1186,10 +1219,12 @@
         myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);
 
         for (final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
-          final File fName = myClassToSourceFile.get(p.second.name);
-          if (fName != null) {
-            myAffectedFiles.add(fName);
-            debug("Affecting file by overriding: ", fName);
+          final Collection<File> fNames = myClassToSourceFile.get(p.second.name);
+          if (fNames != null) {
+            myAffectedFiles.addAll(fNames);
+            for (File fName : fNames) {
+              debug("Affecting file by overriding: ", fName);
+            }
           }
         }
 
@@ -1229,12 +1264,14 @@
                   }
 
                   if (allAbstract && visited) {
-                    final File source = myClassToSourceFile.get(p);
+                    final Collection<File> sources = myClassToSourceFile.get(p);
 
-                    if (source != null && !myCompiledFiles.contains(source)) {
-                      myAffectedFiles.add(source);
+                    if (sources != null && !myCompiledFiles.containsAll(sources)) {
+                      myAffectedFiles.addAll(sources);
                       debug("Removed method is not abstract & overrides some abstract method which is not then over-overridden in subclass ", p);
-                      debug("Affecting subclass source file ", source);
+                      for (File source : sources) {
+                        debug("Affecting subclass source file ", source);
+                      }
                     }
                   }
                 }
@@ -1304,9 +1341,9 @@
                 final ClassRepr aClass = p.getSecond();
 
                 if (aClass != MOCK_CLASS) {
-                  final File fileName = myClassToSourceFile.get(aClass.name);
-                  if (fileName != null) {
-                    myAffectedFiles.add(fileName);
+                  final Collection<File> fileNames = myClassToSourceFile.get(aClass.name);
+                  if (fileNames != null) {
+                    myAffectedFiles.addAll(fileNames);
                   }
                 }
               }
@@ -1374,17 +1411,21 @@
             public boolean execute(int subClass) {
               final ClassRepr r = myFuture.reprByName(subClass);
               if (r != null) {
-                final File sourceFileName = myClassToSourceFile.get(subClass);
-                if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
+                final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
+                if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
                   if (r.isLocal()) {
-                    debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
-                    myAffectedFiles.add(sourceFileName);
+                    for (File sourceFileName : sourceFileNames) {
+                      debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
+                    }
+                    myAffectedFiles.addAll(sourceFileNames);
                   }
                   else {
                     final int outerClass = r.getOuterClassName();
                     if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, f)) {
-                      debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
-                      myAffectedFiles.add(sourceFileName);
+                      for (File sourceFileName : sourceFileNames) {
+                        debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
+                      }
+                      myAffectedFiles.addAll(sourceFileNames);
                     }
                   }
                 }
@@ -1783,7 +1824,9 @@
         // checking if this newly added class duplicates already existing one
         for (ClassRepr c : addedClasses) {
           if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
-            final File currentlyMappedTo = myClassToSourceFile.get(c.name);
+            final Collection<File> currentSources = myClassToSourceFile.get(c.name);
+            final File currentlyMappedTo = currentSources != null && currentSources.size() == 1? currentSources.iterator().next() : null;
+            // only check, if exactly one file is mapped
             if (currentlyMappedTo != null && !FileUtil.filesEqual(currentlyMappedTo, srcFile) && currentlyMappedTo.exists() && myFilter.belongsToCurrentTargetChunk(currentlyMappedTo)) {
               // Same classes from different source files.
               // Schedule for recompilation both to make possible 'duplicate sources' error evident
@@ -1832,11 +1875,13 @@
       toAffect.forEach(new TIntProcedure() {
         @Override
         public boolean execute(int depClass) {
-          final File fName = myClassToSourceFile.get(depClass);
-          if (fName != null) {
-            if (myFilter == null || myFilter.accept(fName)) {
-              debug("Adding dependent file ", fName);
-              myAffectedFiles.add(fName);
+          final Collection<File> fNames = myClassToSourceFile.get(depClass);
+          if (fNames != null) {
+            for (File fName : fNames) {
+              if (myFilter == null || myFilter.accept(fName)) {
+                debug("Adding dependent file ", fName);
+                myAffectedFiles.add(fName);
+              }
             }
           }
           return true;
@@ -1850,24 +1895,30 @@
       state.myDependants.forEach(new TIntProcedure() {
         @Override
         public boolean execute(final int depClass) {
-          final File depFile = myClassToSourceFile.get(depClass);
+          final Collection<File> depFiles = myClassToSourceFile.get(depClass);
+          if (depFiles != null) {
+            for (File depFile : depFiles) {
+              processDependentFile(depClass, depFile);
+            }
+          }
+          return true;
+        }
 
-          if (depFile == null || myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
-            return true;
+        private void processDependentFile(int depClass, @NotNull File depFile) {
+          if (myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
+            return;
           }
 
           debug("Dependent class: ", depClass);
 
           final ClassRepr classRepr = getReprByName(depFile, depClass);
-
           if (classRepr == null) {
-            return true;
+            return;
           }
 
           final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
-
           if (depUsages == null || depUsages.isEmpty()) {
-            return true;
+            return;
           }
 
           for (UsageRepr.Usage usage : depUsages) {
@@ -1876,32 +1927,24 @@
                 if (query.satisfies(usage)) {
                   debug("Added file due to annotation query");
                   myAffectedFiles.add(depFile);
-
-                  return true;
+                  return;
                 }
               }
             }
             else if (state.myAffectedUsages.contains(usage)) {
               final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
-
               if (constraint == null) {
                 debug("Added file with no constraints");
                 myAffectedFiles.add(depFile);
-
-                return true;
+                return;
               }
-              else {
-                if (constraint.checkResidence(depClass)) {
-                  debug("Added file with satisfied constraint");
-                  myAffectedFiles.add(depFile);
-
-                  return true;
-                }
+              if (constraint.checkResidence(depClass)) {
+                debug("Added file with satisfied constraint");
+                myAffectedFiles.add(depFile);
+                return;
               }
             }
           }
-
-          return true;
         }
       });
     }
@@ -2007,11 +2050,27 @@
 
   private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
     final int className = cr.name;
-    if (!FileUtil.filesEqual(sourceFile, myClassToSourceFile.get(className))) { 
-      // if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
-      // we cannot destroy all these links
+
+    // it is safe to cleanup class information if it is mapped to non-existing files only
+    final Collection<File> currentlyMapped = myClassToSourceFile.get(className);
+    if (currentlyMapped == null || currentlyMapped.isEmpty()) {
       return;
     }
+    if (currentlyMapped.size() == 1) {
+      if (!FileUtil.filesEqual(sourceFile, currentlyMapped.iterator().next())) {
+        // if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
+        // we cannot destroy all these links
+        return;
+      }
+    }
+    else {
+      // many files
+      for (File file : currentlyMapped) {
+        if (!FileUtil.filesEqual(sourceFile, file) && file.exists()) {
+          return;
+        }
+      }
+    }
 
     for (final int superSomething : cr.getSupers()) {
       delta.registerRemovedSuperClass(className, superSomething);
@@ -2113,13 +2172,8 @@
           delta.getChangedClasses().forEach(new TIntProcedure() {
             @Override
             public boolean execute(final int className) {
-              final File sourceFile = delta.myClassToSourceFile.get(className);
-              if (sourceFile != null) {
-                myClassToSourceFile.put(className, sourceFile);
-              }
-              else {
-                myClassToSourceFile.remove(className);
-              }
+              final Collection<File> sourceFiles = delta.myClassToSourceFile.get(className);
+              myClassToSourceFile.replace(className, sourceFiles);
 
               cleanupBackDependency(className, null, dependenciesTrashBin);
 
@@ -2138,7 +2192,7 @@
         }
         else {
           myClassToSubclasses.putAll(delta.myClassToSubclasses);
-          myClassToSourceFile.putAll(delta.myClassToSourceFile);
+          myClassToSourceFile.replaceAll(delta.myClassToSourceFile);
           mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
           delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
             public boolean execute(File src, Collection<ClassRepr> classes) {
@@ -2203,18 +2257,21 @@
 
   public Callbacks.Backend getCallback() {
     return new Callbacks.Backend() {
-      public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
+
+      public void associate(String classFileName, Collection<String> sources, ClassReader cr) {
         synchronized (myLock) {
           final int classFileNameS = myContext.get(classFileName);
           final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
           final ClassRepr repr = result.first;
           if (repr != null) {
             final Set<UsageRepr.Usage> localUsages = result.second;
-            final File sourceFile = new File(sourceFileName);
             final int className = repr.name;
 
-            myClassToSourceFile.put(className, sourceFile);
-            mySourceFileToClasses.put(sourceFile, repr);
+            for (String sourceFileName : sources) {
+              final File sourceFile = new File(sourceFileName);
+              myClassToSourceFile.put(className, sourceFile);
+              mySourceFileToClasses.put(sourceFile, repr);
+            }
 
             for (final int s : repr.getSupers()) {
               myClassToSubclasses.put(s, className);
@@ -2231,6 +2288,10 @@
         }
       }
 
+      public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
+        associate(classFileName, Collections.singleton(sourceFileName), cr);
+      }
+
       @Override
       public void registerImports(final String className, final Collection<String> imports, Collection<String> staticImports) {
         final List<String> allImports = new ArrayList<String>();
@@ -2252,14 +2313,16 @@
           myPostPasses.offer(new Runnable() {
             public void run() {
               final int rootClassName = myContext.get(className.replace(".", "/"));
-              final File fileName = myClassToSourceFile.get(rootClassName);
-              final ClassRepr repr = fileName != null? getReprByName(fileName, rootClassName) : null;
+              final Collection<File> fileNames = myClassToSourceFile.get(rootClassName);
+              final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getReprByName(fileNames.iterator().next(), rootClassName) : null;
 
               for (final String i : allImports) {
-                final int iname = myContext.get(i.replace(".", "/"));
+                final int iname = myContext.get(i.replace('.', '/'));
                 myClassToClassDependency.put(iname, rootClassName);
                 if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
-                  mySourceFileToClasses.put(fileName, repr);
+                  for (File fileName : fileNames) {
+                    mySourceFileToClasses.put(fileName, repr);
+                  }
                 }
               }
             }
@@ -2386,10 +2449,10 @@
     assert (myChangedClasses != null && myChangedFiles != null);
     myChangedClasses.add(it);
 
-    final File file = myClassToSourceFile.get(it);
+    final Collection<File> files = myClassToSourceFile.get(it);
 
-    if (file != null) {
-      myChangedFiles.add(file);
+    if (files != null) {
+      myChangedFiles.addAll(files);
     }
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
index 551c3ce..bc353aa 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -144,7 +144,7 @@
       public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
         result.set(version);
       }
-    }, 0);
+    }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
     return result.get();
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
index 823fe08..a6ed636 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
@@ -42,7 +42,7 @@
  *         Date: 10/7/11
  */
 public class BuildDataManager implements StorageOwner {
-  private static final int VERSION = 24;
+  private static final int VERSION = 25;
   private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
   private static final String SRC_TO_FORM_STORAGE = "src-form";
   private static final String OUT_TARGET_STORAGE = "out-target";
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt
similarity index 82%
rename from jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy
rename to jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt
index 80770ee..a3017b2 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt
@@ -16,13 +16,14 @@
 package org.jetbrains.jps.builders
 
 import org.jetbrains.jps.builders.rebuild.JpsRebuildTestCase
+import org.jetbrains.jps.builders.rebuild.fs
 
 /**
  * @author nik
  */
-class JavacFileEncodingTest extends JpsRebuildTestCase {
-  public void test() {
-    doTest("javacFileEncoding/javacFileEncoding.ipr", {
+class JavacFileEncodingTest: JpsRebuildTestCase() {
+  fun test() {
+    doTest("javacFileEncoding/javacFileEncoding.ipr", fs {
       dir("production") {
         dir("javacFileEncoding") {
           file("MyClass.class")
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
index 2c3fca0..eb9b42a 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
@@ -225,7 +225,7 @@
       Map<String, String> allPathVariables = new HashMap<String, String>(pathVariables.size() + 1);
       allPathVariables.putAll(pathVariables);
       allPathVariables.put(PathMacroUtil.APPLICATION_HOME_DIR, PathManager.getHomePath());
-      addPathVariables(allPathVariables);
+      allPathVariables.putAll(getAdditionalPathVariables());
       JpsProjectLoader.loadProject(myProject, allPathVariables, fullProjectPath);
     }
     catch (IOException e) {
@@ -233,7 +233,9 @@
     }
   }
 
-  protected void addPathVariables(Map<String, String> pathVariables) {
+  @NotNull
+  protected Map<String, String> getAdditionalPathVariables() {
+    return Collections.emptyMap();
   }
 
   @Nullable
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
index b76196e..cabb841 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
@@ -30,68 +30,68 @@
  * @author nik
  */
 public class ModuleClasspathTest(): JpsBuildTestCase() {
-    override fun setUp() {
-        super.setUp()
-        addJdk("1.6", "/jdk.jar")
-        addJdk("1.5", "/jdk15.jar")
-        loadProject("moduleClasspath/moduleClasspath.ipr")
-    }
+  override fun setUp() {
+    super.setUp()
+    addJdk("1.6", "/jdk.jar")
+    addJdk("1.5", "/jdk15.jar")
+    loadProject("moduleClasspath/moduleClasspath.ipr")
+  }
 
-    private fun getProjectPath(): String {
-        return FileUtil.toSystemIndependentName(getTestDataRootPath()) + "/moduleClasspath/moduleClasspath.ipr"
-    }
+  private fun getProjectPath(): String {
+    return FileUtil.toSystemIndependentName(getTestDataRootPath()) + "/moduleClasspath/moduleClasspath.ipr"
+  }
 
-    override fun getTestDataRootPath(): String {
-        return FileUtil.toCanonicalPath(PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath(), '/')!!
-    }
+  override fun getTestDataRootPath(): String {
+    return FileUtil.toCanonicalPath(PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath(), '/')!!
+  }
 
-    public fun testSimpleClasspath() {
-        assertClasspath("util", false, listOf("util/lib/exported.jar", "/jdk15.jar"))
-    }
+  public fun testSimpleClasspath() {
+    assertClasspath("util", false, listOf("util/lib/exported.jar", "/jdk15.jar"))
+  }
 
-    public fun testScopes() {
-        assertClasspath("test-util", false, listOf("/jdk.jar", "test-util/lib/provided.jar"))
-        assertClasspath("test-util", true, listOf("/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"))
-    }
+  public fun testScopes() {
+    assertClasspath("test-util", false, listOf("/jdk.jar", "test-util/lib/provided.jar"))
+    assertClasspath("test-util", true, listOf("/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"))
+  }
 
-    public fun testDepModules() {
-        assertClasspath("main", false, listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"))
-        assertClasspath("main", true, listOf("out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", "out/test/test-util", "out/production/test-util", "main/lib/service.jar"))
-    }
+  public fun testDepModules() {
+    assertClasspath("main", false, listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"))
+    assertClasspath("main", true, listOf("out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", "out/test/test-util", "out/production/test-util", "main/lib/service.jar"))
+  }
 
-    public fun testCompilationClasspath() {
-        val chunk = createChunk("main")
-        assertClasspath(listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar"), getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
-        assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
-    }
+  public fun testCompilationClasspath() {
+    val chunk = createChunk("main")
+    assertClasspath(listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar"), getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
+    assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
+  }
 
-    private fun assertClasspath(moduleName: String, includeTests: Boolean, expected: List<String>) {
-        val classpath = getPathsList(ProjectPaths.getCompilationClasspathFiles(createChunk(moduleName), includeTests, true, true))
-        assertClasspath(expected, toSystemIndependentPaths(classpath))
-    }
+  private fun assertClasspath(moduleName: String, includeTests: Boolean, expected: List<String>) {
+    val classpath = getPathsList(ProjectPaths.getCompilationClasspathFiles(createChunk(moduleName), includeTests, true, true))
+    assertClasspath(expected, toSystemIndependentPaths(classpath))
+  }
 
-    private fun createChunk(moduleName: String): ModuleChunk {
-        val module = myProject.getModules().firstOrNull { it.getName() == moduleName }
-        return ModuleChunk(setOf(ModuleBuildTarget(module!!, JavaModuleBuildTargetType.PRODUCTION)))
-    }
+  private fun createChunk(moduleName: String): ModuleChunk {
+    val module = myProject.getModules().first { it.getName() == moduleName }
+    return ModuleChunk(setOf(ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION)))
+  }
 
-    private fun assertClasspath(expected: List<String>, classpath: List<String>) {
-        val basePath = FileUtil.toSystemIndependentName(File(getProjectPath()).getParentFile()!!.getAbsolutePath()) + "/"
-        val actual = toSystemIndependentPaths(classpath).map { StringUtil.trimStart(it, basePath) }
-        Assert.assertEquals(expected.join("\n"), actual.join("\n"))
-    }
+  private fun assertClasspath(expected: List<String>, classpath: List<String>) {
+    val basePath = FileUtil.toSystemIndependentName(File(getProjectPath()).getParentFile()!!.getAbsolutePath()) + "/"
+    val actual = toSystemIndependentPaths(classpath).map { StringUtil.trimStart(it, basePath) }
+    Assert.assertEquals(expected.join("\n"), actual.join("\n"))
+  }
 
-    private fun toSystemIndependentPaths(classpath: List<String>): List<String> {
-        return classpath.map(FileUtil::toSystemIndependentName)
-    }
+  private fun toSystemIndependentPaths(classpath: List<String>): List<String> {
+    return classpath.map(FileUtil::toSystemIndependentName)
+  }
 
-    public fun getPathsList(files: Collection<File>): List<String> {
-        return files.map(::getCanonicalPath)
-    }
+  public fun getPathsList(files: Collection<File>): List<String> {
+    return files.map(::getCanonicalPath)
+  }
 }
 
 private fun getCanonicalPath(file: File): String {
-    val path = file.getPath()
-    return if (path.contains(".")) FileUtil.toCanonicalPath(path)!! else FileUtil.toSystemIndependentName(path)
+  val path = file.getPath()
+  return if (path.contains(".")) FileUtil.toCanonicalPath(path)!! else FileUtil.toSystemIndependentName(path)
 }
 
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt
similarity index 60%
rename from jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy
rename to jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt
index 5f4de62..0a3a49d 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt
@@ -20,14 +20,19 @@
 
 import java.util.jar.Attributes
 import java.util.jar.Manifest
+import java.io.File
+import java.io.FileInputStream
+import kotlin.test.assertTrue
+import kotlin.test.assertEquals
+
 /**
  * @author nik
  */
-class ArtifactRebuildTest extends JpsRebuildTestCase {
-  public void testArtifactIncludesArchiveArtifact() {
-    def name = "artifactIncludesArchiveArtifact"
+class ArtifactRebuildTest: JpsRebuildTestCase() {
+  fun testArtifactIncludesArchiveArtifact() {
+    val name = "artifactIncludesArchiveArtifact"
     try {
-      doTest("$name/${name}.ipr", {
+      doTest("$name/${name}.ipr", fs {
         dir("artifacts") {
           dir("data") {
             archive("a.jar") {
@@ -38,16 +43,16 @@
       })
     }
     finally {
-      FileUtil.delete(new File(FileUtil.toSystemDependentName(getTestDataRootPath() + "/$name/data/a.jar")))
+      FileUtil.delete(File(FileUtil.toSystemDependentName(getTestDataRootPath() + "/$name/data/a.jar")))
     }
   }
 
-  public void testArtifactWithoutOutput() {
-    def outDir = FileUtil.createTempDirectory("output", "").absolutePath
-    loadProject("artifactWithoutOutput/artifactWithoutOutput.ipr", ["OUTPUT_DIR":outDir])
+  fun testArtifactWithoutOutput() {
+    val outDir = FileUtil.createTempDirectory("output", "").getAbsolutePath()
+    loadProject("artifactWithoutOutput/artifactWithoutOutput.ipr", mapOf("OUTPUT_DIR" to outDir))
 
     rebuild()
-    assertOutput(outDir, {
+    assertOutput(outDir, fs {
       dir("artifacts") {
         dir("main") {
           file("data.txt")
@@ -57,8 +62,8 @@
     })
   }
 
-  public void testExtractDir() {
-    doTest("extractDirTest/extractDirTest.ipr", {
+  fun testExtractDir() {
+    doTest("extractDirTest/extractDirTest.ipr", fs {
       dir("artifacts") {
         dir("extractDir") {
           file("b.txt", "b")
@@ -88,20 +93,20 @@
     })
   }
 
-  public void testManifestInArtifact() {
-    loadAndRebuild("manifestInArtifact/manifest.ipr", [:])
-    File jarFile = new File(myOutputDirectory, "artifacts/simple/simple.jar")
-    junit.framework.Assert.assertTrue(jarFile.exists())
-    File extracted = FileUtil.createTempDirectory("build-manifest", "")
+  fun testManifestInArtifact() {
+    loadAndRebuild("manifestInArtifact/manifest.ipr", mapOf())
+    val jarFile = File(myOutputDirectory, "artifacts/simple/simple.jar")
+    assertTrue(jarFile.exists())
+    val extracted = FileUtil.createTempDirectory("build-manifest", "")
     ZipUtil.extract(jarFile, extracted, null)
-    File manifestFile = new File(extracted, "META-INF/MANIFEST.MF")
-    junit.framework.Assert.assertTrue(manifestFile.exists())
-    Manifest manifest = new Manifest(new FileInputStream(manifestFile))
-    junit.framework.Assert.assertEquals("MyClass", manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS))
+    val manifestFile = File(extracted, "META-INF/MANIFEST.MF")
+    assertTrue(manifestFile.exists())
+    val manifest = Manifest(FileInputStream(manifestFile))
+    assertEquals("MyClass", manifest.getMainAttributes()!!.getValue(Attributes.Name.MAIN_CLASS))
   }
 
-  public void testOverwriteArtifacts() {
-    doTest("overwriteTest/overwriteTest.ipr", {
+  fun testOverwriteArtifacts() {
+    doTest("overwriteTest/overwriteTest.ipr", fs {
       dir("artifacts") {
         dir("classes") {
           file("a.xml", "<root2/>")
@@ -128,9 +133,9 @@
     })
   }
 
-  public void testPathVariablesInArtifact() {
-    String externalDir = "${getTestDataRootPath()}/pathVariables/external"
-    doTest("pathVariables/pathVariables.ipr", ["EXTERNAL_DIR": externalDir], {
+  fun testPathVariablesInArtifact() {
+    val externalDir = "${getTestDataRootPath()}/pathVariables/external"
+    doTest("pathVariables/pathVariables.ipr", mapOf("EXTERNAL_DIR" to externalDir), fs {
       dir("artifacts") {
         dir("fileCopy") {
           dir("dir") {
@@ -141,8 +146,8 @@
     })
   }
 
-  public void testModuleTestOutputElement() {
-    doTest("moduleTestOutput/moduleTestOutput.ipr", {
+  fun testModuleTestOutputElement() {
+    doTest("moduleTestOutput/moduleTestOutput.ipr", fs {
       dir("artifacts") {
         dir("tests") {
           file("MyTest.class")
@@ -160,15 +165,4 @@
       }
     })
   }
-
-  //todo[nik] fix
-  public void _testSourceRootUnderOutput() throws Exception {
-    loadProject("sourceFolderUnderOutput/sourceFolderUnderOutput.ipr", [:])
-    try {
-      rebuild()
-      junit.framework.Assert.fail("Cleaning should fail")
-    }
-    catch (Exception ignored) {
-    }
-  }
 }
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
deleted file mode 100644
index 7c10239..0000000
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.jps.builders.rebuild
-import com.intellij.openapi.application.ex.PathManagerEx
-import com.intellij.openapi.util.io.FileUtil
-import com.intellij.util.io.TestFileSystemBuilder
-import org.jetbrains.annotations.NotNull
-import org.jetbrains.jps.util.JpsPathUtil
-import org.jetbrains.jps.builders.JpsBuildTestCase
-import org.jetbrains.jps.model.java.JpsJavaExtensionService
-/**
- * @author nik
- */
-abstract class JpsRebuildTestCase extends JpsBuildTestCase {
-  protected File myOutputDirectory;
-
-  @Override
-  protected void setUp() {
-    super.setUp()
-    addJdk("1.6")
-  }
-
-  def doTest(String projectPath, Closure expectedOutput) {
-    doTest(projectPath, [:], expectedOutput)
-  }
-
-  def doTest(String projectPath, Map<String, String> pathVariables, Closure expectedOutput) {
-    loadAndRebuild(projectPath, pathVariables)
-    assertOutput(getOrCreateOutputDirectory().getAbsolutePath(), expectedOutput);
-  }
-
-  def protected assertOutput(@NotNull String targetFolder, Closure expectedOutput) {
-    def root = TestFileSystemBuilder.fs()
-    initFileSystemItem(root, expectedOutput)
-    root.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(targetFolder)))
-  }
-
-  protected void loadAndRebuild(String projectPath, Map<String, String> pathVariables) {
-    loadProject(projectPath, pathVariables)
-    rebuild()
-  }
-
-  protected void rebuild() {
-    JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath()))
-    rebuildAll()
-  }
-
-  private File getOrCreateOutputDirectory() {
-    if (myOutputDirectory == null) {
-      myOutputDirectory = FileUtil.createTempDirectory("jps-build-output", "")
-    }
-    myOutputDirectory
-  }
-
-  @Override
-  protected void addPathVariables(Map<String, String> pathVariables) {
-    pathVariables.put("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().absolutePath) + "/artifacts")
-  }
-
-  @Override
-  protected String getTestDataRootPath() {
-    return PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output").absolutePath
-  }
-
-  def initFileSystemItem(TestFileSystemBuilder item, Closure initializer) {
-    def meta = new Expando()
-    meta.dir = {String name, Closure content ->
-      initFileSystemItem(item.dir(name), content)
-    }
-    meta.archive = {String name, Closure content ->
-      initFileSystemItem(item.archive(name), content)
-    }
-    meta.file = {Object[] args ->
-      item.file((String)args[0], (String)args.length > 1 ? args[1] : null)
-    }
-
-    initializer.delegate = meta
-    initializer.setResolveStrategy Closure.DELEGATE_FIRST
-    initializer()
-  }
-
-  def File createTempFile() {
-    return FileUtil.createTempFile("jps-build-file", "");
-  }
-}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt
new file mode 100644
index 0000000..dae4cb0
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt
@@ -0,0 +1,86 @@
+package org.jetbrains.jps.builders.rebuild;
+
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.TestFileSystemBuilder;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import kotlin.properties.Delegates
+import com.intellij.util.io.TestFileSystemItem
+
+/**
+ * @author nik
+ */
+public abstract class JpsRebuildTestCase: JpsBuildTestCase() {
+  protected val myOutputDirectory: File by Delegates.lazy {
+    FileUtil.createTempDirectory("jps-build-output", "")
+  }
+
+  override fun setUp() {
+    super.setUp()
+    addJdk("1.6");
+  }
+
+  fun doTest(projectPath: String, expectedOutput: TestFileSystemItem) {
+    doTest(projectPath, LinkedHashMap<String, String>(), expectedOutput);
+  }
+
+  fun doTest(projectPath: String, pathVariables: Map<String, String>, expectedOutput: TestFileSystemItem) {
+    loadAndRebuild(projectPath, pathVariables);
+    assertOutput(myOutputDirectory.getAbsolutePath(), expectedOutput);
+  }
+
+  fun assertOutput(targetFolder: String, expectedOutput: TestFileSystemItem) {
+    expectedOutput.assertDirectoryEqual(File(FileUtil.toSystemDependentName(targetFolder)));
+  }
+
+  fun loadAndRebuild(projectPath: String, pathVariables: Map<String, String>) {
+    loadProject(projectPath, pathVariables);
+    rebuild();
+  }
+
+  fun rebuild() {
+    JpsJavaExtensionService.getInstance()!!.getOrCreateProjectExtension(myProject)
+      .setOutputUrl(JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(myOutputDirectory.getAbsolutePath())));
+    rebuildAll();
+  }
+
+  override fun getAdditionalPathVariables(): MutableMap<String, String> =
+    hashMapOf("ARTIFACTS_OUT" to FileUtil.toSystemIndependentName(myOutputDirectory.getAbsolutePath()) + "/artifacts")
+
+  protected override fun getTestDataRootPath(): String {
+    return PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath();
+  }
+}
+
+fun fs(init: TestFileSystemBuilderBuilder.() -> Unit): TestFileSystemItem {
+  val builder = TestFileSystemBuilder.fs()
+  TestFileSystemBuilderBuilder(builder).init()
+  return builder.build()
+}
+
+class TestFileSystemBuilderBuilder(private val current: TestFileSystemBuilder) {
+  fun file(name: String) {
+    current.file(name)
+  }
+
+  fun file(name: String, content: String) {
+    current.file(name, content)
+  }
+
+  fun dir(name: String, init: TestFileSystemBuilderBuilder.() -> Unit) {
+    val dir = current.dir(name)
+    TestFileSystemBuilderBuilder(dir).init()
+    dir.end()
+  }
+
+  fun archive(name: String, init: TestFileSystemBuilderBuilder.() -> Unit) {
+    val dir = current.archive(name)
+    TestFileSystemBuilderBuilder(dir).init()
+    dir.end()
+  }
+}
\ No newline at end of file
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt
similarity index 85%
rename from jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy
rename to jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt
index 36e03eb..09e72b7 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt
@@ -17,9 +17,9 @@
 /**
  * @author nik
  */
-public class ModuleRebuildTest extends JpsRebuildTestCase {
-  public void testModuleCycle() {
-    doTest("moduleCycle/moduleCycle.ipr", {
+public class ModuleRebuildTest: JpsRebuildTestCase() {
+  fun testModuleCycle() {
+    doTest("moduleCycle/moduleCycle.ipr", fs {
         dir("production") {
           dir("module1") {
             file("Bar1.class")
@@ -34,8 +34,8 @@
     })
   }
 
-  public void testOverlappingSourceRoots() {
-    doTest("overlappingSourceRoots/overlappingSourceRoots.ipr", {
+  fun testOverlappingSourceRoots() {
+    doTest("overlappingSourceRoots/overlappingSourceRoots.ipr", fs {
         dir("production") {
           dir("inner") {
             dir("y") {
@@ -52,8 +52,8 @@
     })
   }
 
-  public void testResourceCopying() {
-    doTest("resourceCopying/resourceCopying.ipr", {
+  fun testResourceCopying() {
+    doTest("resourceCopying/resourceCopying.ipr", fs {
       dir("production") {
         dir("resourceCopying") {
           dir("copy") {
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
index 6214412..cf87eb5 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
@@ -16,16 +16,19 @@
 package org.jetbrains.jps.model.serialization;
 
 import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ObjectUtils;
 import com.intellij.util.SystemProperties;
-import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
 import java.util.Map;
 
+import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
+
 /**
  * @author nik
  */
@@ -34,9 +37,16 @@
   @NonNls public static final String MODULE_DIR_MACRO_NAME = "MODULE_DIR";
   @NonNls public static final String DIRECTORY_STORE_NAME = ".idea";
   @NonNls public static final String APPLICATION_HOME_DIR = "APPLICATION_HOME_DIR";
+  @NonNls public static final String APPLICATION_CONFIG_DIR = "APPLICATION_CONFIG_DIR";
   @NonNls public static final String APPLICATION_PLUGINS_DIR = "APPLICATION_PLUGINS_DIR";
   @NonNls public static final String USER_HOME_NAME = "USER_HOME";
 
+  private static final Map<String, String> ourGlobalMacros = ContainerUtil.<String, String>immutableMapBuilder()
+    .put(APPLICATION_HOME_DIR, toSystemIndependentName(PathManager.getHomePath()))
+    .put(APPLICATION_CONFIG_DIR, toSystemIndependentName(PathManager.getConfigPath()))
+    .put(APPLICATION_PLUGINS_DIR, toSystemIndependentName(PathManager.getPluginsPath()))
+    .put(USER_HOME_NAME, StringUtil.trimEnd(toSystemIndependentName(SystemProperties.getUserHome()), "/")).build();
+
   @Nullable
   public static String getModuleDir(String moduleFilePath) {
     File moduleDirFile = new File(moduleFilePath).getParentFile();
@@ -57,31 +67,18 @@
     return moduleDir;
   }
 
+  @NotNull
   public static String getUserHomePath() {
-    return StringUtil.trimEnd(FileUtil.toSystemIndependentName(SystemProperties.getUserHome()), "/");
+    return ObjectUtils.assertNotNull(getGlobalSystemMacroValue(USER_HOME_NAME));
   }
 
+  @NotNull
   public static Map<String, String> getGlobalSystemMacros() {
-    final Map<String, String> map = new HashMap<String, String>();
-    map.put(APPLICATION_HOME_DIR, getApplicationHomeDirPath());
-    map.put(APPLICATION_PLUGINS_DIR, getApplicationPluginsDirPath());
-    map.put(USER_HOME_NAME, getUserHomePath());
-    return map;
-  }
-
-  private static String getApplicationHomeDirPath() {
-    return FileUtil.toSystemIndependentName(PathManager.getHomePath());
-  }
-
-  private static String getApplicationPluginsDirPath() {
-    return FileUtil.toSystemIndependentName(PathManager.getPluginsPath());
+    return ourGlobalMacros;
   }
 
   @Nullable
   public static String getGlobalSystemMacroValue(String name) {
-    if (APPLICATION_HOME_DIR.equals(name)) return getApplicationHomeDirPath();
-    if (APPLICATION_PLUGINS_DIR.equals(name)) return getApplicationPluginsDirPath();
-    if (USER_HOME_NAME.equals(name)) return getUserHomePath();
-    return null;
+    return ourGlobalMacros.get(name);
   }
 }
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
deleted file mode 100644
index d7e52c6..0000000
--- a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-package org.jetbrains.jps.idea
-
-/**
- * @author max
- */
-public class IdeaProjectLoader {
-  public static String guessHome(Script script) {
-    String uri = script["gant.file"]
-    File home = new File(new URI(uri).getSchemeSpecificPart())
-
-    while (home != null) {
-      if (home.isDirectory() && new File(home, ".idea").exists()) {
-        return home.getCanonicalPath()
-      }
-
-      home = home.getParentFile()
-    }
-
-    throw new IllegalArgumentException("Cannot guess project home from '" + uri + "'")
-  }
-}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java
new file mode 100644
index 0000000..b392dcf
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java
@@ -0,0 +1,30 @@
+package org.jetbrains.jps.idea;
+
+import groovy.lang.Script;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author max
+ */
+public class IdeaProjectLoader {
+  public static String guessHome(Script script) throws IOException, URISyntaxException {
+    String uri = (String)script.getProperty("gant.file");
+    File home = new File(new URI(uri).getSchemeSpecificPart());
+
+    while (home != null) {
+      if (home.isDirectory() && new File(home, ".idea").exists()) {
+        return home.getCanonicalPath();
+      }
+
+
+      home = home.getParentFile();
+    }
+
+
+    throw new IllegalArgumentException("Cannot guess project home from '" + uri + "'");
+  }
+}
diff --git a/native/runner/runnerw/.gitignore b/native/runner/runnerw/.gitignore
index 998f2dd..560bd1a 100644
--- a/native/runner/runnerw/.gitignore
+++ b/native/runner/runnerw/.gitignore
@@ -1,5 +1,6 @@
 *.aps
 *.vcxproj.user
+Debug
 Release
 *.suo
 *.opensdf
diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp
index 8936b28..03e975e 100644
--- a/native/runner/runnerw/runnerw.cpp
+++ b/native/runner/runnerw/runnerw.cpp
@@ -18,16 +18,25 @@
 	exit(0);
 }
 
-void ErrorMessage(char *str) {
-
+void ErrorMessage(char *operationName) {
 	LPVOID msg;
-
-	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-			NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-			(LPTSTR) &msg, 0, NULL);
-
-	printf("%s: %s\n", str, msg);
-	LocalFree(msg);
+	DWORD lastError = GetLastError();
+	FormatMessage(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		lastError,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&msg,
+		0,
+		NULL);
+	if (msg) {
+		fprintf(stderr, "%s failed with error %d: %s\n", operationName, lastError, msg);
+		LocalFree(msg);
+	}
+	else {
+		fprintf(stderr, "%s failed with error %d (no message available)\n", operationName, lastError);
+	}
+	fflush(stderr);
 }
 
 void CtrlBreak() {
@@ -126,6 +135,33 @@
 	}
 }
 
+BOOL attachChildConsole(PROCESS_INFORMATION const &childProcessInfo) {
+	if (!FreeConsole()) {
+		ErrorMessage("FreeConsole");
+		return FALSE;
+	}
+	int attempts = 20;
+	for (int i = 0; i < attempts; i++) {
+		DWORD sleepMillis = i < 5 ? 30 : (i < 10 ? 100 : 500);
+		// sleep to let child process initialize itself
+		Sleep(sleepMillis);
+		if (WaitForSingleObject(childProcessInfo.hProcess, 0) != WAIT_TIMEOUT) {
+			// child process has been terminated, no console to attach to
+			return FALSE;
+		}
+		if (AttachConsole(childProcessInfo.dwProcessId)) {
+			return TRUE;
+		}
+		// ERROR_GEN_FAILURE means "the specified process does not exist"
+		// Seems it also means that the console hasn't been fully initialized.
+		if (GetLastError() != ERROR_GEN_FAILURE) {
+			break;
+		}
+	}
+	ErrorMessage("AttachConsole");
+	return FALSE;
+}
+
 int main(int argc, char * argv[]) {
 	if (argc < 2) {
 		PrintUsage();
@@ -195,18 +231,34 @@
 	char* c_args = new char[args.size() + 1];
 	strcpy(c_args, args.c_str());
 
-	if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
-		ErrorMessage("SetConsoleCtrlHandler");
+	DWORD processFlag = CREATE_DEFAULT_ERROR_MODE;
+	BOOL hasConsoleWindow = GetConsoleWindow() != NULL;
+	if (hasConsoleWindow) {
+		processFlag |= CREATE_NO_WINDOW;
 	}
 
-	if (!CreateProcess(c_app, // Application name
-			c_args, // Application arguments
-			NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi)) {
+	if (!CreateProcess(
+			c_app,
+			c_args,
+			NULL,
+			NULL,
+			TRUE,
+			processFlag,
+			NULL,
+			NULL,
+			&si,
+			&pi)) {
 		ErrorMessage("CreateProcess");
 		CloseHandle(newstdin);
 		CloseHandle(write_stdin);
 		exit(0);
 	}
+	if (hasConsoleWindow) {
+		attachChildConsole(pi);
+	}
+	if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) {
+		ErrorMessage("SetConsoleCtrlHandler");
+	}
 
 	CreateThread(NULL, 0, &scanStdinThread, &write_stdin, 0, NULL);
 
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
index 3a75f17..81e3406 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
@@ -42,6 +42,7 @@
   private boolean myEnabled;
   private HighlightDisplayLevel myLevel;
 
+  private boolean myAdditionalConfigPanelCreated = false;
   private JComponent myAdditionalConfigPanel;
   private static final Logger LOG = Logger.getInstance("#" + ScopeToolState.class.getName());
 
@@ -98,13 +99,11 @@
     myLevel = level;
   }
 
-  @NotNull
+  @Nullable
   public JComponent getAdditionalConfigPanel() {
-    if (myAdditionalConfigPanel == null) {
+    if (!myAdditionalConfigPanelCreated) {
       myAdditionalConfigPanel = myToolWrapper.getTool().createOptionsPanel();
-      if (myAdditionalConfigPanel == null){
-        myAdditionalConfigPanel = new JPanel();
-      }
+      myAdditionalConfigPanelCreated = true;
     }
     return myAdditionalConfigPanel;
   }
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
index 6f0a3c2..b463526 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
@@ -47,6 +47,7 @@
    *
    * @return the analysis scope.
    */
+  @Nullable
   public abstract AnalysisScope getScope();
 
   /**
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
index 0c32f60..5e23b22 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
@@ -43,15 +43,7 @@
 
     @Override
     public void setOption(final String optionName, boolean optionValue) {
-      try {
-        ReflectionUtil.findField(myInspection.getClass(), boolean.class, optionName).setBoolean(myInspection, optionValue);
-      }
-      catch (IllegalAccessException e) {
-        LOG.warn(e);
-      }
-      catch (NoSuchFieldException e) {
-        LOG.warn(e);
-      }
+      ReflectionUtil.setField(myInspection.getClass(), myInspection, boolean.class, optionName, optionValue);
     }
   }
 }
diff --git a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
index c4580e0..cc72d47 100644
--- a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
+++ b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
@@ -40,6 +40,7 @@
   public abstract boolean isProblemFile(VirtualFile virtualFile);
 
   public abstract void weHaveGotProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems);
+  public abstract void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems);
   public abstract void clearProblems(@NotNull VirtualFile virtualFile);
 
   public abstract boolean hasProblemFilesBeneath(@NotNull Condition<VirtualFile> condition);
diff --git a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
index 647cd72..76db4a7 100644
--- a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
+++ b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
@@ -189,10 +189,10 @@
     private final VirtualFile myDirectory;
     private final boolean myWithSubdirectories;
 
-    private DirectoryScope(@NotNull PsiDirectory directory, final boolean withSubdirectories) {
-      super(directory.getProject());
+    private DirectoryScope(@NotNull PsiDirectory psiDirectory, final boolean withSubdirectories) {
+      super(psiDirectory.getProject());
       myWithSubdirectories = withSubdirectories;
-      myDirectory = directory.getVirtualFile();
+      myDirectory = psiDirectory.getVirtualFile();
     }
 
     private DirectoryScope(@NotNull Project project, @NotNull VirtualFile directory, final boolean withSubdirectories) {
@@ -221,6 +221,7 @@
       return false;
     }
 
+    @Override
     public String toString() {
       //noinspection HardCodedStringLiteral
       return "directory scope: " + myDirectory + "; withSubdirs:"+myWithSubdirectories;
@@ -296,6 +297,7 @@
       return false;
     }
 
+    @Override
     public String toString() {
       //noinspection HardCodedStringLiteral
       return "Directories scope: " + Arrays.asList(myDirectories);
diff --git a/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java b/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
index d6e4101..d00655a 100644
--- a/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
+++ b/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
@@ -16,14 +16,13 @@
 package com.intellij.util.ui;
 
 import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.util.ReflectionUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.ButtonModel;
-import javax.swing.JCheckBox;
+import javax.swing.*;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
-import java.lang.reflect.Field;
 
 public class CheckBox extends JCheckBox {
 
@@ -39,31 +38,9 @@
 
     private static boolean getPropertyValue(InspectionProfileEntry owner,
                                             String property) {
-        try {
-            final Class<? extends InspectionProfileEntry> aClass = owner.getClass();
-            final Field field = getField(aClass, property);
-            field.setAccessible(true);
-            return field.getBoolean(owner);
-        } catch (IllegalAccessException ignore) {
-            return false;
-        } catch (NoSuchFieldException ignore) {
-            return false;
-        }
+      return ReflectionUtil.getField(owner.getClass(), owner, boolean.class, property);
     }
 
-  static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
-    try {
-      return clazz.getDeclaredField(fieldName);
-    } catch (NoSuchFieldException e) {
-      final Class superClass = clazz.getSuperclass();
-      if (superClass == null) {
-        throw e;
-      } else {
-        return getField(superClass, fieldName);
-      }
-    }
-  }
-
     private static class SingleCheckboxChangeListener
             implements ChangeListener {
 
@@ -85,16 +62,7 @@
         private static void setPropertyValue(InspectionProfileEntry owner,
                                              String property,
                                              boolean selected) {
-            try {
-                final Class<? extends InspectionProfileEntry> aClass = owner.getClass();
-                final Field field = getField(aClass, property);
-                field.setAccessible(true);
-                field.setBoolean(owner, selected);
-            } catch (IllegalAccessException ignore) {
-                // do nothing
-            } catch (NoSuchFieldException ignore) {
-                // do nothing
-            }
+          ReflectionUtil.setField(owner.getClass(), owner, boolean.class, property, selected);
         }
     }
 }
\ No newline at end of file
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
index d8dc5d0..0a1861e 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
@@ -39,9 +39,13 @@
 import com.intellij.profile.codeInspection.SeverityProvider;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.util.ArrayUtil;
 import com.intellij.util.Consumer;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.graph.CachingSemiGraph;
+import com.intellij.util.graph.DFSTBuilder;
+import com.intellij.util.graph.GraphGenerator;
 import gnu.trove.THashMap;
 import org.jdom.Document;
 import org.jdom.Element;
@@ -85,7 +89,7 @@
   private final ExternalInfo myExternalInfo = new ExternalInfo();
   @TestOnly
   public static boolean INIT_INSPECTIONS = false;
-  private List<NamedScope> myScopes = Collections.emptyList();
+  private String[] myScopesOrder = null;
 
   @Override
   public void setModified(final boolean modified) {
@@ -509,6 +513,7 @@
     catch (ProcessCanceledException e) {
       return false;
     }
+    final Map<String, List<String>> dependencies = new HashMap<String, List<String>>();
     for (InspectionToolWrapper toolWrapper : tools) {
       final String shortName = toolWrapper.getShortName();
       HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
@@ -536,7 +541,7 @@
       final Element element = myDeinstalledInspectionsSettings.remove(toolWrapper.getShortName());
       if (element != null) {
         try {
-          toolsList.readExternal(element, this);
+          toolsList.readExternal(element, this, dependencies);
         }
         catch (InvalidDataException e) {
           LOG.error("Can't read settings for " + toolWrapper, e);
@@ -544,12 +549,39 @@
       }
       myTools.put(toolWrapper.getShortName(), toolsList);
     }
+    final GraphGenerator<String> graphGenerator = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
+      @Override
+      public Collection<String> getNodes() {
+        return dependencies.keySet();
+      }
+
+      @Override
+      public Iterator<String> getIn(String n) {
+        return dependencies.get(n).iterator();
+      }
+    }));
+
+    DFSTBuilder<String> builder = new DFSTBuilder<String>(graphGenerator);
+    if (builder.isAcyclic()) {
+      final List<String> scopes = builder.getSortedNodes();
+      myScopesOrder = ArrayUtil.toStringArray(scopes);
+    }
+
     if (mySource != null) {
       copyToolsConfigurations(mySource, project);
     }
     return true;
   }
 
+  @Nullable
+  public String[] getScopesOrder() {
+    return myScopesOrder;
+  }
+
+  public void setScopesOrder(String[] scopesOrder) {
+    myScopesOrder = scopesOrder;
+  }
+
   @NotNull
   private List<InspectionToolWrapper> createTools(Project project) {
     if (mySource != null) {
@@ -907,13 +939,13 @@
     return getTools(toolWrapper.getShortName(), project).prependTool(scope, toolWrapper, enabled, level);
   }
 
-  public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, int scopeIdx, Project project) {
-    getTools(key.toString(), project).setLevel(level, scopeIdx, project);
+  public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
+    getTools(key.toString(), project).setLevel(level, scopeName, project);
   }
 
-  public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, int scopeIdx, Project project) {
+  public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
     for (HighlightDisplayKey key : keys) {
-      getTools(key.toString(), project).setLevel(level, scopeIdx, project);
+      setErrorLevel(key, level, scopeName, project);
     }
   }
 
@@ -944,10 +976,4 @@
     return super.equals(o) && ((InspectionProfileImpl)o).getProfileManager() == getProfileManager();
   }
 
-  /**
-   * @return list of used scopes for all inspections
-   */
-  public List<NamedScope> getUsedScopes() {
-    return myScopes;
-  }
 }
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
index b28dad4..267c0ee 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
@@ -46,6 +46,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 public class ToolsImpl implements Tools {
   @NonNls private static final String ENABLED_BY_DEFAULT_ATTRIBUTE = "enabled_by_default";
@@ -170,7 +171,7 @@
     }
   }
 
-  void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile) throws InvalidDataException {
+  void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile, Map<String, List<String>> dependencies) throws InvalidDataException {
     final String levelName = toolElement.getAttributeValue(LEVEL_ATTRIBUTE);
     final ProfileManager profileManager = profile.getProfileManager();
     final SeverityRegistrar registrar = ((SeverityProvider)profileManager).getOwnSeverityRegistrar();
@@ -187,6 +188,7 @@
     final InspectionToolWrapper toolWrapper = myDefaultState.getTool();
 
     final List scopeElements = toolElement.getChildren(ProfileEx.SCOPE);
+    final List<String> scopeNames = new ArrayList<String>();
     for (Object sO : scopeElements) {
       final Element scopeElement = (Element)sO;
       final String scopeName = scopeElement.getAttributeValue(ProfileEx.NAME);
@@ -216,6 +218,20 @@
       else {
         addTool(scopeName, copyToolWrapper, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel);
       }
+
+      scopeNames.add(scopeName);
+    }
+
+    for (int i = 0; i < scopeNames.size(); i++) {
+      String scopeName = scopeNames.get(i);
+      List<String> order = dependencies.get(scopeName);
+      if (order == null) {
+        order = new ArrayList<String>();
+        dependencies.put(scopeName, order);
+      }
+      for (int j = i + 1; j < scopeNames.size(); j++) {
+        order.add(scopeNames.get(j));
+      }
     }
 
     // check if unknown children exists
@@ -445,22 +461,36 @@
 
   }
 
-  public void setLevel(@NotNull HighlightDisplayLevel level, int idx, Project project) {
-    if (myTools != null && myTools.size() > idx && idx >= 0) {
-      final ScopeToolState scopeToolState = myTools.get(idx);
-      myTools.remove(idx);
+  public void setLevel(@NotNull HighlightDisplayLevel level, @Nullable String scopeName, Project project) {
+    if (scopeName == null) {
+      myDefaultState.setLevel(level);
+    } else {
+      if (myTools == null) {
+        return;
+      }
+      ScopeToolState scopeToolState = null;
+      int index = -1;
+      for (int i = 0; i < myTools.size(); i++) {
+        ScopeToolState tool = myTools.get(i);
+        if (scopeName.equals(tool.getScopeName())) {
+          scopeToolState = tool;
+          myTools.remove(tool);
+          index = i;
+          break;
+        }
+      }
+      if (index < 0) {
+        throw new IllegalStateException("Scope " + scopeName + " not found");
+      }
+      final InspectionToolWrapper toolWrapper = scopeToolState.getTool();
       final NamedScope scope = scopeToolState.getScope(project);
-      InspectionToolWrapper toolWrapper = scopeToolState.getTool();
       if (scope != null) {
-        myTools.add(idx, new ScopeToolState(scope, toolWrapper, scopeToolState.isEnabled(), level));
+        myTools.add(index, new ScopeToolState(scope, toolWrapper, scopeToolState.isEnabled(), level));
       }
       else {
-        myTools.add(idx, new ScopeToolState(scopeToolState.getScopeName(), toolWrapper, scopeToolState.isEnabled(), level));
+        myTools.add(index, new ScopeToolState(scopeToolState.getScopeName(), toolWrapper, scopeToolState.isEnabled(), level));
       }
     }
-    else if (idx == -1) {
-      myDefaultState.setLevel(level);
-    }
   }
 
   public void setDefaultState(@NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
index 0fbd048..f31e44e 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
@@ -149,6 +149,7 @@
     }
   }
 
+  @Nullable
   @Override
   public AnalysisScope getScope() {
     return myScope;
@@ -304,7 +305,9 @@
     if (!myDeclarationsFound) {
       long before = System.currentTimeMillis();
       final AnalysisScope scope = getScope();
-      scope.accept(myProjectIterator);
+      if (scope != null) {
+        scope.accept(myProjectIterator);
+      }
       myDeclarationsFound = true;
 
       LOG.info("Total duration of processing project usages:" + (System.currentTimeMillis() - before));
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java b/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
index 0afe259..ba9125f 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
 import com.intellij.codeInspection.InspectionProfileEntry;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.ui.DocumentAdapter;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -28,7 +29,6 @@
 import javax.swing.text.Document;
 import javax.swing.text.InternationalFormatter;
 import java.awt.*;
-import java.lang.reflect.Field;
 import java.text.NumberFormat;
 import java.util.regex.Pattern;
 
@@ -150,58 +150,18 @@
   }
 
   private static void setPropertyIntegerValue(InspectionProfileEntry owner, String property, Integer value) {
-    try {
-      final Field field = getField(owner.getClass(), property);
-      field.setAccessible(true);
-      field.setInt(owner, value.intValue());
-    } catch (Exception e) {
-      LOG.error(e);
-    }
+    setPropertyValue(owner, property, value);
   }
 
   private static Integer getPropertyIntegerValue(InspectionProfileEntry owner, String property) {
-    try {
-      final Field field = getField(owner.getClass(), property);
-      field.setAccessible(true);
-      return Integer.valueOf(field.getInt(owner));
-    } catch (Exception e) {
-      LOG.error(e);
-      return 0;
-    }
+    return (Integer)getPropertyValue(owner, property);
   }
 
-  private static void setPropertyValue(InspectionProfileEntry owner, String property, Object value) {
-    try {
-      final Field field = getField(owner.getClass(), property);
-      field.setAccessible(true);
-      field.set(owner, value);
-    } catch (Exception e) {
-      LOG.error(e);
-    }
+  private static void setPropertyValue(@NotNull InspectionProfileEntry owner, String property, Object value) {
+    ReflectionUtil.setField(owner.getClass(), owner, null, property, value);
   }
 
   private static Object getPropertyValue(InspectionProfileEntry owner, String property) {
-    try {
-      final Field field = getField(owner.getClass(), property);
-      field.setAccessible(true);
-      return field.get(owner);
-    }
-    catch (Exception e) {
-      LOG.error(e);
-      return null;
-    }
-  }
-
-  private static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
-    try {
-      return clazz.getDeclaredField(fieldName);
-    } catch (NoSuchFieldException e) {
-      Class superClass = clazz.getSuperclass();
-      if (superClass == null) {
-        throw e;
-      } else {
-        return getField(superClass, fieldName);
-      }
-    }
+    return ReflectionUtil.getField(owner.getClass(), owner, null, property);
   }
 }
diff --git a/platform/core-api/src/com/intellij/ide/caches/FileContent.java b/platform/core-api/src/com/intellij/ide/caches/FileContent.java
index 0933b7f..c4c6d61 100644
--- a/platform/core-api/src/com/intellij/ide/caches/FileContent.java
+++ b/platform/core-api/src/com/intellij/ide/caches/FileContent.java
@@ -47,7 +47,7 @@
   @NotNull
   public byte[] getBytes() throws IOException {
     if (myCachedBytes == null) {
-      myCachedBytes = myVirtualFile.contentsToByteArray(false);
+      myCachedBytes = myVirtualFile.isValid() ? myVirtualFile.contentsToByteArray(false) : ArrayUtil.EMPTY_BYTE_ARRAY;
     }
 
     return myCachedBytes;
diff --git a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
index f3b883d..f733cd0 100644
--- a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
+++ b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
@@ -17,8 +17,10 @@
 
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.util.ObjectUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.lang.reflect.Field;
 
@@ -31,6 +33,7 @@
 
   public abstract boolean isValueSet(String name);
 
+  @Nullable
   public abstract String getValue(@NonNls String name);
 
   public abstract void setValue(@NonNls String name, String value);
@@ -62,7 +65,10 @@
 
   @NotNull
   public String getValue(@NonNls String name, @NotNull String defaultValue) {
-    return isValueSet(name) ? getValue(name) : defaultValue;
+    if (!isValueSet(name)) {
+      return defaultValue;
+    }
+    return ObjectUtils.notNull(getValue(name), defaultValue);
   }
 
   public final int getOrInitInt(@NonNls String name, int defaultValue) {
diff --git a/platform/core-api/src/com/intellij/lexer/DelegateLexer.java b/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
index ce8bbbc..102256b 100644
--- a/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
+++ b/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
@@ -26,7 +26,7 @@
 public class DelegateLexer extends LexerBase {
   protected final Lexer myDelegate;
 
-  public DelegateLexer(Lexer delegate) {
+  public DelegateLexer(@NotNull Lexer delegate) {
     myDelegate = delegate;
   }
 
diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
index a319700..e99b8e6 100644
--- a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
+++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
@@ -79,7 +79,7 @@
     }
   }
 
-  public static void progress(final String text) throws ProcessCanceledException {
+  public static void progress(@NotNull String text) throws ProcessCanceledException {
     progress(text, "");
   }
 
@@ -91,7 +91,7 @@
     }
   }
 
-  public static void progress(final String text, @Nullable String text2) throws ProcessCanceledException {
+  public static void progress(@NotNull String text, @Nullable String text2) throws ProcessCanceledException {
     final ProgressIndicator pi = getInstance().getProgressIndicator();
     if (pi != null) {
       pi.checkCanceled();
@@ -103,6 +103,7 @@
   protected abstract void doCheckCanceled() throws ProcessCanceledException;
 
   public abstract void executeNonCancelableSection(@NotNull Runnable runnable);
+  @NotNull
   public abstract NonCancelableSection startNonCancelableSection();
 
   public abstract void setCancelButtonText(String cancelButtonText);
@@ -135,9 +136,9 @@
    * @throws E exception thrown by process
    */
   public abstract <T, E extends Exception> T runProcessWithProgressSynchronously(@NotNull ThrowableComputable<T, E> process,
-                                                              @NotNull @Nls String progressTitle,
-                                                              boolean canBeCanceled,
-                                                              @Nullable Project project) throws E;
+                                                                                 @NotNull @Nls String progressTitle,
+                                                                                 boolean canBeCanceled,
+                                                                                 @Nullable Project project) throws E;
 
   /**
    * Runs the specified operation in a background thread and shows a modal progress dialog in the
@@ -206,7 +207,10 @@
   public abstract void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator progressIndicator);
 
   protected static final ThreadLocal<ProgressIndicator> myThreadIndicator = new ThreadLocal<ProgressIndicator>();
-  public void executeProcessUnderProgress(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException {
+
+  public void executeProcessUnderProgress(@NotNull Runnable process,
+                                          @Nullable("null means reuse current progress") ProgressIndicator progress)
+    throws ProcessCanceledException {
     ProgressIndicator oldIndicator = null;
 
     boolean set = progress != null && progress != (oldIndicator = myThreadIndicator.get());
diff --git a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
index cc7dddd..96dde81 100644
--- a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
+++ b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
@@ -45,6 +45,7 @@
 
   public abstract boolean isInLibrarySource(@NotNull VirtualFile file);
   public abstract boolean isExcludedFile(@NotNull VirtualFile file);
+  public abstract boolean isUnderIgnored(@NotNull VirtualFile file);
 
   @Nullable
   public abstract Module getModuleForFile(@NotNull VirtualFile file);
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java b/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
index c363a81..f8ddc76 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
@@ -22,7 +22,7 @@
 import java.util.Enumeration;
 import java.util.zip.ZipFile;
 
-/** @deprecated causes ZipFile leaks, do not use (to be removed in IDEA 15) */
+/** @deprecated causes ZipFile leaks, do not use (to be removed in IDEA 15) + can lead to crashes (IDEA-126550) */
 public interface JarFile {
   interface JarEntry {
     String getName();
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
index cd0f15f..9e8c378 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
@@ -84,6 +84,20 @@
     return false;
   }
 
+  /**
+   * @return {@code true} if {@code url} is located under one of {@code rootUrls} or equal to one of them
+   */
+  public static boolean isUnder(@NotNull String url, @Nullable Collection<String> rootUrls) {
+    if (rootUrls == null || rootUrls.isEmpty()) return false;
+
+    for (String excludesUrl : rootUrls) {
+      if (isEqualOrAncestor(excludesUrl, url)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   public static boolean isEqualOrAncestor(@NotNull String ancestorUrl, @NotNull String fileUrl) {
     if (ancestorUrl.equals(fileUrl)) return true;
     if (StringUtil.endsWithChar(ancestorUrl, '/')) {
diff --git a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
index fb2ae2c..f24556f 100644
--- a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
+++ b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
@@ -164,7 +164,7 @@
   }
 
   public static boolean isTrackingInvalidation() {
-    return Registry.is("psi.track.invalidation", true);
+    return Registry.is("psi.track.invalidation");
   }
 
   @Nullable
diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
index 7f04b19..633c25a 100644
--- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
@@ -68,10 +68,8 @@
 
 import java.lang.reflect.Modifier;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 /**
  * @author yole
@@ -210,12 +208,12 @@
             }
 
             @Override
-            public Object get() throws InterruptedException, ExecutionException {
+            public Object get() {
               return null;
             }
 
             @Override
-            public Object get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            public Object get(long timeout, @NotNull TimeUnit unit) {
               return null;
             }
           });
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
deleted file mode 100644
index a6b957c..0000000
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.plugins;
-
-import com.intellij.openapi.extensions.PluginId;
-import com.intellij.util.containers.HashMap;
-import gnu.trove.TObjectIntHashMap;
-
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Stack;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Aug 3, 2004
- */
-public class PluginDescriptorComparator implements Comparator<IdeaPluginDescriptor>{
-  private final TObjectIntHashMap<PluginId> myIdToNumberMap = new TObjectIntHashMap<PluginId>();
-  private int myAvailableNumber = 1;
-
-  public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors){
-    final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>();
-    for (final IdeaPluginDescriptor descriptor : descriptors) {
-      idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
-    }
-    myIdToNumberMap.put(PluginId.getId(PluginManagerCore.CORE_PLUGIN_ID), 0);
-
-    final Stack<PluginId> visited = new Stack<PluginId>();
-    for (int idx = 0; idx < descriptors.length && myIdToNumberMap.size() != descriptors.length; idx++) {
-      assignNumbers(descriptors[idx].getPluginId(), idToDescriptorMap, visited);
-      visited.clear();
-    }
-  }
-
-  private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited){
-    visited.push(id);
-    try {
-      final IdeaPluginDescriptor ideaPluginDescriptor = idToDescriptorMap.get(id);
-      if (ideaPluginDescriptor == null || !ideaPluginDescriptor.isEnabled()) {
-        // missing optional dependency or already disabled due to cycles
-        return;
-      }
-      final PluginId[] parentIds = ideaPluginDescriptor.getDependentPluginIds();
-      for (final PluginId parentId : parentIds) {
-        if (visited.contains(parentId)) {
-          //disable plugins in the cycle 
-          ideaPluginDescriptor.setEnabled(false);
-          break;
-        }
-      }
-      for (PluginId parentId1 : parentIds) {
-        assignNumbers(parentId1, idToDescriptorMap, visited);
-      }
-      if (!myIdToNumberMap.contains(id)) {
-        myIdToNumberMap.put(id, myAvailableNumber++);
-      }
-    }
-    finally {
-      visited.pop();
-    }
-  }
-
-  public int compare(IdeaPluginDescriptor d1, IdeaPluginDescriptor d2) {
-    return myIdToNumberMap.get(d1.getPluginId()) - myIdToNumberMap.get(d2.getPluginId());
-  }
-}
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
index 8f4fd77..e834e33 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
@@ -30,10 +30,7 @@
 import com.intellij.openapi.util.io.StreamUtil;
 import com.intellij.openapi.util.io.ZipFileCache;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.PlatformUtilsCore;
-import com.intellij.util.ReflectionUtil;
+import com.intellij.util.*;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.MultiMap;
 import com.intellij.util.execution.ParametersListUtil;
@@ -43,6 +40,7 @@
 import com.intellij.util.graph.GraphGenerator;
 import com.intellij.util.xmlb.XmlSerializationException;
 import gnu.trove.THashMap;
+import gnu.trove.TIntProcedure;
 import org.jdom.Document;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -498,26 +496,38 @@
     }
   }
 
-  @Deprecated
-  static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+  static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
     final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
     final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
-    /*
     if (!builder.isAcyclic()) {
-      final Pair<String,String> circularDependency = builder.getCircularDependency();
-      throw new Exception("Cyclic dependencies between plugins are not allowed: \"" + circularDependency.getFirst() + "\" and \"" + circularDependency.getSecond() + "");
+      builder.getSCCs().forEach(new TIntProcedure() {
+        int myTNumber = 0;
+        public boolean execute(int size) {
+          if (size > 1) {
+            for (int j = 0; j < size; j++) {
+              idToDescriptorMap.get(builder.getNodeByTNumber(myTNumber + j)).setEnabled(false);
+            }
+          }
+          myTNumber += size;
+          return true;
+        }
+      });
     }
-    */
+
     final Comparator<PluginId> idComparator = builder.comparator();
     return new Comparator<IdeaPluginDescriptor>() {
       @Override
       public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) {
-        return idComparator.compare(o1.getPluginId(), o2.getPluginId());
+        final PluginId pluginId1 = o1.getPluginId();
+        final PluginId pluginId2 = o2.getPluginId();
+        if (pluginId1.getIdString().equals(CORE_PLUGIN_ID)) return -1;
+        if (pluginId2.getIdString().equals(CORE_PLUGIN_ID)) return 1;
+        return idComparator.compare(pluginId1, pluginId2);
       }
     };
   }
 
-  private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+  private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
     final List<PluginId> ids = new ArrayList<PluginId>(idToDescriptorMap.keySet());
     // this magic ensures that the dependent plugins always follow their dependencies in lexicographic order
     // needed to make sure that extensions are always in the same order
@@ -539,7 +549,7 @@
         ArrayList<PluginId> plugins = new ArrayList<PluginId>();
         for (PluginId dependentPluginId : descriptor.getDependentPluginIds()) {
           // check for missing optional dependency
-          IdeaPluginDescriptorImpl dep = idToDescriptorMap.get(dependentPluginId);
+          IdeaPluginDescriptor dep = idToDescriptorMap.get(dependentPluginId);
           if (dep != null) {
             plugins.add(dep.getPluginId());
           }
@@ -901,7 +911,12 @@
     loadDescriptorsFromClassPath(result, fromSources ? progress : null);
 
     IdeaPluginDescriptorImpl[] pluginDescriptors = result.toArray(new IdeaPluginDescriptorImpl[result.size()]);
-    Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors));
+    final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap = new com.intellij.util.containers.HashMap<PluginId, IdeaPluginDescriptorImpl>();
+    for (final IdeaPluginDescriptorImpl descriptor : pluginDescriptors) {
+      idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
+    }
+
+    Arrays.sort(pluginDescriptors, getPluginDescriptorComparator(idToDescriptorMap));
     return pluginDescriptors;
   }
 
@@ -1110,13 +1125,35 @@
     final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
     final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
     if (!builder.isAcyclic()) {
-      final Couple<PluginId> circularDependency = builder.getCircularDependency();
-      final PluginId id = circularDependency.getFirst();
-      final PluginId parentId = circularDependency.getSecond();
       if (!StringUtil.isEmptyOrSpaces(errorMessage)) {
         errorMessage += "<br>";
       }
-      errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id;
+
+      final String cyclePresentation;
+      if (ApplicationManager.getApplication().isInternal()) {
+        final List<String> cycles = new ArrayList<String>();
+        builder.getSCCs().forEach(new TIntProcedure() {
+          int myTNumber = 0;
+          public boolean execute(int size) {
+            if (size > 1) {
+              String cycle = "";
+              for (int j = 0; j < size; j++) {
+                cycle += builder.getNodeByTNumber(myTNumber + j).getIdString() + " ";
+              }
+              cycles.add(cycle);
+            }
+            myTNumber += size;
+            return true;
+          }
+        });
+        cyclePresentation = ": " + StringUtil.join(cycles, ";");
+      } else {
+        final Couple<PluginId> circularDependency = builder.getCircularDependency();
+        final PluginId id = circularDependency.getFirst();
+        final PluginId parentId = circularDependency.getSecond();
+        cyclePresentation = id + "->" + parentId + "->...->" + id;
+      }
+      errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + cyclePresentation;
     }
 
     prepareLoadingPluginsErrorMessage(errorMessage);
diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
index 3338241..b68fa93 100644
--- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
+++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
@@ -1152,64 +1152,66 @@
   }
 
   private void balanceWhiteSpaces() {
-    RelativeTokenTypesView wsTokens = null;
-    RelativeTokenTextView tokenTextGetter = null;
+    RelativeTokenTypesView wsTokens = new RelativeTokenTypesView();
+    RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView();
+    int lastIndex = 0;
 
     for (int i = 1, size = myProduction.size() - 1; i < size; i++) {
-      final ProductionMarker item = myProduction.get(i);
-
+      ProductionMarker item = myProduction.get(i);
       if (item instanceof StartMarker && ((StartMarker)item).myDoneMarker == null) {
         LOG.error(UNBALANCED_MESSAGE);
       }
 
-      final int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
-      int idx = item.myLexemeIndex;
-      while (idx > prevProductionLexIndex && whitespaceOrComment(myLexTypes[idx - 1])) idx--;
-      final int wsStartIndex = idx;
-
+      int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
+      int wsStartIndex = Math.max(item.myLexemeIndex, lastIndex);
+      while (wsStartIndex > prevProductionLexIndex && whitespaceOrComment(myLexTypes[wsStartIndex - 1])) wsStartIndex--;
       int wsEndIndex = item.myLexemeIndex;
       while (wsEndIndex < myLexemeCount && whitespaceOrComment(myLexTypes[wsEndIndex])) wsEndIndex++;
 
-      if (wsTokens == null) wsTokens = new RelativeTokenTypesView();
-      wsTokens.configure(wsStartIndex, wsEndIndex);
-      final boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
-      if (tokenTextGetter == null) tokenTextGetter = new RelativeTokenTextView();
-      tokenTextGetter.configure(wsStartIndex);
+      if (wsStartIndex != wsEndIndex) {
+        wsTokens.configure(wsStartIndex, wsEndIndex);
+        tokenTextGetter.configure(wsStartIndex);
+        boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
+        item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+      }
+      else if (item.myLexemeIndex < wsStartIndex) {
+        item.myLexemeIndex = wsStartIndex;
+      }
 
-      item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+      lastIndex = item.myLexemeIndex;
     }
   }
 
   private final class RelativeTokenTypesView extends AbstractList<IElementType> {
-    private int start;
-    private int size;
+    private int myStart;
+    private int mySize;
 
-    private void configure(int _start, int _end) {
-      size = _end - _start;
-      start = _start;
+    private void configure(int start, int end) {
+      myStart = start;
+      mySize = end - start;
     }
 
     @Override
-    public IElementType get(final int index) {
-      return myLexTypes[start + index];
+    public IElementType get(int index) {
+      return myLexTypes[myStart + index];
     }
 
     @Override
     public int size() {
-      return size;
+      return mySize;
     }
   }
 
   private final class RelativeTokenTextView implements WhitespacesAndCommentsBinder.TokenTextGetter {
-    private int start;
+    private int myStart;
 
-    private void configure(int _start) {
-      start = _start;
+    private void configure(int start) {
+      myStart = start;
     }
 
     @Override
-    public CharSequence get(final int i) {
-      return myText.subSequence(myLexStarts[start + i], myLexStarts[start + i + 1]);
+    public CharSequence get(int i) {
+      return myText.subSequence(myLexStarts[myStart + i], myLexStarts[myStart + i + 1]);
     }
   }
 
diff --git a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
index dd6d73f..6df23d8 100644
--- a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
+++ b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
@@ -74,6 +74,11 @@
   }
 
   @Override
+  public boolean isUnderIgnored(@NotNull VirtualFile file) {
+    return false;
+  }
+
+  @Override
   public Module getModuleForFile(@NotNull VirtualFile file) {
     return myModule;
   }
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
index fa234e1..918ebaa 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
@@ -75,6 +75,9 @@
 
   private final List<EditReadOnlyListener> myReadOnlyListeners = ContainerUtil.createLockFreeCopyOnWriteList();
 
+  private volatile boolean myMightContainTabs = true; // optimisation flag: when document contains no tabs it is dramatically easier to calculate positions in editor
+  private int myTabTrackingRequestors = 0;
+
   private int myCheckGuardedBlocks = 0;
   private boolean myGuardsSuppressed = false;
   private boolean myEventsHandling = false;
@@ -171,14 +174,14 @@
   /**
    * @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret being in the way
    *
-   * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, java.util.List)}
+   * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, int[])}
    * once multicaret logic will become unconditional (not controlled by configuration flag)
    */
-  public boolean stripTrailingSpaces(@Nullable final Project project,
-                                     boolean inChangedLinesOnly,
-                                     boolean virtualSpaceEnabled,
-                                     int caretLine,
-                                     int caretOffset) {
+  boolean stripTrailingSpaces(@Nullable final Project project,
+                              boolean inChangedLinesOnly,
+                              boolean virtualSpaceEnabled,
+                              int caretLine,
+                              int caretOffset) {
     if (!isStripTrailingSpacesEnabled) {
       return true;
     }
@@ -230,24 +233,24 @@
   /**
    * @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret(s) being in the way
    */
-  public boolean stripTrailingSpaces(@Nullable final Project project,
-                                     boolean inChangedLinesOnly,
-                                     boolean virtualSpaceEnabled,
-                                     @NotNull List<Integer> caretOffsets) {
+  boolean stripTrailingSpaces(@Nullable final Project project,
+                              boolean inChangedLinesOnly,
+                              boolean virtualSpaceEnabled,
+                              @NotNull int[] caretOffsets) {
     if (!isStripTrailingSpacesEnabled) {
       return true;
     }
 
     boolean markAsNeedsStrippingLater = false;
     CharSequence text = myText;
-    TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.size());
+    TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.length);
     try {
       if (!virtualSpaceEnabled) {
-        for (Integer caretOffset : caretOffsets) {
-          if (caretOffset == null || caretOffset < 0 || caretOffset > getTextLength()) {
+        for (int caretOffset : caretOffsets) {
+          if (caretOffset < 0 || caretOffset > getTextLength()) {
             continue;
           }
-          Integer line = getLineNumber(caretOffset);
+          int line = getLineNumber(caretOffset);
           List<RangeMarker> markers = caretMarkers.get(line);
           if (markers == null) {
             markers = new ArrayList<RangeMarker>();
@@ -763,6 +766,9 @@
       if (LOG.isDebugEnabled()) LOG.debug(event.toString());
 
       getLineSet().changedUpdate(event);
+      if (myTabTrackingRequestors > 0) {
+        updateMightContainTabs(event.getNewFragment());
+      }
       setModificationStamp(newModificationStamp);
 
       if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -1051,4 +1057,29 @@
   public String toString() {
     return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + "]";
   }
+
+  public void requestTabTracking() {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    if (myTabTrackingRequestors++ == 0) {
+      myMightContainTabs = false;
+      updateMightContainTabs(myText);
+    }
+  }
+
+  public void giveUpTabTracking() {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    if (--myTabTrackingRequestors == 0) {
+      myMightContainTabs = true;
+    }
+  }
+
+  public boolean mightContainTabs() {
+    return myMightContainTabs;
+  }
+
+  private void updateMightContainTabs(CharSequence text) {
+    if (!myMightContainTabs) {
+      myMightContainTabs = StringUtil.contains(text, 0, text.length(), '\t');
+    }
+  }
 }
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
index 975add0..5ce1e2c 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
@@ -123,7 +123,7 @@
       }
     });
     if (alive.get() > DUPLICATE_LIMIT) {
-      return "Too many range markers (" + alive + ") registered in "+this+"\n";
+      return "Too many range markers (" + alive + ") registered for interval "+node+"\n";
     }
 
     return null;
diff --git a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
index ba5858c..2ca35e4 100644
--- a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
+++ b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
@@ -301,15 +301,30 @@
     final PsiToDocumentSynchronizer synchronizer = manager.getSynchronizer();
     final PsiElement changeScope = transaction.getChangeScope();
     LOG.assertTrue(changeScope != null);
-    BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
-    final PsiFile containingFileByTree = getContainingFileByTree(changeScope);
 
+    final PsiFile containingFileByTree = getContainingFileByTree(changeScope);
+    if (changeScope.isPhysical() && synchronizer.toProcessPsiEvent() && isDocumentUncommitted(containingFileByTree)) {
+      // fail-fast to prevent any psi modifications that would cause psi/document text mismatch
+      // PsiToDocumentSynchronizer assertions happen inside event processing and are logged by PsiManagerImpl.fireEvent instead of being rethrown
+      // so it's important to throw something outside event processing
+      throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
+    }
+
+    BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
     Document document = containingFileByTree == null ? null : manager.getCachedDocument(containingFileByTree);
     if(document != null) {
       synchronizer.startTransaction(myProject, document, changeScope);
     }
   }
 
+  private boolean isDocumentUncommitted(@Nullable PsiFile file) {
+    if (file == null) return false;
+
+    PsiDocumentManager manager = PsiDocumentManager.getInstance(myProject);
+    Document cachedDocument = manager.getCachedDocument(file);
+    return cachedDocument != null && manager.isUncommited(cachedDocument);
+  }
+
   @Nullable
   private static PsiFile getContainingFileByTree(@NotNull final PsiElement changeScope) {
     // there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
index 3583af2..8a8f722 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -699,7 +699,7 @@
     }
 
     // we can end up outside write action here if the document has forUseInNonAWTThread=true
-    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+    ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() {
       @Override
       public void run() {
         psiFile.getViewProvider().beforeContentsSynchronized();
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
index 7611dd1..13c4357 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
@@ -74,10 +74,8 @@
     final PsiFile psiFile = event.getFile();
     if (psiFile == null || psiFile.getNode() == null) return;
 
-    final Document document = getCachedDocument(psiFile, force);
-    if (document == null) return;
-
-    if (myPsiDocumentManager.isUncommited(document)) {
+    final Document document = myPsiDocumentManager.getCachedDocument(psiFile);
+    if (document != null && myPsiDocumentManager.isUncommited(document)) {
       throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
     }
   }
@@ -207,7 +205,7 @@
     return myIgnorePsiEvents;
   }
 
-  private boolean toProcessPsiEvent() {
+  public boolean toProcessPsiEvent() {
     return !myIgnorePsiEvents && !ApplicationManager.getApplication().hasWriteAction(IgnorePsiEventsMarker.class);
   }
 
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
index d411380..386fb2d 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
@@ -39,8 +39,7 @@
  * User: cdr
  */
 public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
-  public DiffLog() {
-  }
+  public DiffLog() { }
 
   private abstract static class LogEntry {
     protected LogEntry() {
@@ -58,7 +57,6 @@
       entry.doActualPsiChange(file, astDiffBuilder);
     }
     file.subtreeChanged();
-
     return astDiffBuilder.getEvent();
   }
 
@@ -83,7 +81,6 @@
   @Override
   public void nodeDeleted(@NotNull ASTNode oldParent, @NotNull ASTNode oldNode) {
     myEntries.add(new DeleteEntry(oldParent, oldNode));
-
   }
 
   @Override
@@ -126,14 +123,12 @@
 
       astDiffBuilder.nodeReplaced(oldNode, newNode);
 
-      /////////////////
       ((TreeElement)newNode).clearCaches();
       if (!(newNode instanceof FileElement)) {
         ((CompositeElement)newNode.getTreeParent()).subtreeChanged();
       }
 
       DebugUtil.checkTreeStructure(parent);
-
     }
   }
 
@@ -168,7 +163,6 @@
       ((CompositeElement)parent).subtreeChanged();
 
       DebugUtil.checkTreeStructure(parent);
-
     }
   }
 
@@ -222,7 +216,6 @@
 
       DebugUtil.checkTreeStructure(myOldParent);
     }
-
   }
 
   private static PsiElement getPsi(ASTNode node, PsiFile file) {
diff --git a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
index 115b91a..f21c241 100644
--- a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
@@ -26,7 +26,7 @@
 public class ProjectScopeImpl extends GlobalSearchScope {
   private final FileIndexFacade myFileIndex;
 
-  public ProjectScopeImpl(Project project, FileIndexFacade fileIndex) {
+  public ProjectScopeImpl(@NotNull Project project, @NotNull FileIndexFacade fileIndex) {
     super(project);
     myFileIndex = fileIndex;
   }
@@ -61,6 +61,7 @@
     return PsiBundle.message("psi.search.scope.project");
   }
 
+  @Override
   public String toString() {
     return getDisplayName();
   }
diff --git a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
index c94921b..581352c 100644
--- a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
+++ b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
@@ -66,7 +66,7 @@
 
   // maximal tree depth for which incremental reparse is allowed
   // if tree is deeper then it will be replaced completely - to avoid SOEs
-  public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit", 1000);
+  public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit");
 
   public static final Key<Boolean> TREE_DEPTH_LIMIT_EXCEEDED = Key.create("TREE_IS_TOO_DEEP");
 
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java b/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
index 3650b99..c12cf4f 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.dvcs.repo;
 
+import com.intellij.openapi.Disposable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
@@ -49,7 +50,7 @@
  *
  * @author Nadya Zabrodina
  */
-public interface Repository {
+public interface Repository extends Disposable {
 
 
   /**
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
index a7de8f9..5a605c5 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
@@ -25,7 +25,7 @@
 /**
  * @author Nadya Zabrodina
  */
-public abstract class RepositoryImpl implements Repository, Disposable {
+public abstract class RepositoryImpl implements Repository {
 
   @NotNull private final Project myProject;
   @NotNull private final VirtualFile myRootDir;
@@ -82,7 +82,6 @@
   public void dispose() {
   }
 
-
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
index fa2e9a8..5a5a555 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtil;
@@ -29,7 +30,10 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 import java.util.concurrent.Callable;
 
 /**
@@ -117,7 +121,9 @@
 
     @Override
     public void consume(Object dummy) {
-      myRepository.update();
+      if (!Disposer.isDisposed(myRepository)) {
+        myRepository.update();
+      }
     }
   }
 
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java
new file mode 100644
index 0000000..bb7f64f
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLog;
+import com.intellij.vcs.log.VcsLogDataKeys;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAction {
+
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    Project project = e.getRequiredData(CommonDataKeys.PROJECT);
+    VcsLog log = e.getRequiredData(VcsLogDataKeys.VSC_LOG);
+    List<VcsFullCommitDetails> details = log.getSelectedDetails();
+    MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
+    assert grouped != null;
+    actionPerformed(project, grouped);
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    Project project = e.getProject();
+    VcsLog log = e.getData(VcsLogDataKeys.VSC_LOG);
+    if (project == null || log == null) {
+      e.getPresentation().setEnabledAndVisible(false);
+      return;
+    }
+
+    List<VcsFullCommitDetails> details = log.getSelectedDetails();
+    MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
+    if (grouped == null) {
+      e.getPresentation().setEnabledAndVisible(false);
+    }
+    else {
+      e.getPresentation().setVisible(true);
+      e.getPresentation().setEnabled(!grouped.isEmpty() && isEnabled(grouped));
+    }
+  }
+
+  protected abstract void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
+
+  protected abstract boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
+
+  @Nullable
+  protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root);
+
+  @Nullable
+  private MultiMap<Repo, VcsFullCommitDetails> groupByRootWithCheck(@NotNull Project project, @NotNull List<VcsFullCommitDetails> commits) {
+    MultiMap<Repo, VcsFullCommitDetails> map = MultiMap.create();
+    for (VcsFullCommitDetails commit : commits) {
+      Repo root = getRepositoryForRoot(project, commit.getRoot());
+      if (root == null) { // commit from some other VCS
+        return null;
+      }
+      map.putValue(root, commit);
+    }
+    return map;
+  }
+
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
new file mode 100644
index 0000000..1b4be91
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+
+public abstract class VcsLogOneCommitPerRepoAction<Repo extends Repository> extends VcsLogAction<Repo> {
+
+  @Override
+  protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+    Map<Repo, VcsFullCommitDetails> singleElementMap = convertToSingleElementMap(grouped);
+    assert singleElementMap != null;
+    actionPerformed(project, singleElementMap);
+  }
+
+  @Override
+  protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+    return allValuesAreSingletons(grouped);
+  }
+
+  protected abstract void actionPerformed(@NotNull Project project, @NotNull Map<Repo, VcsFullCommitDetails> commits);
+
+  private boolean allValuesAreSingletons(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+    return !ContainerUtil.exists(grouped.entrySet(), new Condition<Map.Entry<Repo, Collection<VcsFullCommitDetails>>>() {
+      @Override
+      public boolean value(Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry) {
+        return entry.getValue().size() != 1;
+      }
+    });
+  }
+
+  @Nullable
+  private Map<Repo, VcsFullCommitDetails> convertToSingleElementMap(@NotNull MultiMap<Repo, VcsFullCommitDetails> groupedCommits) {
+    Map<Repo, VcsFullCommitDetails> map = ContainerUtil.newHashMap();
+    for (Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry : groupedCommits.entrySet()) {
+      Collection<VcsFullCommitDetails> commits = entry.getValue();
+      if (commits.size() != 1) {
+        return null;
+      }
+      map.put(entry.getKey(), commits.iterator().next());
+    }
+    return map;
+  }
+
+
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
new file mode 100644
index 0000000..4b43380
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Map;
+
+public abstract class VcsLogSingleCommitAction<Repo extends Repository> extends VcsLogAction<Repo> {
+
+  @Override
+  protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+    return grouped.size() == 1;
+  }
+
+  @Override
+  protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+    assert grouped.size() == 1;
+    Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry = grouped.entrySet().iterator().next();
+    Repo repository = entry.getKey();
+    Collection<VcsFullCommitDetails> commits = entry.getValue();
+    assert commits.size() == 1;
+    actionPerformed(repository, commits.iterator().next());
+  }
+
+  protected abstract void actionPerformed(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit);
+
+}
diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
index cb0e1a2..e6b2553 100644
--- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
+++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
@@ -72,6 +72,7 @@
   public int RECENT_FILES_LIMIT = 50;
   public int CONSOLE_COMMAND_HISTORY_LIMIT = 300;
   public int EDITOR_TAB_LIMIT = 10;
+  public int EDITOR_TAB_TITLE_LIMIT = 100;
   public boolean ANIMATE_WINDOWS = true;
   public int ANIMATION_SPEED = 2000; // Pixels per second
   public boolean SHOW_TOOL_WINDOW_NUMBERS = true;
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
similarity index 61%
rename from platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
rename to platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
index 2add3ed..a966d83 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
@@ -15,23 +15,12 @@
  */
 package com.intellij.psi.impl.search;
 
-import com.intellij.lexer.Lexer;
 import com.intellij.lexer.LexerBase;
-import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
 import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.editor.impl.EditorHighlighterCache;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.util.text.CharSequenceSubSequence;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
 * @author Sergey Evdokimov
@@ -49,31 +38,6 @@
     myAlreadyInitializedHighlighter = alreadyInitializedHighlighter;
   }
 
-  @Nullable
-  public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
-    EditorHighlighter highlighter = null;
-
-    PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
-    final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
-    final EditorHighlighter cachedEditorHighlighter;
-    boolean alreadyInitializedHighlighter = false;
-
-    if (document != null &&
-        (cachedEditorHighlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document)) != null &&
-        PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
-      highlighter = cachedEditorHighlighter;
-      alreadyInitializedHighlighter = true;
-    }
-    else if (virtualFile != null) {
-      highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
-    }
-
-    if (highlighter != null) {
-      return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
-    }
-    return null;
-  }
-
   @Override
   public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int state) {
     if (myAlreadyInitializedHighlighter) {
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
index 4efac18..10fc11a 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
@@ -69,6 +69,18 @@
   }
 
   @NotNull
+  public <T> DataNode<T> createOrReplaceChild(@NotNull Key<T> key, @NotNull T data) {
+    for (Iterator<DataNode<?>> iterator = myChildren.iterator(); iterator.hasNext(); ) {
+      DataNode<?> child = iterator.next();
+      if (child.getKey().equals(key)) {
+        iterator.remove();
+        break;
+      }
+    }
+    return createChild(key, data);
+  }
+
+  @NotNull
   public Key<T> getKey() {
     return myKey;
   }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java
new file mode 100644
index 0000000..6bc9cf9
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+public class DefaultExternalFilter implements ExternalFilter {
+  private static final long serialVersionUID = 1L;
+
+  @NotNull
+  private String myFilterType;
+  @NotNull
+  private String myPropertiesAsJsonMap;
+
+  public DefaultExternalFilter() {
+    myPropertiesAsJsonMap = "";
+    myFilterType = "";
+  }
+
+
+  public DefaultExternalFilter(ExternalFilter filter) {
+    myPropertiesAsJsonMap = filter.getPropertiesAsJsonMap();
+    myFilterType = filter.getFilterType();
+  }
+
+  @NotNull
+  @Override
+  public String getFilterType() {
+    return myFilterType;
+  }
+
+  public void setFilterType(@NotNull String filterType) {
+    myFilterType = filterType;
+  }
+
+  @Override
+  @NotNull
+  public String getPropertiesAsJsonMap() {
+    return myPropertiesAsJsonMap;
+  }
+
+  public void setPropertiesAsJsonMap(@NotNull String propertiesAsJsonMap) {
+    myPropertiesAsJsonMap = propertiesAsJsonMap;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java
new file mode 100644
index 0000000..8b7991b
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/16/2014
+ */
+public class DefaultExternalPlugin implements ExternalPlugin {
+  private static final long serialVersionUID = 1L;
+
+  @NotNull
+  private String myId;
+
+  public DefaultExternalPlugin() {
+  }
+
+  public DefaultExternalPlugin(ExternalPlugin plugin) {
+    myId = plugin.getId();
+  }
+
+  @NotNull
+  @Override
+  public String getId() {
+    return myId;
+  }
+
+  public void setId(@NotNull String id) {
+    myId = id;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java
new file mode 100644
index 0000000..cecb9ad
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalProject implements ExternalProject {
+
+  private static final long serialVersionUID = 1L;
+
+  @NotNull
+  private String myName;
+  @NotNull
+  private String myQName;
+  @Nullable
+  private String myDescription;
+  @NotNull
+  private String myGroup;
+  @NotNull
+  private String myVersion;
+  @NotNull
+  private Map<String, ExternalProject> myChildProjects;
+  @NotNull
+  private File myProjectDir;
+  @NotNull
+  private File myBuildDir;
+  @Nullable
+  private File myBuildFile;
+  @NotNull
+  private Map<String, ExternalTask> myTasks;
+  @NotNull
+  private Map<String, ?> myProperties;
+  @NotNull
+  private Map<String, ExternalSourceSet> mySourceSets;
+  @NotNull
+  private String myExternalSystemId;
+  @NotNull
+  private Map<String, ExternalPlugin> myPlugins;
+
+  public DefaultExternalProject() {
+    myChildProjects = new HashMap<String, ExternalProject>();
+    myTasks = new HashMap<String, ExternalTask>();
+    myProperties = new HashMap<String, Object>();
+    mySourceSets = new HashMap<String, ExternalSourceSet>();
+    myPlugins = new HashMap<String, ExternalPlugin>();
+  }
+
+  public DefaultExternalProject(@NotNull ExternalProject externalProject) {
+    this();
+    myName = externalProject.getName();
+    myQName = externalProject.getQName();
+    myVersion = externalProject.getVersion();
+    myGroup = externalProject.getGroup();
+    myDescription = externalProject.getDescription();
+    myProjectDir = externalProject.getProjectDir();
+    myBuildDir = externalProject.getBuildDir();
+    myBuildFile = externalProject.getBuildFile();
+    myExternalSystemId = externalProject.getExternalSystemId();
+
+    for (Map.Entry<String, ExternalProject> entry : externalProject.getChildProjects().entrySet()) {
+      myChildProjects.put(entry.getKey(), new DefaultExternalProject(entry.getValue()));
+    }
+
+    for (Map.Entry<String, ExternalTask> entry : externalProject.getTasks().entrySet()) {
+      myTasks.put(entry.getKey(), new DefaultExternalTask(entry.getValue()));
+    }
+    for (Map.Entry<String, ExternalSourceSet> entry : externalProject.getSourceSets().entrySet()) {
+      mySourceSets.put(entry.getKey(), new DefaultExternalSourceSet(entry.getValue()));
+    }
+    for (Map.Entry<String, ExternalPlugin> entry : externalProject.getPlugins().entrySet()) {
+      myPlugins.put(entry.getKey(), new DefaultExternalPlugin(entry.getValue()));
+    }
+  }
+
+
+  @NotNull
+  @Override
+  public String getExternalSystemId() {
+    return myExternalSystemId;
+  }
+
+  public void setExternalSystemId(@NotNull String externalSystemId) {
+    myExternalSystemId = externalSystemId;
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return myName;
+  }
+
+  public void setName(@NotNull String name) {
+    myName = name;
+  }
+
+  @NotNull
+  @Override
+  public String getQName() {
+    return myQName;
+  }
+
+  public void setQName(@NotNull String QName) {
+    myQName = QName;
+  }
+
+  @Nullable
+  @Override
+  public String getDescription() {
+    return myDescription;
+  }
+
+  public void setDescription(@Nullable String description) {
+    myDescription = description;
+  }
+
+  @NotNull
+  @Override
+  public String getGroup() {
+    return myGroup;
+  }
+
+  public void setGroup(@NotNull String group) {
+    myGroup = group;
+  }
+
+  @NotNull
+  @Override
+  public String getVersion() {
+    return myVersion;
+  }
+
+  public void setVersion(@NotNull String version) {
+    myVersion = version;
+  }
+
+  @NotNull
+  @Override
+  public Map<String, ExternalProject> getChildProjects() {
+    return myChildProjects;
+  }
+
+  public void setChildProjects(@NotNull Map<String, ExternalProject> childProjects) {
+    myChildProjects = childProjects;
+  }
+
+  @NotNull
+  @Override
+  public File getProjectDir() {
+    return myProjectDir;
+  }
+
+  public void setProjectDir(@NotNull File projectDir) {
+    myProjectDir = projectDir;
+  }
+
+  @NotNull
+  @Override
+  public File getBuildDir() {
+    return myBuildDir;
+  }
+
+  public void setBuildDir(@NotNull File buildDir) {
+    myBuildDir = buildDir;
+  }
+
+  @Nullable
+  @Override
+  public File getBuildFile() {
+    return myBuildFile;
+  }
+
+  public void setBuildFile(@Nullable File buildFile) {
+    myBuildFile = buildFile;
+  }
+
+  @NotNull
+  @Override
+  public Map<String, ExternalTask> getTasks() {
+    return myTasks;
+  }
+
+  public void setTasks(@NotNull Map<String, ExternalTask> tasks) {
+    myTasks = tasks;
+  }
+
+  @NotNull
+  @Override
+  public Map<String, ExternalPlugin> getPlugins() {
+    return myPlugins;
+  }
+
+  public void setPlugins(@NotNull Map<String, ExternalPlugin> plugins) {
+    myPlugins = plugins;
+  }
+
+  @NotNull
+  @Override
+  public Map<String, ?> getProperties() {
+    return myProperties;
+  }
+
+  public void setProperties(@NotNull Map<String, ?> properties) {
+    myProperties = properties;
+  }
+
+  @Nullable
+  @Override
+  public Object getProperty(String name) {
+    return myProperties.get(name);
+  }
+
+  @NotNull
+  @Override
+  public Map<String, ExternalSourceSet> getSourceSets() {
+    return mySourceSets;
+  }
+
+  public void setSourceSets(@NotNull Map<String, ExternalSourceSet> sourceSets) {
+    mySourceSets = sourceSets;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java
new file mode 100644
index 0000000..d6a8d7a
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalSourceDirectorySet implements ExternalSourceDirectorySet {
+  private static final long serialVersionUID = 1L;
+
+  @NotNull
+  private String myName;
+  @NotNull
+  private Set<File> mySrcDirs;
+  @NotNull
+  private File myOutputDir;
+  @NotNull
+  private Set<String> myExcludes;
+  @NotNull
+  private Set<String> myIncludes;
+  @NotNull
+  private List<ExternalFilter> myFilters;
+
+  public DefaultExternalSourceDirectorySet() {
+    mySrcDirs = new HashSet<File>();
+    myExcludes = new HashSet<String>();
+    myIncludes = new HashSet<String>();
+    myFilters = new ArrayList<ExternalFilter>();
+  }
+
+  public DefaultExternalSourceDirectorySet(ExternalSourceDirectorySet sourceDirectorySet) {
+    this();
+    myName = sourceDirectorySet.getName();
+    mySrcDirs = new HashSet<File>(sourceDirectorySet.getSrcDirs());
+    myOutputDir = sourceDirectorySet.getOutputDir();
+    myExcludes = new HashSet<String>(sourceDirectorySet.getExcludes());
+    myIncludes = new HashSet<String>(sourceDirectorySet.getIncludes());
+    for (ExternalFilter filter : sourceDirectorySet.getFilters()) {
+      myFilters.add(new DefaultExternalFilter(filter));
+    }
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return myName;
+  }
+
+  public void setName(@NotNull String name) {
+    myName = name;
+  }
+
+  @NotNull
+  @Override
+  public Set<File> getSrcDirs() {
+    return mySrcDirs;
+  }
+
+  public void setSrcDirs(@NotNull Set<File> srcDirs) {
+    mySrcDirs = srcDirs;
+  }
+
+  @NotNull
+  @Override
+  public File getOutputDir() {
+    return myOutputDir;
+  }
+
+  @NotNull
+  @Override
+  public Set<String> getIncludes() {
+    return myIncludes;
+  }
+
+  public void setIncludes(@NotNull Set<String> includes) {
+    myIncludes = includes;
+  }
+
+  @NotNull
+  @Override
+  public Set<String> getExcludes() {
+    return myExcludes;
+  }
+
+  public void setExcludes(@NotNull Set<String> excludes) {
+    myExcludes = excludes;
+  }
+
+  @NotNull
+  @Override
+  public List<ExternalFilter> getFilters() {
+    return myFilters;
+  }
+
+  public void setFilters(@NotNull List<ExternalFilter> filters) {
+    myFilters = filters;
+  }
+
+  public void setOutputDir(@NotNull File outputDir) {
+    myOutputDir = outputDir;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java
new file mode 100644
index 0000000..19d692d
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.model.project.IExternalSystemSourceType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalSourceSet implements ExternalSourceSet {
+  private static final long serialVersionUID = 1L;
+
+  private String myName;
+  private Map<IExternalSystemSourceType, ExternalSourceDirectorySet> mySources;
+
+  public DefaultExternalSourceSet() {
+    mySources = new HashMap<IExternalSystemSourceType, ExternalSourceDirectorySet>();
+  }
+
+  public DefaultExternalSourceSet(ExternalSourceSet sourceSet) {
+    this();
+    myName = sourceSet.getName();
+    for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> entry : sourceSet.getSources().entrySet()) {
+      mySources.put(ExternalSystemSourceType.from(entry.getKey()), new DefaultExternalSourceDirectorySet(entry.getValue()));
+    }
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return myName;
+  }
+
+  public void setName(String name) {
+    myName = name;
+  }
+
+  @NotNull
+  @Override
+  public Map<IExternalSystemSourceType, ExternalSourceDirectorySet> getSources() {
+    return mySources;
+  }
+
+  public void setSources(Map<IExternalSystemSourceType, ExternalSourceDirectorySet> sources) {
+    mySources = sources;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java
new file mode 100644
index 0000000..e9392eb
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalTask implements ExternalTask {
+  private static final long serialVersionUID = 1L;
+
+  @NotNull
+  private String myName;
+  @NotNull
+  private String myQName;
+  @Nullable
+  private String myDescription;
+  @Nullable
+  private String myGroup;
+
+  public DefaultExternalTask() {
+  }
+
+  public DefaultExternalTask(ExternalTask externalTask) {
+    myName = externalTask.getName();
+    myQName = externalTask.getQName();
+    myDescription = externalTask.getDescription();
+    myGroup = externalTask.getGroup();
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return myName;
+  }
+
+  public void setName(@NotNull String name) {
+    myName = name;
+  }
+
+  @NotNull
+  @Override
+  public String getQName() {
+    return myQName;
+  }
+
+  public void setQName(@NotNull String QName) {
+    myQName = QName;
+  }
+
+  @Nullable
+  @Override
+  public String getDescription() {
+    return myDescription;
+  }
+
+  public void setDescription(@Nullable String description) {
+    myDescription = description;
+  }
+
+  @Nullable
+  @Override
+  public String getGroup() {
+    return myGroup;
+  }
+
+  public void setGroup(@Nullable String group) {
+    myGroup = group;
+  }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java
new file mode 100644
index 0000000..98fc003
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalFilter extends Serializable {
+  @NotNull
+  String getFilterType();
+  @NotNull
+  String getPropertiesAsJsonMap();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java
new file mode 100644
index 0000000..edd3db7
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalPlugin extends Serializable {
+  @NotNull
+  String getId();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java
new file mode 100644
index 0000000..6df2d41
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalProject extends Serializable {
+
+  @NotNull
+  String getExternalSystemId();
+
+  @NotNull
+  String getName();
+
+  @NotNull
+  String getQName();
+
+  @Nullable
+  String getDescription();
+
+  @NotNull
+  String getGroup();
+
+  @NotNull
+  String getVersion();
+
+  @NotNull
+  Map<String, ExternalProject> getChildProjects();
+
+  @NotNull
+  File getProjectDir();
+
+  @NotNull
+  File getBuildDir();
+
+  @Nullable
+  File getBuildFile();
+
+  @NotNull
+  Map<String, ExternalTask> getTasks();
+
+  //@NotNull
+  //Map<String, ExternalConfiguration> getConfigurations();
+
+  //@NotNull
+  //List<ExternalRepository> getRepositories();
+
+  //@NotNull
+  //List<ExternalDependency> getDependencies();
+
+  @NotNull
+  Map<String, ExternalPlugin> getPlugins();
+
+  //@NotNull
+  //ExternalProjectBuild getBuild();
+
+  @NotNull
+  Map<String, ?> getProperties();
+
+  @Nullable
+  Object getProperty(String name);
+
+  @NotNull
+  Map<String, ExternalSourceSet> getSourceSets();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java
new file mode 100644
index 0000000..70f0bed
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalSourceDirectorySet extends Serializable {
+  @NotNull
+  String getName();
+
+  @NotNull
+  Set<File> getSrcDirs();
+
+  @NotNull
+  File getOutputDir();
+
+  @NotNull
+  Set<String> getExcludes();
+  @NotNull
+  Set<String> getIncludes();
+
+  @NotNull
+  List<ExternalFilter> getFilters();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java
new file mode 100644
index 0000000..b23c07b
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import com.intellij.openapi.externalSystem.model.project.IExternalSystemSourceType;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalSourceSet extends Serializable {
+  @NotNull
+  String getName();
+  //@NotNull
+  //ClasspathContainer getCompileClasspath();
+
+  //@NotNull
+  //ClasspathContainer getRuntimeClasspath();
+
+  @NotNull
+  Map<IExternalSystemSourceType, ExternalSourceDirectorySet> getSources();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java
new file mode 100644
index 0000000..b4c61c6
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalTask extends Serializable {
+  @NotNull
+  String getName();
+  @NotNull
+  String getQName();
+  @Nullable
+  String getDescription();
+  @Nullable
+  String getGroup();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
index ffe8a52..0e112b1 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
@@ -1,52 +1,62 @@
 package com.intellij.openapi.externalSystem.model.project;
 
-import org.jetbrains.annotations.NotNull;
-
-import java.io.Serializable;
-
 /**
  * Enumerates module source types.
  * 
  * @author Denis Zhdanov
  * @since 8/10/11 5:21 PM
  */
-public class ExternalSystemSourceType implements Serializable {
+public enum ExternalSystemSourceType implements IExternalSystemSourceType {
 
-  @NotNull public static final ExternalSystemSourceType SOURCE   = new ExternalSystemSourceType("SOURCE");
-  @NotNull public static final ExternalSystemSourceType TEST     = new ExternalSystemSourceType("TEST");
-  @NotNull public static final ExternalSystemSourceType EXCLUDED = new ExternalSystemSourceType("EXCLUDED");
-  @NotNull public static final ExternalSystemSourceType SOURCE_GENERATED = new ExternalSystemSourceType("SOURCE_GENERATED");
-  @NotNull public static final ExternalSystemSourceType TEST_GENERATED  = new ExternalSystemSourceType("TEST_GENERATED");
-  @NotNull public static final ExternalSystemSourceType RESOURCE  = new ExternalSystemSourceType("RESOURCE");
-  @NotNull public static final ExternalSystemSourceType TEST_RESOURCE  = new ExternalSystemSourceType("TEST_RESOURCE");
-  
-  private static final long serialVersionUID = 1L;
+  SOURCE(false, false, false, false),
+  TEST(true, false, false, false),
+  EXCLUDED(false, false, false, true),
+  SOURCE_GENERATED(true, true, false, false),
+  TEST_GENERATED(true, true, false, false),
+  RESOURCE(false, false, true, false),
+  TEST_RESOURCE(true, false, true, false);
 
-  @NotNull private final String myId;
+  private final boolean isTest;
+  private final boolean isGenerated;
+  private final boolean isResource;
+  private final boolean isExcluded;
 
-  public ExternalSystemSourceType(@NotNull String id) {
-    myId = id;
+  ExternalSystemSourceType(boolean test, boolean generated, boolean resource, boolean excluded) {
+    isTest = test;
+    isGenerated = generated;
+    isResource = resource;
+    isExcluded = excluded;
   }
 
   @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-
-    ExternalSystemSourceType type = (ExternalSystemSourceType)o;
-
-    if (!myId.equals(type.myId)) return false;
-
-    return true;
+  public boolean isTest() {
+    return isTest;
   }
 
   @Override
-  public int hashCode() {
-    return myId.hashCode();
+  public boolean isGenerated() {
+    return isGenerated;
   }
 
   @Override
-  public String toString() {
-    return myId;
+  public boolean isResource() {
+    return isResource;
+  }
+
+  @Override
+  public boolean isExcluded() {
+    return isExcluded;
+  }
+
+  public static ExternalSystemSourceType from(IExternalSystemSourceType sourceType) {
+    for (ExternalSystemSourceType systemSourceType : ExternalSystemSourceType.values()) {
+      if (systemSourceType.isGenerated == sourceType.isGenerated() &&
+          systemSourceType.isResource == sourceType.isResource() &&
+          systemSourceType.isTest == sourceType.isTest() &&
+          systemSourceType.isExcluded == sourceType.isExcluded()) {
+        return systemSourceType;
+      }
+    }
+    throw new IllegalArgumentException("Invalid source type: " + sourceType);
   }
 }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java
new file mode 100644
index 0000000..2ad8821
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.externalSystem.model.project;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/17/2014
+ */
+public interface IExternalSystemSourceType extends Serializable {
+  boolean isTest();
+
+  boolean isGenerated();
+
+  boolean isResource();
+
+  boolean isExcluded();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
index a6cfc65..fd34934 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
@@ -681,4 +681,9 @@
   public static String getExternalProjectPath(@Nullable Module module) {
     return module != null ? module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY) : null;
   }
+
+  @Nullable
+  public static String getExternalProjectId(@Nullable Module module) {
+    return module != null ? module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_ID_KEY) : null;
+  }
 }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
index 2830678..160c959 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
@@ -27,6 +27,7 @@
   @NonNls @NotNull public static final String EXTERNAL_SYSTEM_ID_KEY  = "external.system.id";
   @NonNls @NotNull public static final String LINKED_PROJECT_PATH_KEY = "external.linked.project.path";
   @NonNls @NotNull public static final String ROOT_PROJECT_PATH_KEY = "external.root.project.path";
+  @NonNls @NotNull public static final String LINKED_PROJECT_ID_KEY = "external.linked.project.id";
 
   @NonNls @NotNull public static final String EXTERNAL_SYSTEM_MODULE_GROUP_KEY  = "external.system.module.group";
   @NonNls @NotNull public static final String EXTERNAL_SYSTEM_MODULE_VERSION_KEY  = "external.system.module.version";
diff --git a/platform/external-system-impl/external-system-impl.iml b/platform/external-system-impl/external-system-impl.iml
index aa68fdc..1cbf68f 100644
--- a/platform/external-system-impl/external-system-impl.iml
+++ b/platform/external-system-impl/external-system-impl.iml
@@ -24,6 +24,7 @@
     <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
     <orderEntry type="module" module-name="testFramework" scope="TEST" />
     <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+    <orderEntry type="module" module-name="compiler-impl" scope="TEST" />
   </component>
 </module>
 
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java
deleted file mode 100644
index 1e6dadd..0000000
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.intellij.openapi.externalSystem.service.project;
-
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Facades all services necessary for the 'sync project changes' processing.
- * <p/>
- * Thread-safe.
- * 
- * @author Denis Zhdanov
- * @since 2/14/12 1:26 PM
- */
-public class ProjectStructureServices {
-
-  @NotNull private final ProjectStructureHelper        myProjectStructureHelper;
-  @NotNull private final PlatformFacade                myPlatformFacade;
-  @NotNull private final ExternalLibraryPathTypeMapper myLibraryPathTypeMapper;
-
-  public ProjectStructureServices(@NotNull ProjectStructureHelper projectStructureHelper,
-                                  @NotNull PlatformFacade platformFacade,
-                                  @NotNull ExternalLibraryPathTypeMapper mapper)
-  {
-    myProjectStructureHelper = projectStructureHelper;
-    myPlatformFacade = platformFacade;
-    myLibraryPathTypeMapper = mapper;
-  }
-
-  @NotNull
-  public ProjectStructureHelper getProjectStructureHelper() {
-    return myProjectStructureHelper;
-  }
-
-  @NotNull
-  public PlatformFacade getPlatformFacade() {
-    return myPlatformFacade;
-  }
-
-  @NotNull
-  public ExternalLibraryPathTypeMapper getLibraryPathTypeMapper() {
-    return myLibraryPathTypeMapper;
-  }
-}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
index 7e74838..3e1c95a 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
@@ -33,8 +33,13 @@
 import com.intellij.openapi.externalSystem.util.Order;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -151,7 +156,7 @@
                 createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, true, createEmptyContentRootDirectories);
               }
               for (SourceRoot path : contentRoot.getPaths(ExternalSystemSourceType.EXCLUDED)) {
-                createExcludedRootIfAbsent(contentEntry, path, module.getName());
+                createExcludedRootIfAbsent(contentEntry, path, module.getName(), module.getProject());
               }
               contentEntriesMap.remove(contentEntry.getUrl());
             }
@@ -214,14 +219,18 @@
     }
   }
 
-  private static void createExcludedRootIfAbsent(@NotNull ContentEntry entry, @NotNull SourceRoot root, @NotNull String moduleName) {
+  private static void createExcludedRootIfAbsent(@NotNull ContentEntry entry, @NotNull SourceRoot root, @NotNull String moduleName, @NotNull Project project) {
+    String rootPath = root.getPath();
     for (VirtualFile file : entry.getExcludeFolderFiles()) {
-      if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(root.getPath())) {
+      if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(rootPath)) {
         return;
       }
     }
     LOG.info(String.format("Importing excluded root '%s' for content root '%s' of module '%s'", root, entry.getUrl(), moduleName));
-    entry.addExcludeFolder(toVfsUrl(root.getPath()));
+    entry.addExcludeFolder(toVfsUrl(rootPath));
+    if (!Registry.is("ide.hide.excluded.files")) {
+      ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(rootPath);
+    }
   }
 
   @Override
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
index 4b1e3b1..3291979 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
@@ -274,6 +274,7 @@
     module.putUserData(MODULE_DATA_KEY, moduleData);
 
     module.setOption(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY, moduleData.getOwner().toString());
+    module.setOption(ExternalSystemConstants.LINKED_PROJECT_ID_KEY, moduleData.getId());
     module.setOption(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY, moduleData.getLinkedExternalProjectPath());
     final ProjectData projectData = moduleDataNode.getData(ProjectKeys.PROJECT);
     module.setOption(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY, projectData != null ? projectData.getLinkedExternalProjectPath() : "");
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
index 6575ffb..c2dcfe5 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
@@ -25,6 +25,7 @@
 import com.intellij.util.containers.ContainerUtilRt;
 import com.intellij.util.containers.Stack;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.List;
@@ -40,8 +41,10 @@
 
   private static final Logger LOG = Logger.getInstance("#" + ProjectDataManager.class.getName());
 
-  @NotNull private final NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>> myServices =
-    new NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>>() {
+  @NotNull private final NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>> myServices;
+
+  public ProjectDataManager() {
+    myServices = new NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>>() {
       @NotNull
       @Override
       protected Map<Key<?>, List<ProjectDataService<?, ?>>> compute() {
@@ -57,10 +60,22 @@
         for (List<ProjectDataService<?, ?>> services : result.values()) {
           ExternalSystemApiUtil.orderAwareSort(services);
         }
-
         return result;
       }
     };
+  }
+
+  @Nullable
+  public List<ProjectDataService<?, ?>> getDataServices(Key<?> key) {
+    return myServices.getValue().get(key);
+  }
+
+  @Nullable
+  public ProjectDataService<?, ?> getDataService(Key<?> key) {
+    final List<ProjectDataService<?, ?>> dataServices = myServices.getValue().get(key);
+    assert dataServices == null || dataServices.isEmpty() || dataServices.size() == 1;
+    return ContainerUtil.getFirstItem(dataServices);
+  }
 
   @SuppressWarnings("unchecked")
   public <T> void importData(@NotNull Collection<DataNode<?>> nodes, @NotNull Project project, boolean synchronous) {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
index 5dcb5ef..deb9a90 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
@@ -193,6 +193,11 @@
     return myProjectSettingsControl;
   }
 
+  @Nullable
+  public ExternalSystemSettingsControl<SystemSettings> getSystemSettingsControl() {
+    return mySystemSettingsControl;
+  }
+
   public void setLinkedProjectPath(@NotNull String path) {
     myProjectSettings.setExternalProjectPath(path);
     myLinkedProjectPathField.setText(path);
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
index 22ec927..449de84 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
@@ -15,24 +15,42 @@
  */
 package com.intellij.openapi.externalSystem.test;
 
+import com.intellij.compiler.CompilerTestUtil;
+import com.intellij.compiler.CompilerWorkspaceConfiguration;
+import com.intellij.compiler.artifacts.ArtifactsTestUtil;
+import com.intellij.compiler.impl.ModuleCompileScope;
+import com.intellij.openapi.application.AccessToken;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.application.WriteAction;
 import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileScope;
+import com.intellij.openapi.compiler.CompileStatusNotification;
+import com.intellij.openapi.compiler.CompilerManager;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.module.StdModuleTypes;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
 import com.intellij.testFramework.IdeaTestCase;
+import com.intellij.testFramework.IdeaTestUtil;
 import com.intellij.testFramework.PsiTestUtil;
 import com.intellij.testFramework.UsefulTestCase;
 import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
 import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.io.TestFileSystemItem;
 import com.intellij.util.ui.UIUtil;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
@@ -40,6 +58,7 @@
 import org.junit.After;
 import org.junit.Before;
 
+import javax.swing.*;
 import java.awt.*;
 import java.io.File;
 import java.io.IOException;
@@ -129,11 +148,11 @@
   @Override
   public void tearDown() throws Exception {
     try {
-      myProject = null;
-      UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+      edt(new Runnable() {
         @Override
         public void run() {
           try {
+            CompilerTestUtil.disableExternalCompiler(myProject);
             tearDownFixtures();
           }
           catch (Exception e) {
@@ -141,6 +160,7 @@
           }
         }
       });
+      myProject = null;
       if (!FileUtil.delete(myTestDir) && myTestDir.exists()) {
         System.err.println("Cannot delete " + myTestDir);
         //printDirectoryContent(myDir);
@@ -319,7 +339,11 @@
   protected VirtualFile createProjectSubFile(String relativePath) throws IOException {
     File f = new File(getProjectPath(), relativePath);
     FileUtil.ensureExists(f.getParentFile());
-    f.createNewFile();
+    FileUtil.ensureCanCreateFile(f);
+    final boolean created = f.createNewFile();
+    if(!created) {
+      throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
+    }
     return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
   }
 
@@ -329,6 +353,116 @@
     return file;
   }
 
+
+  protected void compileModules(final String... moduleNames) {
+    compile(createModulesCompileScope(moduleNames));
+  }
+
+  protected void buildArtifacts(String... artifactNames) {
+    compile(createArtifactsScope(artifactNames));
+  }
+
+  private void compile(final CompileScope scope) {
+    edt(new Runnable() {
+      @Override
+      public void run() {
+        for (Module module : scope.getAffectedModules()) {
+          setupJdkForModule(module.getName());
+        }
+      }
+    });
+
+    CompilerWorkspaceConfiguration.getInstance(myProject).CLEAR_OUTPUT_DIRECTORY = true;
+
+    final Semaphore semaphore = new Semaphore();
+    semaphore.down();
+    edt(new Runnable() {
+      @Override
+      public void run() {
+        CompilerTestUtil.enableExternalCompiler();
+        CompilerManager.getInstance(myProject).make(scope, new CompileStatusNotification() {
+          @Override
+          public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
+            //assertFalse(aborted);
+            //assertEquals(collectMessages(compileContext, CompilerMessageCategory.ERROR), 0, errors);
+            //assertEquals(collectMessages(compileContext, CompilerMessageCategory.WARNING), 0, warnings);
+            semaphore.up();
+          }
+        });
+      }
+    });
+    while (!semaphore.waitFor(100)) {
+      if (SwingUtilities.isEventDispatchThread()) {
+        UIUtil.dispatchAllInvocationEvents();
+      }
+    }
+    if (SwingUtilities.isEventDispatchThread()) {
+      UIUtil.dispatchAllInvocationEvents();
+    }
+  }
+
+  private CompileScope createModulesCompileScope(final String[] moduleNames) {
+    final List<Module> modules = new ArrayList<Module>();
+    for (String name : moduleNames) {
+      modules.add(getModule(name));
+    }
+    return new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
+  }
+
+  private CompileScope createArtifactsScope(String[] artifactNames) {
+    List<Artifact> artifacts = new ArrayList<Artifact>();
+    for (String name : artifactNames) {
+      artifacts.add(ArtifactsTestUtil.findArtifact(myProject, name));
+    }
+    return ArtifactCompileScope.createArtifactsScope(myProject, artifacts);
+  }
+
+  protected Sdk setupJdkForModule(final String moduleName) {
+    final Sdk sdk = true ? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk() : createJdk("Java 1.5");
+    ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
+    return sdk;
+  }
+
+  protected static Sdk createJdk(String versionName) {
+    return IdeaTestUtil.getMockJdk17(versionName);
+  }
+
+  protected Module getModule(final String name) {
+    AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
+    try {
+      Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
+      assertNotNull("Module " + name + " not found", m);
+      return m;
+    }
+    finally {
+      accessToken.finish();
+    }
+  }
+
+  protected void assertExplodedLayout(String artifactName, String expected) {
+    assertJarLayout(artifactName + " exploded", expected);
+  }
+
+  protected void assertJarLayout(String artifactName, String expected) {
+    ArtifactsTestUtil.assertLayout(myProject, artifactName, expected);
+  }
+
+  protected void assertArtifactOutputPath(final String artifactName, final String expected) {
+    ArtifactsTestUtil.assertOutputPath(myProject, artifactName, expected);
+  }
+
+  protected void assertArtifactOutputFileName(final String artifactName, final String expected) {
+    ArtifactsTestUtil.assertOutputFileName(myProject, artifactName, expected);
+  }
+
+  protected void assertArtifactOutput(String artifactName, TestFileSystemItem fs) {
+    final Artifact artifact = ArtifactsTestUtil.findArtifact(myProject, artifactName);
+    final VirtualFile outputFile = artifact.getOutputFile();
+    assert outputFile != null;
+    final File file = VfsUtilCore.virtualToIoFile(outputFile);
+    fs.assertFileEqual(file);
+  }
+
   private static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) throws IOException {
     new WriteAction<VirtualFile>() {
       @Override
diff --git a/platform/icons/src/actions/GroupByFile.png b/platform/icons/src/actions/GroupByFile.png
new file mode 100644
index 0000000..b79988d
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile@2x.png b/platform/icons/src/actions/GroupByFile@2x.png
new file mode 100644
index 0000000..5342abe
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile@2x.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile@2x_dark.png b/platform/icons/src/actions/GroupByFile@2x_dark.png
new file mode 100644
index 0000000..809d342
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile_dark.png b/platform/icons/src/actions/GroupByFile_dark.png
new file mode 100644
index 0000000..f5db91f
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile_dark.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableBanner.png b/platform/icons/src/general/projectConfigurableBanner.png
new file mode 100644
index 0000000..b655f59
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableBanner.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableBanner@2x.png b/platform/icons/src/general/projectConfigurableBanner@2x.png
new file mode 100644
index 0000000..04495ec
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableBanner@2x.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableSelected.png b/platform/icons/src/general/projectConfigurableSelected.png
new file mode 100644
index 0000000..dcbb64a
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableSelected.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableSelected@2x.png b/platform/icons/src/general/projectConfigurableSelected@2x.png
new file mode 100644
index 0000000..3550d5f
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableSelected@2x.png
Binary files differ
diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
index 259ea39..c773402 100644
--- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
+++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
@@ -56,6 +56,8 @@
   private static Set<Module> buildDependents(Module module) {
     Set<Module> result = new THashSet<Module>();
     result.add(module);
+    
+    Set<Module> processedExporting = new THashSet<Module>();
 
     ModuleIndex index = getModuleIndex(module.getProject());
 
@@ -64,9 +66,11 @@
 
     while (!walkingQueue.isEmpty()) {
       Module current = walkingQueue.pullFirst();
+      processedExporting.add(current);
       result.addAll(index.plainUsages.get(current));
       for (Module dependent : index.exportingUsages.get(current)) {
-        if (result.add(dependent)) {
+        result.add(dependent);
+        if (processedExporting.add(dependent)) {
           walkingQueue.addLast(dependent);
         }
       }
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
index 3e65714..8519453 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
@@ -149,7 +149,9 @@
         }
 
         private int convertToMask(final WordOccurrence.Kind kind) {
-          if (kind == null) return UsageSearchContext.ANY;
+          if (kind == null) {
+            return UsageSearchContext.ANY;
+          }
           if (kind == WordOccurrence.Kind.CODE) return UsageSearchContext.IN_CODE;
           if (kind == WordOccurrence.Kind.COMMENTS) return UsageSearchContext.IN_COMMENTS;
           if (kind == WordOccurrence.Kind.LITERALS) return UsageSearchContext.IN_STRINGS;
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
index 6f904ba..b89042b 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
@@ -76,7 +76,7 @@
 
   }
 
-  private GlobalSearchScope getDefaultResolveScope(@NotNull PsiFile psiFile, @NotNull final VirtualFile vFile) {
+  private GlobalSearchScope getResolveScopeFromProviders(@NotNull final VirtualFile vFile) {
     return myDefaultResolveScopesCache.get(vFile);
   }
 
@@ -85,8 +85,6 @@
     Module module = projectFileIndex.getModuleForFile(vFile);
     if (module != null) {
       boolean includeTests = projectFileIndex.isInTestSourceContent(vFile);
-                             // TODO: dmitrylomov: removed this line to see what fails.
-                             //!(vFile.getFileType() == StdFileTypes.JAVA && projectFileIndex.isContentSourceFile(vFile));
       return GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests);
     }
     else {
@@ -167,7 +165,7 @@
       return GlobalSearchScope.allScope(myProject);
     }
 
-    return getDefaultResolveScope(contextFile, vFile);
+    return getResolveScopeFromProviders(vFile);
   }
 
 
@@ -175,7 +173,7 @@
   public GlobalSearchScope getDefaultResolveScope(final VirtualFile vFile) {
     final PsiFile psiFile = myManager.findFile(vFile);
     assert psiFile != null;
-    return getDefaultResolveScope(psiFile, vFile);
+    return getResolveScopeFromProviders(vFile);
   }
 
 
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
index 624d60f..2c152b5 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -16,8 +16,8 @@
 package com.intellij.codeInsight.completion;
 
 import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.SelectionModel;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.util.PsiUtilBase;
@@ -45,26 +45,24 @@
   private final OffsetMap myOffsetMap;
   private String myDummyIdentifier = DUMMY_IDENTIFIER;
 
-  public CompletionInitializationContext(final Editor editor, final PsiFile file, final CompletionType completionType, int invocationCount) {
+  public CompletionInitializationContext(final Editor editor, final Caret caret, final PsiFile file, final CompletionType completionType, int invocationCount) {
     myEditor = editor;
     myFile = file;
     myCompletionType = completionType;
     myInvocationCount = invocationCount;
     myOffsetMap = new OffsetMap(editor.getDocument());
 
-    myOffsetMap.addOffset(START_OFFSET, calcStartOffset(editor));
-    myOffsetMap.addOffset(SELECTION_END_OFFSET, calcSelectionEnd(editor));
-    myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, calcSelectionEnd(editor)));
+    myOffsetMap.addOffset(START_OFFSET, calcStartOffset(caret));
+    myOffsetMap.addOffset(SELECTION_END_OFFSET, calcSelectionEnd(caret));
+    myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, calcSelectionEnd(caret)));
   }
 
-  private static int calcSelectionEnd(Editor editor) {
-    final SelectionModel selectionModel = editor.getSelectionModel();
-    return selectionModel.hasSelection() ? selectionModel.getSelectionEnd() : editor.getCaretModel().getOffset();
+  private static int calcSelectionEnd(Caret caret) {
+    return caret.hasSelection() ? caret.getSelectionEnd() : caret.getOffset();
   }
 
-  public static int calcStartOffset(Editor editor) {
-    final SelectionModel selectionModel = editor.getSelectionModel();
-    return selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset();
+  public static int calcStartOffset(Caret caret) {
+    return caret.hasSelection() ? caret.getSelectionStart() : caret.getOffset();
   }
 
   static int calcDefaultIdentifierEnd(Editor editor, int startFrom) {
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
index 8a7feb2..6cccc06 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
@@ -19,6 +19,7 @@
 import com.intellij.patterns.ElementPattern;
 import com.intellij.patterns.StandardPatterns;
 import com.intellij.util.Consumer;
+import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.LinkedHashSet;
@@ -61,7 +62,6 @@
 
   /**
    * If a given element matches the prefix, give it for further processing (which may eventually result in its appearing in the completion list)
-   * @param element
    */
   public abstract void addElement(@NotNull final LookupElement element);
 
@@ -75,15 +75,17 @@
     }
   }
 
+  @Contract(value="", pure=true)
   @NotNull public abstract CompletionResultSet withPrefixMatcher(@NotNull PrefixMatcher matcher);
 
   /**
    * Creates a default camel-hump prefix matcher based on given prefix
-   * @param prefix
    */
+  @Contract(value="", pure=true)
   @NotNull public abstract CompletionResultSet withPrefixMatcher(@NotNull String prefix);
 
   @NotNull
+  @Contract(value="", pure=true)
   public abstract CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter);
 
   public abstract void addLookupAdvertisement(@NotNull String text);
@@ -92,6 +94,7 @@
    * @return A result set with the same prefix, but the lookup strings will be matched case-insensitively. Their lookup strings will
    * remain as they are though, so upon insertion the prefix case will be changed.
    */
+  @Contract(value="", pure=true)
   @NotNull public abstract CompletionResultSet caseInsensitive();
 
   @NotNull
diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
index 189e658..771ca52 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
@@ -23,6 +23,7 @@
 import com.intellij.psi.PsiNamedElement;
 import com.intellij.psi.util.PsiUtilCore;
 import gnu.trove.THashSet;
+import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -85,10 +86,12 @@
   /**
    * @deprecated use {@link #withInsertHandler(com.intellij.codeInsight.completion.InsertHandler)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setInsertHandler(@Nullable InsertHandler<LookupElement> insertHandler) {
     return withInsertHandler(insertHandler);
   }
 
+  @Contract(value="", pure=true)
   public LookupElementBuilder withInsertHandler(@Nullable InsertHandler<LookupElement> insertHandler) {
     return new LookupElementBuilder(myLookupString, myObject, insertHandler, myRenderer, myHardcodedPresentation,
                                     myAllLookupStrings, myCaseSensitive);
@@ -97,9 +100,11 @@
   /**
    * @deprecated use {@link #withRenderer(LookupElementRenderer)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setRenderer(@Nullable LookupElementRenderer<LookupElement> renderer) {
     return withRenderer(renderer);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withRenderer(@Nullable LookupElementRenderer<LookupElement> renderer) {
     return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, renderer, myHardcodedPresentation,
                                     myAllLookupStrings, myCaseSensitive);
@@ -114,10 +119,12 @@
   /**
    * @deprecated use {@link #withIcon(javax.swing.Icon)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setIcon(@Nullable Icon icon) {
     return withIcon(icon);
   }
 
+  @Contract(value="", pure=true)
   public LookupElementBuilder withIcon(@Nullable Icon icon) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setIcon(icon);
@@ -139,9 +146,11 @@
   /**
    * @deprecated use {@link #withLookupString(String)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder addLookupString(@NotNull String another) {
     return withLookupString(another);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withLookupString(@NotNull String another) {
     final THashSet<String> set = new THashSet<String>(myAllLookupStrings);
     set.add(another);
@@ -157,6 +166,7 @@
   /**
    * @deprecated use {@link #withCaseSensitivity(boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setCaseSensitive(boolean caseSensitive) {
     return withCaseSensitivity(caseSensitive);
   }
@@ -165,6 +175,7 @@
    * @return modified builder
    * @see com.intellij.codeInsight.completion.CompletionResultSet#caseInsensitive()
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder withCaseSensitivity(boolean caseSensitive) {
     return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, myRenderer, myHardcodedPresentation,
                                     myAllLookupStrings, caseSensitive);
@@ -173,9 +184,11 @@
   /**
    * @deprecated use {@link #withItemTextForeground(java.awt.Color)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setItemTextForeground(@NotNull Color itemTextForeground) {
     return withItemTextForeground(itemTextForeground);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withItemTextForeground(@NotNull Color itemTextForeground) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setItemTextForeground(itemTextForeground);
@@ -185,9 +198,11 @@
   /**
    * @deprecated use {@link #withItemTextUnderlined(boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setItemTextUnderlined(boolean underlined) {
     return withItemTextUnderlined(underlined);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withItemTextUnderlined(boolean underlined) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setItemTextUnderlined(underlined);
@@ -197,9 +212,11 @@
   /**
    * @deprecated use {@link #withTypeText(String)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setTypeText(@Nullable String typeText) {
     return withTypeText(typeText);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withTypeText(@Nullable String typeText) {
     return withTypeText(typeText, false);
   }
@@ -207,14 +224,17 @@
   /**
    * @deprecated use {@link #withTypeText(String, boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setTypeText(@Nullable String typeText, boolean grayed) {
     return withTypeText(typeText, grayed);
   }
 
+  @Contract(value="", pure=true)
   public LookupElementBuilder withTypeText(@Nullable String typeText, boolean grayed) {
     return withTypeText(typeText, null, grayed);
   }
 
+  @Contract(value="", pure=true)
   public LookupElementBuilder withTypeText(@Nullable String typeText, @Nullable Icon typeIcon, boolean grayed) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setTypeText(typeText, typeIcon);
@@ -226,9 +246,11 @@
   /**
    * @deprecated use {@link #withPresentableText(String)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setPresentableText(@NotNull String presentableText) {
     return withPresentableText(presentableText);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withPresentableText(@NotNull String presentableText) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setItemText(presentableText);
@@ -239,9 +261,11 @@
   /**
    * @deprecated use {@link #bold()}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setBold() {
     return bold();
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder bold() {
     return withBoldness(true);
   }
@@ -249,9 +273,11 @@
   /**
    * @deprecated use {@link #withBoldness(boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setBold(boolean bold) {
     return withBoldness(bold);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withBoldness(boolean bold) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setItemTextBold(bold);
@@ -262,9 +288,11 @@
   /**
    * @deprecated use {@link #strikeout()}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setStrikeout() {
     return strikeout();
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder strikeout() {
     return withStrikeoutness(true);
   }
@@ -272,9 +300,11 @@
   /**
    * @deprecated use {@link #withStrikeoutness(boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setStrikeout(boolean strikeout) {
     return withStrikeoutness(strikeout);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withStrikeoutness(boolean strikeout) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setStrikeout(strikeout);
@@ -285,9 +315,11 @@
   /**
    * @deprecated use {@link #withTailText(String)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setTailText(@Nullable String tailText) {
     return withTailText(tailText);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withTailText(@Nullable String tailText) {
     return withTailText(tailText, false);
   }
@@ -295,9 +327,11 @@
   /**
    * @deprecated use {@link #withTailText(String, boolean)}
    */
+  @Contract(value="", pure=true)
   public LookupElementBuilder setTailText(@Nullable String tailText, boolean grayed) {
     return withTailText(tailText, grayed);
   }
+  @Contract(value="", pure=true)
   public LookupElementBuilder withTailText(@Nullable String tailText, boolean grayed) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.setTailText(tailText, grayed);
@@ -305,12 +339,14 @@
                                     myAllLookupStrings, myCaseSensitive);
   }
 
+  @Contract(value="", pure=true)
   public LookupElementBuilder appendTailText(@NotNull String tailText, boolean grayed) {
     final LookupElementPresentation presentation = copyPresentation();
     presentation.appendTailText(tailText, grayed);
     return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, null, presentation, myAllLookupStrings, myCaseSensitive);
   }
 
+  @Contract(value="", pure=true)
   public LookupElement withAutoCompletionPolicy(AutoCompletionPolicy policy) {
     return policy.applyPolicy(this);
   }
diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
index efee74b..8d4d3b2 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
@@ -142,14 +142,15 @@
     return myContent;
   }
 
-  public void setRestarter(Runnable runnable) {
-    myRestarter = runnable;
-  }
-
+  @Nullable
   public Runnable getRestarter() {
     return myRestarter;
   }
 
+  public void setRestarter(@Nullable Runnable runnable) {
+    myRestarter = runnable;
+  }
+
   public boolean isActivateToolWindowWhenAdded() {
     return myActivateToolWindowWhenAdded;
   }
diff --git a/platform/lang-api/src/com/intellij/find/FindManager.java b/platform/lang-api/src/com/intellij/find/FindManager.java
index 56339d1..abf90bb 100644
--- a/platform/lang-api/src/com/intellij/find/FindManager.java
+++ b/platform/lang-api/src/com/intellij/find/FindManager.java
@@ -172,6 +172,18 @@
   public abstract void setFindWasPerformed();
 
   /**
+   * Gets the flag indicating that 'Add Selection for Next Occurrence' action was performed recently,
+   * so "Find Next" and "Find Previous" actions should work in its context.
+   */
+  public abstract boolean selectNextOccurrenceWasPerformed();
+
+  /**
+   * Sets the flag indicating that 'Add Selection for Next Occurrence' action was performed recently,
+   * so "Find Next" and "Find Previous" actions should work in its context.
+   */
+  public abstract void setSelectNextOccurrenceWasPerformed();
+
+  /**
    * Explicitly tell FindManager that "Find Next" and "Find Previous" actions should not use
    * find usages previous results.
    */
diff --git a/platform/lang-api/src/com/intellij/find/FindModel.java b/platform/lang-api/src/com/intellij/find/FindModel.java
index a09070c..5dafc2d 100644
--- a/platform/lang-api/src/com/intellij/find/FindModel.java
+++ b/platform/lang-api/src/com/intellij/find/FindModel.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.search.SearchScope;
+import com.intellij.util.PatternUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -72,8 +73,7 @@
   private boolean isSearchHighlighters = false;
   private boolean isReplaceState = false;
   private boolean isWholeWordsOnly = false;
-  private boolean isInCommentsOnly;
-  private boolean isInStringLiteralsOnly;
+  private SearchContext searchContext = SearchContext.ANY;
   private boolean isFromCursor = true;
   private boolean isForward = true;
   private boolean isGlobal = true;
@@ -96,6 +96,7 @@
   private SearchScope customScope;
   private boolean isCustomScope = false;
   private boolean isMultiline = false;
+  private boolean mySearchInProjectFiles;
 
   public boolean isMultiline() {
     return isMultiline;
@@ -170,8 +171,7 @@
     isCustomScope = model.isCustomScope;
     isFindAll = model.isFindAll;
 
-    isInCommentsOnly = model.isInCommentsOnly;
-    isInStringLiteralsOnly = model.isInStringLiteralsOnly;
+    searchContext = model.searchContext;
 
     isMultiline = model.isMultiline;
   }
@@ -190,8 +190,8 @@
     if (isForward != findModel.isForward) return false;
     if (isFromCursor != findModel.isFromCursor) return false;
     if (isGlobal != findModel.isGlobal) return false;
-    if (isInCommentsOnly != findModel.isInCommentsOnly) return false;
-    if (isInStringLiteralsOnly != findModel.isInStringLiteralsOnly) return false;
+    if (searchContext != findModel.searchContext) return false;
+
     if (isMultiline != findModel.isMultiline) return false;
     if (isMultipleFiles != findModel.isMultipleFiles) return false;
     if (isOpenInNewTabEnabled != findModel.isOpenInNewTabEnabled) return false;
@@ -215,6 +215,7 @@
     if (myStringToReplace != null ? !myStringToReplace.equals(findModel.myStringToReplace) : findModel.myStringToReplace != null) {
       return false;
     }
+    if (mySearchInProjectFiles != findModel.mySearchInProjectFiles) return false;
 
     return true;
   }
@@ -227,8 +228,7 @@
     result = 31 * result + (isSearchHighlighters ? 1 : 0);
     result = 31 * result + (isReplaceState ? 1 : 0);
     result = 31 * result + (isWholeWordsOnly ? 1 : 0);
-    result = 31 * result + (isInCommentsOnly ? 1 : 0);
-    result = 31 * result + (isInStringLiteralsOnly ? 1 : 0);
+    result = 31 * result + (searchContext.ordinal());
     result = 31 * result + (isFromCursor ? 1 : 0);
     result = 31 * result + (isForward ? 1 : 0);
     result = 31 * result + (isGlobal ? 1 : 0);
@@ -252,6 +252,7 @@
     result = 31 * result + (isCustomScope ? 1 : 0);
     result = 31 * result + (isMultiline ? 1 : 0);
     result = 31 * result + (isPreserveCase ? 1 : 0);
+    result = 31 * result + (mySearchInProjectFiles ? 1 : 0);
     result = 31 * result + (myPattern != null ? myPattern.hashCode() : 0);
     return result;
   }
@@ -274,7 +275,7 @@
   public void setStringToFind(@NotNull String s) {
     boolean changed = !StringUtil.equals(s, myStringToFind);
     myStringToFind = s;
-    myPattern = NO_PATTERN;
+    myPattern = PatternUtil.NOTHING;
     if (changed) {
       notifyObservers();
     }
@@ -409,7 +410,7 @@
     boolean changed = val != isCaseSensitive;
     isCaseSensitive = val;
     if (changed) {
-      myPattern = NO_PATTERN;
+      myPattern = PatternUtil.NOTHING;
       notifyObservers();
     }
   }
@@ -658,8 +659,8 @@
   }
 
   @Override
-  public Object clone() {
-    return super.clone();
+  public FindModel clone() {
+    return (FindModel)super.clone();
   }
 
 
@@ -670,8 +671,7 @@
     buffer.append("myStringToReplace =").append(myStringToReplace).append("\n");
     buffer.append("isReplaceState =").append(isReplaceState).append("\n");
     buffer.append("isWholeWordsOnly =").append(isWholeWordsOnly).append("\n");
-    buffer.append("isInStringLiterals =").append(isInStringLiteralsOnly).append("\n");
-    buffer.append("isInComments =").append(isInCommentsOnly).append("\n");
+    buffer.append("searchContext =").append(searchContext).append("\n");
     buffer.append("isFromCursor =").append(isFromCursor).append("\n");
     buffer.append("isForward =").append(isForward).append("\n");
     buffer.append("isGlobal =").append(isGlobal).append("\n");
@@ -689,6 +689,7 @@
     buffer.append("fileFilter =").append(fileFilter).append("\n");
     buffer.append("moduleName =").append(moduleName).append("\n");
     buffer.append("customScopeName =").append(customScopeName).append("\n");
+    buffer.append("searchInProjectFiles =").append(mySearchInProjectFiles).append("\n");
     return buffer.toString();
   }
 
@@ -849,45 +850,95 @@
     }
   }
 
-  public boolean isInStringLiteralsOnly() {
-    return isInStringLiteralsOnly;
+  public enum SearchContext {
+    ANY, IN_STRING_LITERALS, IN_COMMENTS, EXCEPT_STRING_LITERALS, EXCEPT_COMMENTS, EXCEPT_COMMENTS_AND_STRING_LITERALS
   }
 
-  public void setInStringLiteralsOnly(boolean inStringLiteralsOnly) {
-    boolean changed = isInStringLiteralsOnly != inStringLiteralsOnly;
-    isInStringLiteralsOnly = inStringLiteralsOnly;
-    if (changed) {
-      notifyObservers();
-    }
+  public boolean isInStringLiteralsOnly() {
+    return searchContext == SearchContext.IN_STRING_LITERALS;
+  }
+
+  public boolean isExceptComments() {
+    return searchContext == SearchContext.EXCEPT_COMMENTS;
+  }
+
+  public boolean isExceptStringLiterals() {
+    return searchContext == SearchContext.EXCEPT_STRING_LITERALS;
   }
 
   public boolean isInCommentsOnly() {
-    return isInCommentsOnly;
+    return searchContext == SearchContext.IN_COMMENTS;
   }
 
+  public boolean isExceptCommentsAndStringLiterals() {
+    return searchContext == SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS;
+  }
+
+  @Deprecated
   public void setInCommentsOnly(boolean inCommentsOnly) {
-    boolean changed = isInCommentsOnly != inCommentsOnly;
-    isInCommentsOnly = inCommentsOnly;
+    doApplyContextChange(inCommentsOnly, SearchContext.IN_COMMENTS);
+  }
+
+  @Deprecated
+  public void setInStringLiteralsOnly(boolean inStringLiteralsOnly) {
+    doApplyContextChange(inStringLiteralsOnly, SearchContext.IN_STRING_LITERALS);
+  }
+
+  private void doApplyContextChange(boolean newOptionValue, SearchContext option) {
+    boolean changed = false;
+    if (newOptionValue) {
+      changed = searchContext != option;
+      searchContext = option;
+    } else if (searchContext == option) { // do not reset unrelated value
+      changed = true;
+      searchContext = SearchContext.ANY;
+    }
+
     if (changed) {
       notifyObservers();
     }
   }
 
-  private static final Pattern NO_PATTERN = Pattern.compile("");
-  private Pattern myPattern = NO_PATTERN;
+  public @NotNull SearchContext getSearchContext() {
+    return searchContext;
+  }
+
+  public void setSearchContext(@NotNull SearchContext _searchContext) {
+    doSetContext(_searchContext);
+  }
+
+  private void doSetContext(SearchContext newSearchContext) {
+    boolean changed = newSearchContext != searchContext;
+    searchContext = newSearchContext;
+    if (changed) {
+      notifyObservers();
+    }
+  }
+
+  public boolean isSearchInProjectFiles() {
+    return mySearchInProjectFiles;
+  }
+
+  public void setSearchInProjectFiles(boolean searchInProjectFiles) {
+    boolean changed = mySearchInProjectFiles != searchInProjectFiles;
+    mySearchInProjectFiles = searchInProjectFiles;
+    if (changed) {
+      notifyObservers();
+    }
+  }
+
+  private Pattern myPattern = PatternUtil.NOTHING;
 
   public Pattern compileRegExp() {
     String toFind = getStringToFind();
 
     Pattern pattern = myPattern;
-    if (pattern == NO_PATTERN) {
+    if (pattern == PatternUtil.NOTHING) {
       try {
         myPattern = pattern = Pattern.compile(toFind, isCaseSensitive() ? Pattern.MULTILINE : Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
       }
       catch (PatternSyntaxException e) {
-        LOG.error("Regexp:'" + toFind + "'", e);
-        myPattern = null;
-        return null;
+        myPattern = pattern = null;
       }
     }
 
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
index bb8a60c..6f23ac6 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
 import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.platform.ProjectTemplate;
 import com.intellij.util.SystemProperties;
@@ -48,6 +49,7 @@
   private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
   private StorageScheme myProjectStorageFormat = StorageScheme.DIRECTORY_BASED;
   private boolean myNewWizard;
+  private ModulesProvider myModulesProvider;
 
   public void setProjectStorageFormat(StorageScheme format) {
     myProjectStorageFormat = format;
@@ -61,6 +63,14 @@
     myNewWizard = newWizard;
   }
 
+  public ModulesProvider getModulesProvider() {
+    return myModulesProvider;
+  }
+
+  public void setModulesProvider(ModulesProvider modulesProvider) {
+    myModulesProvider = modulesProvider;
+  }
+
   public interface Listener {
     void buttonsUpdateRequested();
     void nextStepRequested();
diff --git a/platform/lang-api/src/com/intellij/lexer/LexerUtil.java b/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
index 7623248..8abdfa5 100644
--- a/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
+++ b/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
@@ -16,6 +16,8 @@
 package com.intellij.lexer;
 
 import com.intellij.util.CharTable;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author max
@@ -30,4 +32,12 @@
   public static CharSequence internToken(Lexer lexer, CharTable table) {
     return table.intern(getTokenText(lexer));
   }
+
+  @Contract("!null->!null")
+  public static Lexer getRootLexer(@Nullable Lexer lexer) {
+    while (lexer instanceof DelegateLexer) {
+      lexer = ((DelegateLexer)lexer).getDelegate();
+    }
+    return lexer;
+  }
 }
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
index 2c44a32..d858bfc 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
@@ -56,7 +56,6 @@
 
   public CodeStyleSettings(boolean loadExtensions) {
     super(null);
-    RIGHT_MARGIN = DEFAULT_RIGHT_MARGIN;
     initTypeToName();
     initImportsByDefault();
 
@@ -108,12 +107,16 @@
 
   private void addCustomSettings(CustomCodeStyleSettings settings) {
     if (settings != null) {
-      myCustomSettings.put(settings.getClass(), settings);
+      synchronized (myCustomSettings) {
+        myCustomSettings.put(settings.getClass(), settings);
+      }
     }
   }
 
   public <T extends CustomCodeStyleSettings> T getCustomSettings(Class<T> aClass) {
-    return (T)myCustomSettings.get(aClass);
+    synchronized (myCustomSettings) {
+      return (T)myCustomSettings.get(aClass);
+    }
   }
 
   @Override
@@ -125,7 +128,7 @@
 
   private void copyCustomSettingsFrom(@NotNull CodeStyleSettings from) {
     myCustomSettings.clear();
-    for (final CustomCodeStyleSettings settings : from.myCustomSettings.values()) {
+    for (final CustomCodeStyleSettings settings : from.getCustomSettingsValues()) {
       addCustomSettings((CustomCodeStyleSettings) settings.clone());
     }
 
@@ -244,6 +247,7 @@
   public int INNER_CLASSES_ORDER_WEIGHT = 7;
 
 //----------------- WRAPPING ---------------------------
+  public int RIGHT_MARGIN = 120;
   public boolean WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = false;
 
 
@@ -431,6 +435,12 @@
   private CodeStyleSettings myParentSettings;
   private boolean myLoadedAdditionalIndentOptions;
 
+  private Collection<CustomCodeStyleSettings> getCustomSettingsValues() {
+    synchronized (myCustomSettings) {
+      return Collections.unmodifiableCollection(myCustomSettings.values());
+    }
+  }
+
   @Override
   public void readExternal(Element element) throws InvalidDataException {
     DefaultJDOMExternalizer.readExternal(this, element);
@@ -452,7 +462,7 @@
       }
     }
     boolean oldOptionsImported = importOldIndentOptions(element);
-    for (final CustomCodeStyleSettings settings : myCustomSettings.values()) {
+    for (final CustomCodeStyleSettings settings : getCustomSettingsValues()) {
       settings.readExternal(element);
       settings.importLegacySettings();
     }
@@ -564,7 +574,7 @@
   public void writeExternal(Element element) throws WriteExternalException {
     final CodeStyleSettings parentSettings = new CodeStyleSettings();
     DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter<CodeStyleSettings>(this, parentSettings));
-    List<CustomCodeStyleSettings> customSettings = new ArrayList<CustomCodeStyleSettings>(myCustomSettings.values());
+    List<CustomCodeStyleSettings> customSettings = new ArrayList<CustomCodeStyleSettings>(getCustomSettingsValues());
     
     Collections.sort(customSettings, new Comparator<CustomCodeStyleSettings>(){
       @Override
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
index 20b96ca..299d172 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -287,7 +287,6 @@
 
 //----------------- GENERAL --------------------
   public int RIGHT_MARGIN = -1;
-  public final static int DEFAULT_RIGHT_MARGIN = 120;
 
   public boolean LINE_COMMENT_AT_FIRST_COLUMN = true;
   public boolean BLOCK_COMMENT_AT_FIRST_COLUMN = true;
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
index f978d5f..59736bc 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
@@ -18,6 +18,7 @@
 import com.intellij.lang.Language;
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
 import com.intellij.ui.SpeedSearchComparator;
 import com.intellij.ui.TreeTableSpeedSearch;
@@ -378,7 +379,7 @@
       this.groupName = groupName;
 
       try {
-        Class styleSettingsClass = clazz == null ? CodeStyleSettings.class : clazz;
+        Class styleSettingsClass = clazz == null ? CommonCodeStyleSettings.class : clazz;
         this.field = styleSettingsClass.getField(fieldName);
       }
       catch (NoSuchFieldException e) {
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
new file mode 100644
index 0000000..67f579a
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.codeStyle.RightMarginForm">
+  <grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="12cf8" class="com.intellij.ui.components.JBLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/ApplicationBundle" key="editbox.right.margin.columns"/>
+        </properties>
+      </component>
+      <vspacer id="1265c">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+      <component id="78fe" class="javax.swing.JTextField" binding="myRightMarginField">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+            <preferred-size width="50" height="-1"/>
+          </grid>
+        </constraints>
+        <properties>
+          <horizontalAlignment value="2"/>
+        </properties>
+      </component>
+      <component id="5ef52" class="javax.swing.JCheckBox" binding="myDefaultGeneralCheckBox" default-binding="true">
+        <constraints>
+          <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/ApplicationBundle" key="settings.code.style.default.general"/>
+        </properties>
+      </component>
+    </children>
+  </grid>
+</form>
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
new file mode 100644
index 0000000..70c747d
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package com.intellij.application.options.codeStyle;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * Can be used for languages which do not use standard "Wrapping and Braces" panel.
+ * <p>
+ * <strong>Note</strong>: besides adding the panel to UI it is necessary to make sure that language's own
+ * <code>LanguageCodeStyleSettingsProvider</code> explicitly supports RIGHT_MARGIN field in <code>customizeSettings()</code>
+ * method as shown below:
+ * <pre>
+ * public void customizeSettings(...) {
+ *   if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+ *     consumer.showStandardOptions("RIGHT_MARGIN");
+ *   }
+ * }
+ * </pre>
+ * @author Rustam Vishnyakov
+ */
+public class RightMarginForm {
+  private JTextField myRightMarginField;
+  private JCheckBox myDefaultGeneralCheckBox;
+  private JPanel myTopPanel;
+  private final Language myLanguage;
+  private final int myDefaultRightMargin;
+
+  public RightMarginForm(@NotNull Language language, @NotNull CodeStyleSettings settings) {
+    myLanguage = language;
+    myDefaultRightMargin = settings.RIGHT_MARGIN;
+    myDefaultGeneralCheckBox.addChangeListener(new ChangeListener() {
+      @Override
+      public void stateChanged(ChangeEvent e) {
+        if (myDefaultGeneralCheckBox.isSelected()) {
+          myRightMarginField.setText(Integer.toString(myDefaultRightMargin));
+          myRightMarginField.setEnabled(false);
+        }
+        else {
+          myRightMarginField.setEnabled(true);
+        }
+      }
+    });
+  }
+
+  public void reset(@NotNull CodeStyleSettings settings) {
+    CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+    if (langSettings != settings && langSettings.RIGHT_MARGIN >= 0) {
+      myDefaultGeneralCheckBox.setSelected(false);
+      myRightMarginField.setText(Integer.toString(langSettings.RIGHT_MARGIN));
+    }
+    else {
+      myDefaultGeneralCheckBox.setSelected(true);
+      myRightMarginField.setText(Integer.toString(settings.RIGHT_MARGIN));
+      if (langSettings == settings) {
+        myDefaultGeneralCheckBox.setEnabled(false);
+        myRightMarginField.setEnabled(false);
+      }
+    }
+  }
+
+  public void apply(@NotNull CodeStyleSettings settings) {
+    CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+    if (langSettings != settings) {
+      if (myDefaultGeneralCheckBox.isSelected()) {
+        langSettings.RIGHT_MARGIN = -1;
+      }
+      else {
+        langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.RIGHT_MARGIN);
+      }
+    }
+  }
+
+  public boolean isModified(@NotNull CodeStyleSettings settings) {
+    CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+    if (myDefaultGeneralCheckBox.isSelected()) {
+      return langSettings.RIGHT_MARGIN >= 0;
+    }
+    else {
+      return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.RIGHT_MARGIN);
+    }
+  }
+
+  private int getFieldRightMargin(int fallBackValue) {
+    String strValue = myRightMarginField.getText();
+    if (!strValue.trim().isEmpty()) {
+      try {
+        return Integer.parseInt(strValue);
+      }
+      catch (NumberFormatException e) {
+        myRightMarginField.setText(Integer.toString(fallBackValue));
+      }
+    }
+    return fallBackValue;
+  }
+
+  public JPanel getTopPanel() {
+    return myTopPanel;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
index fa14958..145ae10 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
@@ -165,7 +165,7 @@
     }
 
     final List<ArrangementSectionRule> result = ContainerUtil.newArrayList();
-    final List<StdArrangementMatchRule> currentRules = ContainerUtil.newArrayList();
+    final List<StdArrangementMatchRule> buffer = ContainerUtil.newArrayList();
     String currentSectionStart = null;
     for (int i = 0; i < getModel().getSize(); i++) {
       Object element = getModel().getElementAt(i);
@@ -174,15 +174,12 @@
           mySectionRuleManager == null ? null : mySectionRuleManager.getSectionRuleData((StdArrangementMatchRule)element);
         if (sectionRule != null) {
           if (sectionRule.isSectionStart()) {
-            if (currentSectionStart != null) {
-              result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
-              currentRules.clear();
-            }
+            appendBufferedSectionRules(result, buffer, currentSectionStart);
             currentSectionStart = sectionRule.getText();
           }
           else {
-            result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), currentRules));
-            currentRules.clear();
+            result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), buffer));
+            buffer.clear();
             currentSectionStart = null;
           }
         }
@@ -190,17 +187,34 @@
           result.add(ArrangementSectionRule.create((StdArrangementMatchRule)element));
         }
         else {
-          currentRules.add((StdArrangementMatchRule)element);
+          buffer.add((StdArrangementMatchRule)element);
         }
       }
     }
 
-    if (currentSectionStart != null) {
-      result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
-    }
+    appendBufferedSectionRules(result, buffer, currentSectionStart);
     return result;
   }
 
+  private static void appendBufferedSectionRules(@NotNull List<ArrangementSectionRule> result,
+                                                 @NotNull List<StdArrangementMatchRule> buffer,
+                                                 @Nullable String currentSectionStart) {
+    if (currentSectionStart == null) {
+      return;
+    }
+
+    if (buffer.isEmpty()) {
+      result.add(ArrangementSectionRule.create(currentSectionStart, null));
+    }
+    else {
+      result.add(ArrangementSectionRule.create(currentSectionStart, null, buffer.get(0)));
+      for (int j = 1; j < buffer.size(); j++) {
+        result.add(ArrangementSectionRule.create(buffer.get(j)));
+      }
+      buffer.clear();
+    }
+  }
+
   @Override
   protected void processMouseEvent(MouseEvent e) {
     int id = e.getID();
diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
index 9872c7c..db23ce1 100644
--- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
+++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
@@ -3,7 +3,7 @@
   <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="20" y="20" width="500" height="527"/>
+      <xy x="20" y="20" width="500" height="585"/>
     </constraints>
     <properties/>
     <border type="none"/>
@@ -108,7 +108,7 @@
           <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
-      <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
+      <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
           <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -119,7 +119,7 @@
         </clientProperties>
         <border type="none" title-resource-bundle="messages/ApplicationBundle" title-key="group.tab.closing.policy"/>
         <children>
-          <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+          <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
             <margin top="0" left="0" bottom="0" right="0"/>
             <constraints>
               <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -129,7 +129,9 @@
             <children>
               <component id="527a6" class="javax.swing.JLabel">
                 <constraints>
-                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                    <preferred-size width="60" height="27"/>
+                  </grid>
                 </constraints>
                 <properties>
                   <text resource-bundle="messages/ApplicationBundle" key="editbox.tab.limit"/>
@@ -138,19 +140,38 @@
               <component id="16477" class="javax.swing.JTextField" binding="myEditorTabLimitField">
                 <constraints>
                   <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
-                    <preferred-size width="30" height="-1"/>
+                    <preferred-size width="30" height="27"/>
                   </grid>
                 </constraints>
                 <properties>
                   <text value="15"/>
                 </properties>
               </component>
+              <component id="2479d" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="messages/ApplicationBundle" key="editbox.tab.title.limit"/>
+                </properties>
+              </component>
+              <component id="3499c" class="javax.swing.JTextField" binding="myTabTitleLimitField">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                    <preferred-size width="30" height="27"/>
+                  </grid>
+                </constraints>
+                <properties>
+                  <columns value="2"/>
+                  <text value="30"/>
+                </properties>
+              </component>
             </children>
           </grid>
           <grid id="9b723" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
             <margin top="0" left="0" bottom="0" right="0"/>
             <constraints>
-              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties/>
             <border type="none"/>
@@ -184,7 +205,7 @@
           <grid id="611cc" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
             <margin top="10" left="0" bottom="0" right="0"/>
             <constraints>
-              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+              <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties/>
             <border type="none"/>
diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
index 4e1de81..35a3408 100644
--- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
@@ -45,6 +45,7 @@
   private JCheckBox myShowCloseButtonOnCheckBox;
   private JCheckBox myShowDirectoryInTabCheckBox;
   private JRadioButton myActivateRightNeighbouringTabRadioButton;
+  private JTextField myTabTitleLimitField;
 
   public EditorTabsConfigurable() {
     myEditorTabPlacement.setModel(new DefaultComboBoxModel(new Object[]{
@@ -119,6 +120,7 @@
     myHideKnownExtensions.setSelected(uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS);
     myShowDirectoryInTabCheckBox.setSelected(uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES);
     myEditorTabLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_LIMIT));
+    myTabTitleLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_TITLE_LIMIT));
     myShowCloseButtonOnCheckBox.setSelected(uiSettings.SHOW_CLOSE_BUTTON);
 
     if (uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST) {
@@ -171,14 +173,29 @@
     uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE = myActivateRightNeighbouringTabRadioButton.isSelected();
 
     String temp = myEditorTabLimitField.getText();
-    if(temp.trim().length() > 0){
+    if (temp.trim().length() > 0) {
       try {
         int newEditorTabLimit = Integer.parseInt(temp);
-        if(newEditorTabLimit>0&&newEditorTabLimit!=uiSettings.EDITOR_TAB_LIMIT){
-          uiSettings.EDITOR_TAB_LIMIT=newEditorTabLimit;
+        if (newEditorTabLimit > 0 && newEditorTabLimit != uiSettings.EDITOR_TAB_LIMIT) {
+          uiSettings.EDITOR_TAB_LIMIT = newEditorTabLimit;
           uiSettingsChanged = true;
         }
-      }catch (NumberFormatException ignored){}
+      }
+      catch (NumberFormatException ignored) {
+      }
+    }
+    temp = myTabTitleLimitField.getText();
+    if (temp.trim().length() > 0) {
+      try {
+        int newTabTitleLimit = Integer.parseInt(temp);
+        newTabTitleLimit = Math.max(25, Math.min(100, newTabTitleLimit));
+        if (newTabTitleLimit != uiSettings.EDITOR_TAB_TITLE_LIMIT){
+          uiSettings.EDITOR_TAB_TITLE_LIMIT = newTabTitleLimit;
+          uiSettingsChanged = true;
+        }
+      }
+      catch (NumberFormatException ignored) {
+      }
     }
     if(uiSettingsChanged){
       uiSettings.fireUISettingsChanged();
@@ -191,6 +208,7 @@
     boolean isModified = isModified(myCbModifiedTabsMarkedWithAsterisk, uiSettings.MARK_MODIFIED_TABS_WITH_ASTERISK);
     isModified |= isModified(myShowTabsTooltipsCheckBox, uiSettings.SHOW_TABS_TOOLTIPS);
     isModified |= isModified(myEditorTabLimitField, uiSettings.EDITOR_TAB_LIMIT);
+    isModified |= isModified(myTabTitleLimitField, uiSettings.EDITOR_TAB_TITLE_LIMIT);
     int tabPlacement = ((Integer)myEditorTabPlacement.getSelectedItem()).intValue();
     isModified |= tabPlacement != uiSettings.EDITOR_TAB_PLACEMENT;
     isModified |= myHideKnownExtensions.isSelected() != uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
index bf77a30..af6bbdc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
@@ -289,7 +289,16 @@
     }
 
     try {
-      List<Range> changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+      List<Range> changedRanges;
+
+      LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document);
+      if (tracker != null) {
+        changedRanges = tracker.getRanges();
+      }
+      else {
+        changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+      }
+
       return getChangedTextRanges(document, changedRanges);
     }
     catch (FilesTooBigForDiffException e) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
index 4966a94..8ec833e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
@@ -79,9 +79,6 @@
     PsiDocumentManager.getInstance(project).commitAllDocuments();
     final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
     final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
-    if (files == null) {
-      return;
-    }
 
     PsiFile file = null;
     final PsiDirectory dir;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
index e0a3be5..fcb080d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
@@ -71,6 +71,8 @@
 
 public class CodeCompletionHandlerBase {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CodeCompletionHandlerBase");
+  private static final Key<Boolean> CARET_PROCESSED = Key.create("CodeCompletionHandlerBase.caretProcessed");
+
   @NotNull private final CompletionType myCompletionType;
   final boolean invokedExplicitly;
   final boolean synchronous;
@@ -108,6 +110,13 @@
   }
 
   public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted) {
+    clearCaretMarkers(editor);
+    invokeCompletion(project, editor, time, hasModifiers, restarted, editor.getCaretModel().getPrimaryCaret());
+  }
+
+  public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted, @NotNull final Caret caret) {
+    markCaretAsProcessed(caret);
+
     if (invokedExplicitly) {
       CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
     }
@@ -162,12 +171,12 @@
             PsiDocumentManager.getInstance(project).commitAllDocuments();
             CompletionAssertions.checkEditorValid(editor);
 
-            final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
+            final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
             assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
             psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
             CompletionAssertions.assertCommitSuccessful(editor, psiFile);
 
-            initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount);
+            initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount, caret);
           }
         };
         ApplicationManager.getApplication().runWriteAction(runnable);
@@ -186,9 +195,9 @@
     insertDummyIdentifier(initializationContext[0], hasModifiers, invocationCount);
   }
 
-  private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount) {
+  private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount, Caret caret) {
     final Ref<CompletionContributor> current = Ref.create(null);
-    CompletionInitializationContext context = new CompletionInitializationContext(editor, psiFile, myCompletionType, invocationCount) {
+    CompletionInitializationContext context = new CompletionInitializationContext(editor, caret, psiFile, myCompletionType, invocationCount) {
       CompletionContributor dummyIdentifierChanger;
 
       @Override
@@ -400,8 +409,15 @@
                                     final LookupElement[] items, boolean hasModifiers) {
     if (items.length == 0) {
       LookupManager.getInstance(indicator.getProject()).hideActiveLookup();
-      indicator.handleEmptyLookup(true);
-      checkNotSync(indicator, items);
+
+      Caret nextCaret = getNextCaretToProcess(indicator.getEditor());
+      if (nextCaret != null) {
+        invokeCompletion(indicator.getProject(), indicator.getEditor(), indicator.getParameters().getInvocationCount(), hasModifiers, false, nextCaret);
+      }
+      else {
+        indicator.handleEmptyLookup(true);
+        checkNotSync(indicator, items);
+      }
       return;
     }
 
@@ -866,4 +882,23 @@
       }
     };
   }
+
+  private static void clearCaretMarkers(@NotNull Editor editor) {
+    for (Caret caret : editor.getCaretModel().getAllCarets()) {
+      caret.putUserData(CARET_PROCESSED, null);
+    }
+  }
+
+  private static void markCaretAsProcessed(@NotNull Caret caret) {
+    caret.putUserData(CARET_PROCESSED, Boolean.TRUE);
+  }
+
+  private static Caret getNextCaretToProcess(@NotNull Editor editor) {
+    for (Caret caret : editor.getCaretModel().getAllCarets()) {
+      if (caret.getUserData(CARET_PROCESSED) == null) {
+        return caret;
+      }
+    }
+    return null;
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
index 8560129..0321191 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
@@ -73,7 +73,7 @@
 
   @Override
   protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
-    if (!Registry.is("editor.injected.highlighting.enabled", true)) return;
+    if (!Registry.is("editor.injected.highlighting.enabled")) return;
 
     final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);
 
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
index 9211bea..6ff2421 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
@@ -38,7 +38,7 @@
 
   @Override
   protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
-    if (!Registry.is("wolf.the.problem.solver", true)) return;
+    if (!Registry.is("wolf.the.problem.solver")) return;
     final WolfTheProblemSolver solver = WolfTheProblemSolver.getInstance(myProject);
     if (solver instanceof WolfTheProblemSolverImpl) {
       ((WolfTheProblemSolverImpl)solver).startCheckingIfVincentSolvedProblemsYet(progress, this);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index c27ce40..05a1e01 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -261,10 +261,20 @@
   }
 
   public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus) {
-    showJavaDocInfo(editor, file, requestFocus, true);
+    showJavaDocInfo(editor, file, requestFocus, null);
   }
 
-  private void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus, final boolean autoupdate) {
+  public void showJavaDocInfo(final Editor editor,
+                              @Nullable final PsiFile file,
+                              boolean requestFocus,
+                              final Runnable closeCallback) {
+    showJavaDocInfo(editor, file, requestFocus, true, closeCallback);
+  }
+
+  private void showJavaDocInfo(final Editor editor,
+                               @Nullable final PsiFile file,
+                               boolean requestFocus,
+                               final boolean autoupdate, @Nullable final Runnable closeCallback) {
     myEditor = editor;
     final Project project = getProject(file);
     PsiDocumentManager.getInstance(project).commitAllDocuments();
@@ -314,7 +324,7 @@
           return;
         }
         if (lookupIteObject instanceof PsiElement) {
-          doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate);
+          doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate, closeCallback);
           return;
         }
 
@@ -337,12 +347,12 @@
           }
         }
         else {
-          doShowJavaDocInfo(element, false, this, originalElement, autoupdate);
+          doShowJavaDocInfo(element, false, this, originalElement, autoupdate, closeCallback);
         }
       }
     };
 
-    doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate);
+    doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate, closeCallback);
   }
 
   public PsiElement findTargetElement(Editor editor, PsiFile file) {
@@ -969,7 +979,7 @@
   
   @Override
   protected void doUpdateComponent(Editor editor, PsiFile psiFile) {
-    showJavaDocInfo(editor, psiFile, false, true);
+    showJavaDocInfo(editor, psiFile, false, true, null);
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
index 2a46c08..b738baf 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
@@ -19,12 +19,12 @@
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
 import com.intellij.openapi.editor.actions.CopyAction;
 import com.intellij.openapi.editor.actions.EditorActionUtil;
 import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.EditorCopyPasteHelperImpl;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.ide.CopyPasteManager;
 import com.intellij.openapi.project.Project;
@@ -92,7 +92,7 @@
     }
 
     String text = editor.getCaretModel().supportsMultipleCarets()
-                  ? CopyPasteSupport.getSelectedTextForClipboard(editor, transferableDatas)
+                  ? EditorCopyPasteHelperImpl.getSelectedTextForClipboard(editor, transferableDatas)
                   : selectionModel.getSelectedText();
     String rawText = TextBlockTransferable.convertLineSeparators(text, "\n", transferableDatas);
     String escapedText = null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
index 345cb80..17916e0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
@@ -17,15 +17,22 @@
 
 import com.intellij.codeInsight.CodeInsightSettings;
 import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.formatting.*;
+import com.intellij.lang.LanguageFormatting;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
 import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
 import com.intellij.util.text.CharArrayUtil;
 import org.jetbrains.annotations.NotNull;
@@ -36,40 +43,75 @@
 public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
   private static final Logger LOG = Logger.getInstance(IndentingBackspaceHandler.class);
 
+  private boolean isApplicable;
   private boolean caretWasAtLineStart;
+  private String precalculatedSpacing;
 
   @Override
   public void beforeCharDeleted(char c, PsiFile file, Editor editor) {
-    caretWasAtLineStart = editor.getCaretModel().getLogicalPosition().column == 0;
+    if (CodeInsightSettings.getInstance().SMART_BACKSPACE != CodeInsightSettings.AUTOINDENT || !StringUtil.isWhiteSpace(c)) {
+      isApplicable = false;
+      return;
+    }
+    LanguageCodeStyleSettingsProvider codeStyleSettingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(file.getLanguage());
+    if (codeStyleSettingsProvider != null && codeStyleSettingsProvider.isIndentBasedLanguageSemantics()) {
+      isApplicable = false;
+      return;
+    }
+    Document document = editor.getDocument();
+    CharSequence charSequence = document.getCharsSequence();
+    CaretModel caretModel = editor.getCaretModel();
+    int caretOffset = caretModel.getOffset();
+    LogicalPosition pos = caretModel.getLogicalPosition();
+    isApplicable = true;
+    caretWasAtLineStart = pos.column == 0;
+    precalculatedSpacing = null;
+    if (caretWasAtLineStart && pos.line > 0 && caretOffset < charSequence.length() && !StringUtil.isWhiteSpace(charSequence.charAt(caretOffset))) {
+      int prevLineEnd = document.getLineEndOffset(pos.line - 1);
+      if (prevLineEnd > 0 && !StringUtil.isWhiteSpace(charSequence.charAt(prevLineEnd - 1))) {
+        PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
+        precalculatedSpacing = getSpacing(file, caretOffset);
+      }
+    }
   }
 
   @Override
   public boolean charDeleted(char c, PsiFile file, Editor editor) {
-    if (CodeInsightSettings.getInstance().SMART_BACKSPACE != CodeInsightSettings.AUTOINDENT || !StringUtil.isWhiteSpace(c)) {
-      return false;
-    }
-    LanguageCodeStyleSettingsProvider codeStyleSettingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(file.getLanguage());
-    if (codeStyleSettingsProvider != null && codeStyleSettingsProvider.isIndentBasedLanguageSemantics()) {
+    if (!isApplicable) {
       return false;
     }
 
+    Project project = file.getProject();
     Document document = editor.getDocument();
+    CaretModel caretModel = editor.getCaretModel();
 
-    int caretOffset = editor.getCaretModel().getOffset();
+    int caretOffset = caretModel.getOffset();
     int offset = CharArrayUtil.shiftForward(document.getCharsSequence(), caretOffset, " \t");
     int beforeWhitespaceOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), offset - 1, " \t") + 1;
-    LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : editor.getCaretModel().getLogicalPosition();
+    LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : caretModel.getLogicalPosition();
     int lineStartOffset = document.getLineStartOffset(logicalPosition.line);
     if (lineStartOffset < beforeWhitespaceOffset) {
-      if (caretWasAtLineStart && beforeWhitespaceOffset < offset) {
-        document.deleteString(beforeWhitespaceOffset, offset);
-        return true;
+      if (caretWasAtLineStart && beforeWhitespaceOffset <= offset) {
+        String spacing;
+        if (precalculatedSpacing == null) {
+          PsiDocumentManager.getInstance(project).commitDocument(document);
+          spacing = getSpacing(file, offset);
+        }
+        else {
+          spacing = precalculatedSpacing;
+        }
+        if (beforeWhitespaceOffset < offset || !spacing.isEmpty()) {
+          document.replaceString(beforeWhitespaceOffset, offset, spacing);
+          caretModel.moveToOffset(beforeWhitespaceOffset + spacing.length());
+          return true;
+        }
       }
       return false;
     }
 
-    CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(editor.getProject());
-    String indent = codeStyleFacade.getLineIndent(document, lineStartOffset);
+    PsiDocumentManager.getInstance(project).commitDocument(document);
+    CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project);
+    String indent = codeStyleFacade.getLineIndent(document, offset);
     if (indent == null) {
       return false;
     }
@@ -79,7 +121,7 @@
 
     if (logicalPosition.column == targetColumn) {
       if (caretOffset < offset) {
-        editor.getCaretModel().moveToLogicalPosition(logicalPosition);
+        caretModel.moveToLogicalPosition(logicalPosition);
         return true;
       }
       return false;
@@ -87,7 +129,7 @@
 
     if (caretWasAtLineStart || logicalPosition.column > targetColumn) {
       document.replaceString(lineStartOffset, offset, indent);
-      editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
+      caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
       return true;
     }
 
@@ -100,12 +142,13 @@
     int targetOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), prevLineEndOffset - 1, " \t") + 1;
 
     if (prevLineStartOffset < targetOffset) {
-      document.deleteString(targetOffset, offset);
-      editor.getCaretModel().moveToOffset(targetOffset);
+      String spacing = getSpacing(file, offset);
+      document.replaceString(targetOffset, offset, spacing);
+      caretModel.moveToOffset(targetOffset + spacing.length());
     }
     else {
       document.replaceString(prevLineStartOffset, offset, indent);
-      editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
+      caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
     }
     return true;
   }
@@ -132,4 +175,15 @@
     }
     return width;
   }
+
+  private static String getSpacing(PsiFile file, int offset) {
+    FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
+    if (builder == null) {
+      return "";
+    }
+    CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
+    FormattingModel model = builder.createModel(file, settings);
+    int spacing = FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
+    return StringUtil.repeatSymbol(' ', spacing);
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
index bb21eac..ba4768f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
@@ -148,14 +148,17 @@
        return;
     }
 
+    final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
+    final Document originalDocument = originalEditor.getDocument();
     originalEditor.getCaretModel().runForEachCaret(new CaretAction() {
       @Override
       public void perform(Caret caret) {
-        PsiDocumentManager.getInstance(project)
-          .doPostponedOperationsAndUnblockDocument(originalEditor.getDocument()); // to clean up after previous caret processing
+        if (psiDocumentManager.isDocumentBlockedByPsi(originalDocument)) {
+          psiDocumentManager.doPostponedOperationsAndUnblockDocument(originalDocument); // to clean up after previous caret processing
+        }
 
         Editor editor = injectedEditorIfCharTypedIsSignificant(charTyped, originalEditor, originalFile);
-        PsiFile file = editor == originalEditor ? originalFile : PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+        PsiFile file = editor == originalEditor ? originalFile : psiDocumentManager.getPsiFile(editor.getDocument());
 
 
         final TypedHandlerDelegate[] delegates = Extensions.getExtensions(TypedHandlerDelegate.EP_NAME);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 3a1f04b..9a71909 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -372,31 +372,34 @@
     checkValid();
 
     CollectionListModel<LookupElement> listModel = getListModel();
+
+    Pair<List<LookupElement>, Integer> pair;
     synchronized (myList) {
-      Pair<List<LookupElement>, Integer> pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
-      List<LookupElement> items = pair.first;
-      Integer toSelect = pair.second;
-      if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
-        LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
-      }
-
-      myOffsets.checkMinPrefixLengthChanges(items, this);
-      List<LookupElement> oldModel = listModel.toList();
-
-      listModel.removeAll();
-      if (!items.isEmpty()) {
-        listModel.add(items);
-      }
-      else {
-        addEmptyItem(listModel);
-      }
-
-      updateListHeight(listModel);
-
-      myList.setSelectedIndex(toSelect);
-      return !ContainerUtil.equalsIdentity(oldModel, items);
+      pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
+    }
+    
+    List<LookupElement> items = pair.first;
+    Integer toSelect = pair.second;
+    if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
+      LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
+      toSelect = 0;
     }
 
+    myOffsets.checkMinPrefixLengthChanges(items, this);
+    List<LookupElement> oldModel = listModel.toList();
+
+    listModel.removeAll();
+    if (!items.isEmpty()) {
+      listModel.add(items);
+    }
+    else {
+      addEmptyItem(listModel);
+    }
+
+    updateListHeight(listModel);
+
+    myList.setSelectedIndex(toSelect);
+    return !ContainerUtil.equalsIdentity(oldModel, items);
   }
 
   private boolean isSelectionVisible() {
@@ -566,7 +569,7 @@
         public void perform(Caret caret) {
           EditorModificationUtil.deleteSelectedText(hostEditor);
           final int caretOffset = hostEditor.getCaretModel().getOffset();
-          int lookupStart = caretOffset - prefix;
+          int lookupStart = Math.max(caretOffset - prefix, 0);
 
           int len = hostEditor.getDocument().getTextLength();
           LOG.assertTrue(lookupStart >= 0 && lookupStart <= len,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
index 3c0e84a..3617c94 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
@@ -19,30 +19,46 @@
 import com.intellij.ide.util.DefaultPsiElementCellRenderer;
 import com.intellij.ide.util.EditSourceUtil;
 import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.navigation.GotoRelatedItem;
+import com.intellij.navigation.GotoRelatedProvider;
 import com.intellij.navigation.NavigationItem;
+import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.markup.HighlighterTargetArea;
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
 import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.pom.Navigatable;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.impl.ElementBase;
 import com.intellij.psi.search.PsiElementProcessor;
-import com.intellij.ui.JBListWithHintProvider;
+import com.intellij.ui.*;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.ui.popup.list.PopupListElementRenderer;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.*;
+import java.util.List;
 
 /**
  * @author ven
@@ -220,4 +236,242 @@
     }
     return attributes;
   }
+
+  @NotNull
+  public static JBPopup getRelatedItemsPopup(final List<? extends GotoRelatedItem> items, String title) {
+    Object[] elements = new Object[items.size()];
+    //todo[nik] move presentation logic to GotoRelatedItem class
+    final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
+    for (int i = 0; i < items.size(); i++) {
+      GotoRelatedItem item = items.get(i);
+      elements[i] = item.getElement() != null ? item.getElement() : item;
+      itemsMap.put(item.getElement(), item);
+    }
+
+    return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
+      @Override
+      public boolean process(Object element) {
+        if (element instanceof PsiElement) {
+          //noinspection SuspiciousMethodCalls
+          itemsMap.get(element).navigate();
+        }
+        else {
+          ((GotoRelatedItem)element).navigate();
+        }
+        return true;
+      }
+    }
+    );
+  }
+
+  private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
+                                           final String title, final Processor<Object> processor) {
+
+    final Ref<Boolean> hasMnemonic = Ref.create(false);
+    final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
+      {
+        setFocusBorderEnabled(false);
+      }
+
+      @Override
+      public String getElementText(PsiElement element) {
+        String customName = itemsMap.get(element).getCustomName();
+        return (customName != null ? customName : super.getElementText(element));
+      }
+
+      @Override
+      protected Icon getIcon(PsiElement element) {
+        Icon customIcon = itemsMap.get(element).getCustomIcon();
+        return customIcon != null ? customIcon : super.getIcon(element);
+      }
+
+      @Override
+      public String getContainerText(PsiElement element, String name) {
+        String customContainerName = itemsMap.get(element).getCustomContainerName();
+
+        if (customContainerName != null) {
+          return customContainerName;
+        }
+        PsiFile file = element.getContainingFile();
+        return file != null && !getElementText(element).equals(file.getName())
+               ? "(" + file.getName() + ")"
+               : null;
+      }
+
+      @Override
+      protected DefaultListCellRenderer getRightCellRenderer(Object value) {
+        return null;
+      }
+
+      @Override
+      protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
+                                                           JList list,
+                                                           Object value,
+                                                           int index,
+                                                           boolean selected,
+                                                           boolean hasFocus) {
+        final GotoRelatedItem item = (GotoRelatedItem)value;
+        Color color = list.getForeground();
+        final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
+        final String name = item.getCustomName();
+        if (name == null) return false;
+        renderer.append(name, nameAttributes);
+        renderer.setIcon(item.getCustomIcon());
+        return true;
+      }
+
+      @Override
+      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+        if (!hasMnemonic.get()) return component;
+
+        final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
+        final int mnemonic = getMnemonic(value, itemsMap);
+        final JLabel label = new JLabel("");
+        if (mnemonic != -1) {
+          label.setText(mnemonic + ".");
+          label.setDisplayedMnemonicIndex(0);
+        }
+        label.setPreferredSize(new JLabel("8.").getPreferredSize());
+
+        final JComponent leftRenderer = (JComponent)component.getComponents()[0];
+        component.remove(leftRenderer);
+        panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
+        panelWithMnemonic.setBackground(leftRenderer.getBackground());
+        label.setBackground(leftRenderer.getBackground());
+        panelWithMnemonic.add(label, BorderLayout.WEST);
+        panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
+        component.add(panelWithMnemonic);
+        return component;
+      }
+    };
+    final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
+      @Override
+      public boolean isSpeedSearchEnabled() {
+        return true;
+      }
+
+      @Override
+      public String getIndexedString(Object value) {
+        if (value instanceof GotoRelatedItem) {
+          //noinspection ConstantConditions
+          return ((GotoRelatedItem)value).getCustomName();
+        }
+        final PsiElement element = (PsiElement)value;
+        return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
+      }
+
+      @Override
+      public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
+        processor.process(selectedValue);
+        return super.onChosen(selectedValue, finalChoice);
+      }
+    }) {
+    };
+    popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
+      Map<Object, String> separators = new HashMap<Object, String>();
+      {
+        final ListModel model = popup.getList().getModel();
+        String current = null;
+        boolean hasTitle = false;
+        for (int i = 0; i < model.getSize(); i++) {
+          final Object element = model.getElementAt(i);
+          final GotoRelatedItem item = itemsMap.get(element);
+          if (item != null && !StringUtil.equals(current, item.getGroup())) {
+            current = item.getGroup();
+            separators.put(element, current);
+            if (!hasTitle && !StringUtil.isEmpty(current)) {
+              hasTitle = true;
+            }
+          }
+        }
+
+        if (!hasTitle) {
+          separators.remove(model.getElementAt(0));
+        }
+      }
+      @Override
+      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+        final String separator = separators.get(value);
+
+        if (separator != null) {
+          JPanel panel = new JPanel(new BorderLayout());
+          panel.add(component, BorderLayout.CENTER);
+          final SeparatorWithText sep = new SeparatorWithText() {
+            @Override
+            protected void paintComponent(Graphics g) {
+              g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
+              g.fillRect(0,0,getWidth(), getHeight());
+              super.paintComponent(g);
+            }
+          };
+          sep.setCaption(separator);
+          panel.add(sep, BorderLayout.NORTH);
+          return panel;
+        }
+        return component;
+      }
+    });
+
+    popup.setMinimumSize(new Dimension(200, -1));
+
+    for (Object item : elements) {
+      final int mnemonic = getMnemonic(item, itemsMap);
+      if (mnemonic != -1) {
+        final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
+        popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
+        popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
+        hasMnemonic.set(true);
+      }
+    }
+    return popup;
+  }
+
+  private static Action createNumberAction(final int mnemonic,
+                                           final ListPopupImpl listPopup,
+                                           final Map<PsiElement, GotoRelatedItem> itemsMap,
+                                           final Processor<Object> processor) {
+      return new AbstractAction() {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+          for (final Object item : listPopup.getListStep().getValues()) {
+            if (getMnemonic(item, itemsMap) == mnemonic) {
+              listPopup.setFinalRunnable(new Runnable() {
+                @Override
+                public void run() {
+                  processor.process(item);
+                }
+              });
+              listPopup.closeOk(null);
+            }
+          }
+        }
+      };
+    }
+
+  private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
+    return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
+  }
+
+  @NotNull
+  public static List<GotoRelatedItem> collectRelatedItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
+    Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
+    for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
+      items.addAll(provider.getItems(contextElement));
+      if (dataContext != null) {
+        items.addAll(provider.getItems(dataContext));
+      }
+    }
+    GotoRelatedItem[] result = items.toArray(new GotoRelatedItem[items.size()]);
+    Arrays.sort(result, new Comparator<GotoRelatedItem>() {
+      @Override
+      public int compare(GotoRelatedItem i1, GotoRelatedItem i2) {
+        String o1 = i1.getGroup();
+        String o2 = i2.getGroup();
+        return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
+      }
+    });
+    return Arrays.asList(result);
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
index eeb5e04..4ea365f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
@@ -44,6 +44,11 @@
   }
 
   @Override
+  public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+    if (myDelegate != null) myDelegate.weHaveGotNonIgnorableProblems(virtualFile, problems);
+  }
+
+  @Override
   public boolean hasProblemFilesBeneath(@NotNull final Condition<VirtualFile> condition) {
     return false;
   }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
index 45b4532..fab185e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
@@ -413,6 +413,12 @@
   public void weHaveGotProblems(@NotNull final VirtualFile virtualFile, @NotNull List<Problem> problems) {
     if (problems.isEmpty()) return;
     if (!isToBeHighlighted(virtualFile)) return;
+    weHaveGotNonIgnorableProblems(virtualFile, problems);
+  }
+
+  @Override
+  public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+    if (problems.isEmpty()) return;
     boolean fireListener = false;
     synchronized (myProblems) {
       ProblemFileInfo storedProblems = myProblems.get(virtualFile);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
index 516ed91..0c838cd 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
@@ -212,8 +212,11 @@
     if (variableName.equals(TemplateImpl.END)) {
       return new TextResult("");
     }
-    if (myPredefinedVariableValues != null && myPredefinedVariableValues.containsKey(variableName)) {
-      return new TextResult(myPredefinedVariableValues.get(variableName));
+    if (myPredefinedVariableValues != null) {
+      String text = myPredefinedVariableValues.get(variableName);
+      if (text != null) {
+        return new TextResult(text);
+      }
     }
     CharSequence text = myDocument.getCharsSequence();
     int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
new file mode 100644
index 0000000..2989f0d
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+
+import com.intellij.codeInsight.unwrap.ScopeHighlighter;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pass;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.IntroduceTargetChooser;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * See {@link PostfixTemplateExpressionSelector} for description
+ */
+public class ChooserExpressionSelector implements PostfixTemplateExpressionSelector {
+
+  @NotNull
+  private final Condition<PsiElement> myCondition;
+
+  public ChooserExpressionSelector(@NotNull Condition<PsiElement> condition) {
+    myCondition = condition;
+  }
+
+
+  public boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+                               @NotNull PsiElement context,
+                               @NotNull Document copyDocument,
+                               int newOffset) {
+    return !getExpressions(postfixTemplate, context, copyDocument, newOffset).isEmpty();
+  }
+
+  public void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+                             @NotNull PsiElement context,
+                             @NotNull final Editor editor) {
+    List<PsiElement> expressions =
+      getExpressions(postfixTemplate, context, editor.getDocument(), editor.getCaretModel().getOffset());
+
+    if (expressions.isEmpty()) {
+      PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
+    }
+    else if (expressions.size() == 1) {
+      postfixTemplate.expandForChooseExpression(expressions.get(0), editor);
+    }
+    else {
+
+      if (ApplicationManager.getApplication().isUnitTestMode()) {
+        PsiElement item = ContainerUtil.getLastItem(expressions);
+        assert item != null;
+        postfixTemplate.expandForChooseExpression(item, editor);
+        return;
+      }
+
+      IntroduceTargetChooser.showChooser(
+        editor, expressions,
+        new Pass<PsiElement>() {
+          public void pass(@NotNull final PsiElement e) {
+            ApplicationManager.getApplication().runWriteAction(new Runnable() {
+              @Override
+              public void run() {
+                CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() {
+                  public void run() {
+                    postfixTemplate.expandForChooseExpression(e, editor);
+                  }
+                }, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID);
+              }
+            });
+          }
+        },
+        postfixTemplate.getPsiInfo().getRenderer(),
+        "Expressions", 0, ScopeHighlighter.NATURAL_RANGER
+      );
+    }
+  }
+
+  @NotNull
+  private List<PsiElement> getExpressions(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate,
+                                          @NotNull PsiElement context,
+                                          @NotNull Document document,
+                                          final int offset) {
+    List<PsiElement> possibleExpressions = postfixTemplate.getPsiInfo().getExpressions(context, document, offset);
+    List<PsiElement> expressions = ContainerUtil.filter(possibleExpressions,
+                                                        new Condition<PsiElement>() {
+                                                          @Override
+                                                          public boolean value(PsiElement expression) {
+                                                            return expression.getTextRange().getEndOffset() == offset;
+                                                          }
+                                                        }
+    );
+    return ContainerUtil
+      .filter(expressions.isEmpty() ? maybeTopmostExpression(postfixTemplate, context) : expressions, myCondition);
+  }
+
+
+  @NotNull
+  private static List<PsiElement> maybeTopmostExpression(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, @NotNull PsiElement context) {
+    return ContainerUtil.createMaybeSingletonList(postfixTemplate.getPsiInfo().getTopmostExpression(context));
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
deleted file mode 100644
index f6b0ced..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.codeInsight.unwrap.ScopeHighlighter;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Pass;
-import com.intellij.psi.PsiElement;
-import com.intellij.refactoring.IntroduceTargetChooser;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-/**
- * @author ignatov
- */
-public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate {
-
-  @NotNull
-  protected final PostfixTemplatePsiInfoBase myInfo;
-
-  protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example, @NotNull PostfixTemplatePsiInfoBase info) {
-    super(name, example);
-    myInfo = info;
-  }
-
-  protected ExpressionPostfixTemplateWithChooser(@NotNull String name,
-                                                 @NotNull String key,
-                                                 @NotNull String example,
-                                                 @NotNull PostfixTemplatePsiInfoBase info) {
-    super(name, key, example);
-    myInfo = info;
-  }
-
-  @Override
-  public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
-    return !getExpressions(context, copyDocument, newOffset).isEmpty();
-  }
-
-  @Override
-  public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
-    List<PsiElement> expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset());
-
-    if (expressions.isEmpty()) {
-      PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
-    }
-    else if (expressions.size() == 1) {
-      doIt(editor, expressions.get(0));
-    }
-    else {
-
-      if (ApplicationManager.getApplication().isUnitTestMode()) {
-        doIt(editor, expressions.get(expressions.size() - 1));
-        return;
-      }
-
-      IntroduceTargetChooser.showChooser(
-        editor, expressions,
-        new Pass<PsiElement>() {
-          public void pass(@NotNull final PsiElement e) {
-            ApplicationManager.getApplication().runWriteAction(new Runnable() {
-              @Override
-              public void run() {
-                CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() {
-                  public void run() {
-                    doIt(editor, e);
-                  }
-                }, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID);
-              }
-            });
-          }
-        },
-        myInfo.getRenderer(),
-        "Expressions", 0, ScopeHighlighter.NATURAL_RANGER
-      );
-    }
-  }
-
-  @NotNull
-  protected List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) {
-    List<PsiElement> possibleExpressions = myInfo.getExpressions(context, document, offset);
-    List<PsiElement> expressions = ContainerUtil.filter(possibleExpressions,
-                                                        new Condition<PsiElement>() {
-                                                          @Override
-                                                          public boolean value(PsiElement expression) {
-                                                            return expression.getTextRange().getEndOffset() == offset;
-                                                          }
-                                                        }
-    );
-    return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition());
-  }
-
-  @NotNull
-  @SuppressWarnings("unchecked")
-  protected Condition<PsiElement> getTypeCondition() {
-    return Condition.TRUE;
-  }
-
-  @NotNull
-  private List<PsiElement> maybeTopmostExpression(@NotNull PsiElement context) {
-    return ContainerUtil.createMaybeSingletonList(myInfo.getTopmostExpression(context));
-  }
-
-  protected abstract void doIt(@NotNull Editor editor, @NotNull PsiElement expression);
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
index 9c1d9c6..3944cd9 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
@@ -16,26 +16,34 @@
 package com.intellij.codeInsight.template.postfix.templates;
 
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
 
-public class NotPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
 
-  public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfoBase info) {
-    super("not", "!expr", info);
+public class NotPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+  public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info, @NotNull Condition<PsiElement> typeChecker) {
+    super("not", "!expr", info, selectorWithChooser(typeChecker));
   }
 
+  public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info) {
+    super("not", "!expr", info, selectorWithChooser());
+  }
 
   public NotPostfixTemplate(@NotNull String name,
                             @NotNull String key,
                             @NotNull String example,
-                            @NotNull PostfixTemplatePsiInfoBase info) {
-    super(name, key, example, info);
+                            @NotNull PostfixTemplatePsiInfo info,
+                            @NotNull Condition<PsiElement> typeChecker
+  ) {
+    super(name, key, example, info, selectorWithChooser(typeChecker));
   }
 
   @Override
-  protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
-    PsiElement element = myInfo.getNegatedExpression(expression);
+  protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+    PsiElement element = myPsiInfo.getNegatedExpression(expression);
     expression.replace(element);
   }
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
index 9a5d03a..3f1dd11 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
@@ -16,16 +16,25 @@
 package com.intellij.codeInsight.template.postfix.templates;
 
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
 
-public class ParenthesizedPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
-  public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfoBase psiInfo) {
-    super("par", "(expr)", psiInfo);
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+
+public class ParenthesizedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+  public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo, Condition<PsiElement> condition) {
+    super("par", "(expr)", psiInfo, selectorWithChooser(condition));
+  }
+
+
+  public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo) {
+    super("par", "(expr)", psiInfo, selectorWithChooser());
   }
 
   @Override
-  protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
-    expression.replace(myInfo.createExpression(expression, "(", ")"));
+  protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+    expression.replace(myPsiInfo.createExpression(expression, "(", ")"));
   }
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
new file mode 100644
index 0000000..6b5d559
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Interface provides method used in {@link com.intellij.codeInsight.template.postfix.templates.PostfixTemplateWithExpressionSelector}
+ *
+ * You should implement the interface if you have non-trivial logic how to determine expression for next processing in postfix template
+ * Otherwise, you can use one of existing simple implementations:
+ *
+ * 1) {@link com.intellij.codeInsight.template.postfix.templates.ChooserExpressionSelector} - The selector get all expression
+ * in the current position and show to user chooser for these expressions.
+ *
+ * 2) {@link com.intellij.codeInsight.template.postfix.templates.TopmostExpressionSelector} - The selector pass to postfix template
+ * top most expression in the current position
+ *
+ *
+ */
+public interface PostfixTemplateExpressionSelector {
+
+  /**
+   * Check that we can select not-null expression(PsiElement) in current context
+   */
+  boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+                        @NotNull PsiElement context,
+                        @NotNull Document copyDocument,
+                        int newOffset);
+
+  /**
+   * Select expression(PsiElement)  and call postfixTemplate.expandForChooseExpression for selected expression
+   */
+  void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+                      @NotNull PsiElement context,
+                      @NotNull final Editor editor);
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
index 8f47167..6664d64 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
@@ -16,25 +16,42 @@
 package com.intellij.codeInsight.template.postfix.templates;
 
 
+import com.intellij.openapi.editor.Document;
 import com.intellij.psi.PsiElement;
+import com.intellij.util.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public interface PostfixTemplatePsiInfo {
+import java.util.List;
+
+public abstract class PostfixTemplatePsiInfo {
 
   @NotNull
-  PsiElement createStatement(@NotNull PsiElement context,
-                             @NotNull String prefix,
-                             @NotNull String suffix);
+  public abstract PsiElement createStatement(@NotNull PsiElement context,
+                                             @NotNull String prefix,
+                                             @NotNull String suffix);
 
   @NotNull
-  PsiElement createExpression(@NotNull PsiElement context,
-                              @NotNull String prefix,
-                              @NotNull String suffix);
+  public abstract PsiElement createExpression(@NotNull PsiElement context,
+                                              @NotNull String prefix,
+                                              @NotNull String suffix);
 
   @Nullable
-  PsiElement getTopmostExpression(@NotNull PsiElement element);
+  public abstract PsiElement getTopmostExpression(@NotNull PsiElement element);
 
   @NotNull
-  PsiElement getNegatedExpression(@NotNull PsiElement element);
+  public abstract PsiElement getNegatedExpression(@NotNull PsiElement element);
+
+  @NotNull
+  public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset);
+
+  @NotNull
+  public Function<PsiElement, String> getRenderer() {
+    return new Function<PsiElement, String>() {
+      @Override
+      public String fun(@NotNull PsiElement element) {
+        return element.getText();
+      }
+    };
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java
deleted file mode 100644
index 7254e65..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.psi.PsiElement;
-import com.intellij.util.Function;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-public abstract class PostfixTemplatePsiInfoBase implements PostfixTemplatePsiInfo {
-
-  @NotNull
-  public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset);
-
-  @NotNull
-  public Function<PsiElement, String> getRenderer() {
-    return new Function<PsiElement, String>() {
-      @Override
-      public String fun(@NotNull PsiElement element) {
-        return element.getText();
-      }
-    };
-  }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
new file mode 100644
index 0000000..d7cfbaf
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost;
+
+public abstract class PostfixTemplateWithExpressionSelector extends PostfixTemplate {
+
+  @NotNull
+  protected final PostfixTemplatePsiInfo myPsiInfo;
+  @NotNull
+  private final PostfixTemplateExpressionSelector mySelector;
+
+  protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+                                                  @NotNull String key,
+                                                  @NotNull String example,
+                                                  @NotNull PostfixTemplatePsiInfo psiInfo,
+                                                  @NotNull PostfixTemplateExpressionSelector selector) {
+    super(name, key, example);
+    myPsiInfo = psiInfo;
+    mySelector = selector;
+  }
+
+
+  protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+                                                  @NotNull String example,
+                                                  @NotNull PostfixTemplatePsiInfo psiInfo,
+                                                  @NotNull PostfixTemplateExpressionSelector selector) {
+    super(name, example);
+    myPsiInfo = psiInfo;
+    mySelector = selector;
+  }
+
+  protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+                                                  @NotNull String example,
+                                                  @NotNull PostfixTemplatePsiInfo psiInfo,
+                                                  @NotNull Condition<PsiElement> typeChecker) {
+    this(name, example, psiInfo, selectorTopmost(typeChecker));
+  }
+
+  protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+                                                  @NotNull String example,
+                                                  @NotNull PostfixTemplatePsiInfo psiInfo) {
+    this(name, example, psiInfo, selectorTopmost());
+  }
+
+
+  @Override
+  public final boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+    return mySelector.hasExpression(this, context, copyDocument, newOffset);
+  }
+
+  @Override
+  public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+    mySelector.expandTemplate(this, context, editor);
+  }
+
+  protected abstract void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor);
+
+  @NotNull
+  PostfixTemplatePsiInfo getPsiInfo() {
+    return myPsiInfo;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
index 877e10b..5ff744e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
@@ -21,6 +21,8 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
 import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -31,6 +33,22 @@
   private PostfixTemplatesUtils() {
   }
 
+  public static PostfixTemplateExpressionSelector selectorWithChooser() {
+    return selectorWithChooser(Conditions.<PsiElement>alwaysTrue());
+  }
+
+  public static PostfixTemplateExpressionSelector selectorTopmost() {
+    return selectorTopmost(Conditions.<PsiElement>alwaysTrue());
+  }
+
+  public static PostfixTemplateExpressionSelector selectorWithChooser(Condition<PsiElement> condition) {
+    return new ChooserExpressionSelector(condition);
+  }
+
+  public static PostfixTemplateExpressionSelector selectorTopmost(Condition<PsiElement> condition) {
+    return new TopmostExpressionSelector(condition);
+  }
+
   @Nullable
   public static TextRange surround(@NotNull Surrounder surrounder,
                                    @NotNull Editor editor,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
index ed1605d..5b5c362 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
@@ -22,7 +22,7 @@
 import org.jetbrains.annotations.NotNull;
 
 
-public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StatementWrapPostfixTemplate extends PostfixTemplateWithExpressionSelector {
 
   @SuppressWarnings("unchecked")
   protected StatementWrapPostfixTemplate(@NotNull String name,
@@ -39,9 +39,7 @@
   }
 
   @Override
-  public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
-    PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
-    assert topmostExpression != null;
+  public void expandForChooseExpression(@NotNull PsiElement topmostExpression, @NotNull Editor editor) {
     PsiElement parent = topmostExpression.getParent();
     PsiElement expression = getWrappedExpression(topmostExpression);
     PsiElement replace = parent.replace(expression);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
index 4d6582f..9f19b20 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
@@ -26,7 +26,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
 
   public StringBasedPostfixTemplate(@NotNull String name,
                                     @NotNull String example,
@@ -36,10 +36,8 @@
   }
 
   @Override
-  public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
-    PsiElement expr = myPsiInfo.getTopmostExpression(context);
-    assert expr != null;
-    Project project = context.getProject();
+  public final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull Editor editor) {
+    Project project = expr.getProject();
     Document document = editor.getDocument();
     PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr;
     document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
index 52ad0c4..29ea4d3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
@@ -40,11 +40,9 @@
 
 
   @Override
-  public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
+  public final void expandForChooseExpression(@NotNull PsiElement context, @NotNull final Editor editor) {
     PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
-    PsiElement expression = getWrappedExpression(topmostExpression);
-    assert topmostExpression != null;
-    PsiElement replace = topmostExpression.replace(expression);
+    PsiElement replace = getReplacedExpression(topmostExpression);
     TextRange range = PostfixTemplatesUtils.surround(getSurrounder(), editor, replace);
 
     if (range != null) {
@@ -52,6 +50,12 @@
     }
   }
 
+  protected PsiElement getReplacedExpression(PsiElement topmostExpression) {
+    PsiElement expression = getWrappedExpression(topmostExpression);
+    assert topmostExpression != null;
+    return topmostExpression.replace(expression);
+  }
+
   public boolean isStatement() {
     return false;
   }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
new file mode 100644
index 0000000..bd6028d
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+
+/**
+ * See {@link PostfixTemplateExpressionSelector} for description
+ */
+public class TopmostExpressionSelector implements PostfixTemplateExpressionSelector {
+
+  @NotNull
+  private final Condition<PsiElement> myCondition;
+
+  public TopmostExpressionSelector(@NotNull Condition<PsiElement> condition) {
+
+    myCondition = condition;
+  }
+
+  @Override
+  public boolean hasExpression(@NotNull PostfixTemplateWithExpressionSelector template,
+                               @NotNull PsiElement context,
+                               @NotNull Document copyDocument,
+                               int newOffset) {
+    PsiElement topmostExpression = template.getPsiInfo().getTopmostExpression(context);
+    return topmostExpression != null && myCondition.value(topmostExpression);
+  }
+
+  @Override
+  public void expandTemplate(@NotNull PostfixTemplateWithExpressionSelector template,
+                             @NotNull PsiElement context,
+                             @NotNull Editor editor) {
+    PostfixTemplatePsiInfo info = template.getPsiInfo();
+    PsiElement expression = info.getTopmostExpression(context);
+    if (expression == null) {
+      return;
+    }
+    template.expandForChooseExpression(expression, editor);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
deleted file mode 100644
index 0d7d424..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class TypedPostfixTemplate extends PostfixTemplate {
-
-  protected final PostfixTemplatePsiInfo myPsiInfo;
-  protected final Condition<PsiElement> myTypeChecker;
-
-  protected TypedPostfixTemplate(@NotNull String name,
-                                 @NotNull String example,
-                                 @NotNull PostfixTemplatePsiInfo psiInfo,
-                                 @NotNull Condition<PsiElement> typeChecker) {
-    super(name, example);
-    this.myPsiInfo = psiInfo;
-    this.myTypeChecker = typeChecker;
-  }
-
-  @Override
-  public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
-    PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
-    return topmostExpression != null && myTypeChecker.value(topmostExpression);
-  }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
index 2c934d7..7ae9488 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
@@ -64,6 +64,8 @@
         @NotNull
         @Override
         protected ContentManager compute() {
+          ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
+          toolWindowManager.registerToolWindow(ToolWindowId.INSPECTION, true, ToolWindowAnchor.BOTTOM, project);
           return ContentFactory.SERVICE.getInstance().createContentManager(new TabbedPaneContentUI(), true, project);
         }
       };
diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
index f19d92f..b27a939 100644
--- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
+++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
@@ -74,7 +74,7 @@
   }
 
   public static void executeConfiguration(Project project,
-                                          DataContext context,
+                                          @Nullable DataContext context,
                                           @Nullable RunnerAndConfigurationSettings configuration,
                                           Executor executor,
                                           ExecutionTarget target,
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
index 6c0bfff..9aab415 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
@@ -45,7 +45,9 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiFileFactory;
 import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.ExceptionUtil;
 import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.io.SafeFileOutputStream;
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 import com.thoughtworks.xstream.io.xml.XppReader;
@@ -56,7 +58,6 @@
 
 import java.awt.event.KeyEvent;
 import java.io.*;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -65,6 +66,8 @@
  */
 public class ConsoleHistoryController {
 
+  private static final int VERSION = 1;
+
   private static final Logger LOG = Logger.getInstance("com.intellij.execution.console.ConsoleHistoryController");
 
   private final LanguageConsoleImpl myConsole;
@@ -394,7 +397,15 @@
         }
       }
       catch (Exception ex) {
-        LOG.error(ex);
+        //noinspection ThrowableResultOfMethodCallIgnored
+        Throwable cause = ExceptionUtil.getRootCause(ex);
+        if (cause instanceof EOFException) {
+          LOG.warn("Failed to load " + myType + " console history from: " + file.getPath(), ex);
+          return false;
+        }
+        else {
+          LOG.error(ex);
+        }
       }
       finally {
         if (xmlReader != null) {
@@ -423,6 +434,7 @@
         }
         serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8);
         saveHistory(serializer);
+        serializer.flush();
       }
       catch (Exception ex) {
         LOG.error(ex);
@@ -439,47 +451,58 @@
     }
 
     @Nullable
-    private String loadHistory(final HierarchicalStreamReader in, final String expectedId) {
+    private String loadHistory(HierarchicalStreamReader in, String expectedId) {
       if (!in.getNodeName().equals("console-history")) return null;
-      final String id = in.getAttribute("id");
+      int version = StringUtil.parseInt(in.getAttribute("version"), 0);
+      String id = in.getAttribute("id");
       if (!expectedId.equals(id)) return null;
-      final ArrayList<String> entries = new ArrayList<String>();
+      List<String> entries = ContainerUtil.newArrayList();
       String consoleContent = null;
       while (in.hasMoreChildren()) {
         in.moveDown();
         if ("history-entry".equals(in.getNodeName())) {
-          entries.add(in.getValue());
+          entries.add(StringUtil.notNullize(in.getValue()));
         }
         else if ("console-content".equals(in.getNodeName())) {
-          consoleContent = in.getValue();
+          consoleContent = StringUtil.notNullize(in.getValue());
         }
         in.moveUp();
       }
       for (ListIterator<String> iterator = entries.listIterator(entries.size()); iterator.hasPrevious(); ) {
-        final String entry = iterator.previous();
+        String entry = iterator.previous();
         getModel().addToHistory(entry);
       }
       return consoleContent;
     }
 
-    private void saveHistory(final XmlSerializer out) throws IOException {
+    private void saveHistory(XmlSerializer out) throws IOException {
       out.startDocument(CharsetToolkit.UTF8, null);
       out.startTag(null, "console-history");
+      out.attribute(null, "version", String.valueOf(VERSION));
       out.attribute(null, "id", myId);
-      for (String s : getModel().getHistory()) {
-        out.startTag(null, "history-entry");
-        out.text(s);
-        out.endTag(null, "history-entry");
+      try {
+        for (String s : getModel().getHistory()) {
+          textTag(out, "history-entry", s);
+        }
+        String current = myContent;
+        if (StringUtil.isNotEmpty(current)) {
+          textTag(out, "console-content", current);
+        }
       }
-      String current = myContent;
-      if (StringUtil.isNotEmpty(current)) {
-        out.startTag(null, "console-content");
-        out.text(current);
-        out.endTag(null, "console-content");
+      finally {
+        out.endTag(null, "console-history");
+        out.endDocument();
       }
-      out.endTag(null, "console-history");
-      out.endDocument();
     }
   }
 
+  private static void textTag(@NotNull XmlSerializer out, @NotNull String tag, @NotNull String text) throws IOException {
+    out.startTag(null, tag);
+    try {
+      out.cdsect(text);
+    }
+    finally {
+      out.endTag(null, tag);
+    }
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
index c760310..87e1323 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
@@ -9,6 +9,7 @@
 import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.execution.ui.ObservableConsoleView;
 import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -34,6 +35,8 @@
   private final S myPrimaryConsoleView;
   @NotNull
   private final T mySecondaryConsoleView;
+  @Nullable
+  private final String myStateStorageKey;
 
   private boolean myPrimary;
   @Nullable
@@ -41,25 +44,46 @@
   @NotNull
   private final SwitchDuplexConsoleViewAction mySwitchConsoleAction;
 
+
   public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView) {
+    this(primaryConsoleView, secondaryConsoleView, null);
+  }
+
+  public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView, @Nullable String stateStorageKey) {
     super(new CardLayout());
     myPrimaryConsoleView = primaryConsoleView;
     mySecondaryConsoleView = secondaryConsoleView;
+    myStateStorageKey = stateStorageKey;
 
     add(myPrimaryConsoleView.getComponent(), PRIMARY_CONSOLE_PANEL);
     add(mySecondaryConsoleView.getComponent(), SECONDARY_CONSOLE_PANEL);
 
-    mySwitchConsoleAction = new SwitchDuplexConsoleViewAction(this);
+    mySwitchConsoleAction = new SwitchDuplexConsoleViewAction();
 
     myPrimary = true;
-    enableConsole(false);
+    enableConsole(getStoredState());
 
     Disposer.register(this, myPrimaryConsoleView);
     Disposer.register(this, mySecondaryConsoleView);
   }
 
-  public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(S primary, T secondary) {
-    return new DuplexConsoleView<S, T>(primary, secondary);
+  public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(@NotNull S primary,
+                                                                                              @NotNull T secondary,
+                                                                                              @Nullable String stateStorageKey) {
+    return new DuplexConsoleView<S, T>(primary, secondary, stateStorageKey);
+  }
+
+  private void setStoredState(boolean primary) {
+    if (myStateStorageKey != null) {
+      PropertiesComponent.getInstance().setValue(myStateStorageKey, String.valueOf(primary));
+    }
+  }
+
+  private boolean getStoredState() {
+    if (myStateStorageKey == null) {
+      return false;
+    }
+    return PropertiesComponent.getInstance().getBoolean(myStateStorageKey, false);
   }
 
   public void enableConsole(boolean primary) {
@@ -215,23 +239,22 @@
     return mySwitchConsoleAction.getTemplatePresentation();
   }
 
-  private static class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
-    private final DuplexConsoleView myConsole;
+  private class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
 
-    public SwitchDuplexConsoleViewAction(final DuplexConsoleView console) {
+    public SwitchDuplexConsoleViewAction() {
       super(ExecutionBundle.message("run.configuration.show.command.line.action.name"), null,
             AllIcons.Debugger.ToolConsole);
-      myConsole = console;
     }
 
     @Override
     public boolean isSelected(final AnActionEvent event) {
-      return !myConsole.isPrimaryConsoleEnabled();
+      return !isPrimaryConsoleEnabled();
     }
 
     @Override
     public void setSelected(final AnActionEvent event, final boolean flag) {
-      myConsole.enableConsole(!flag);
+      enableConsole(!flag);
+      setStoredState(!flag);
       ApplicationManager.getApplication().invokeLater(new Runnable() {
         @Override
         public void run() {
@@ -244,12 +267,12 @@
     public void update(final AnActionEvent event) {
       super.update(event);
       final Presentation presentation = event.getPresentation();
-      final boolean isRunning = myConsole.myProcessHandler != null && !myConsole.myProcessHandler.isProcessTerminated();
+      final boolean isRunning = myProcessHandler != null && !myProcessHandler.isProcessTerminated();
       if (isRunning) {
         presentation.setEnabled(true);
       }
       else {
-        myConsole.enableConsole(true);
+        enableConsole(true);
         presentation.putClientProperty(SELECTED_PROPERTY, false);
         presentation.setEnabled(false);
       }
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
index 9cb57be..1a9afd1 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -670,12 +670,14 @@
     }
   }
 
+  @NotNull
   public Editor getCurrentEditor() {
-    return ObjectUtils.chooseNotNull(myCurrentEditor, myConsoleEditor);
+    return ObjectUtils.notNull(myCurrentEditor, myConsoleEditor);
   }
 
+  @NotNull
   public Language getLanguage() {
-    return myVirtualFile.getLanguage();
+    return ObjectUtils.assertNotNull(myVirtualFile.getLanguage());
   }
 
   public void setLanguage(@NotNull Language language) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
index ae6af9d..edf1352 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
@@ -49,6 +49,8 @@
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.util.*;
 import java.util.List;
 
@@ -345,6 +347,14 @@
       mySettings = settings;
       init();
       myJBList.setSelectedValue(mySelectedSettings, true);
+      myJBList.addMouseListener(new MouseAdapter() {
+        @Override
+        public void mouseClicked(MouseEvent e) {
+          if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() ==2) {
+            doOKAction();
+          }
+        }
+      });
       FontMetrics fontMetrics = myJBList.getFontMetrics(myJBList.getFont());
       int maxWidth = fontMetrics.stringWidth("m") * 30;
       for (RunnerAndConfigurationSettings setting : settings) {
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
index df7f7e1..b4b3cd9 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -15,6 +15,9 @@
  */
 package com.intellij.execution.runners;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.ExecutionHelper;
 import com.intellij.execution.ExecutionManager;
@@ -129,37 +132,29 @@
     registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent());
     registerActionShortcuts(actions, panel);
     panel.updateUI();
+
     showConsole(defaultExecutor, contentDescriptor);
 
     // Run
     myProcessHandler.startNotify();
   }
 
-  private String constructConsoleTitle(final @NotNull String consoleTitle) {
+  protected String constructConsoleTitle(final @NotNull String consoleTitle) {
     if (shouldAddNumberToTitle()) {
-      List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
-        @NotNull
-        @Override
-        public Boolean fun(String dom) {
-          return dom.contains(consoleTitle);
-        }
-      });
+      List<String> activeConsoleNames = getActiveConsoleNames(consoleTitle);
       int max = 0;
-      for (RunContentDescriptor dsc : consoles) {
-        ProcessHandler handler = dsc.getProcessHandler();
-        if (handler != null && !handler.isProcessTerminated()) {
-          if (max == 0) {
-            max = 1;
+      for (String name : activeConsoleNames) {
+        if (max == 0) {
+          max = 1;
+        }
+        try {
+          int num = Integer.parseInt(name.substring(consoleTitle.length() + 1, name.length() - 1));
+          if (num > max) {
+            max = num;
           }
-          try {
-            int num = Integer.parseInt(dsc.getDisplayName().substring(consoleTitle.length() + 1, dsc.getDisplayName().length() - 1));
-            if (num > max) {
-              max = num;
-            }
-          }
-          catch (Exception ignored) {
-            //skip
-          }
+        }
+        catch (Exception ignored) {
+          //skip
         }
       }
       if (max >= 1) {
@@ -178,9 +173,9 @@
     return false;
   }
 
-  protected void showConsole(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
+  protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
     // Show in run toolwindow
-    ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);
+    ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, contentDescriptor);
   }
 
   protected void finishConsole() {
@@ -245,11 +240,13 @@
   public static AnAction createConsoleExecAction(@NotNull LanguageConsoleView console,
                                                  @NotNull ProcessHandler processHandler,
                                                  @NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
-    return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+    return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+                                    consoleExecuteActionHandler);
   }
 
   protected AnAction createConsoleExecAction(@NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
-    return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+    return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+                                    consoleExecuteActionHandler);
   }
 
   @SuppressWarnings("UnusedDeclaration")
@@ -301,4 +298,31 @@
   public ProcessBackedConsoleExecuteActionHandler getConsoleExecuteActionHandler() {
     return myConsoleExecuteActionHandler;
   }
+
+  protected List<String> getActiveConsoleNames(final String consoleTitle) {
+    return getActiveConsolesFromRunToolWindow(consoleTitle);
+  }
+
+  protected List<String> getActiveConsolesFromRunToolWindow(final String consoleTitle) {
+    List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
+      @NotNull
+      @Override
+      public Boolean fun(String dom) {
+        return dom.contains(consoleTitle);
+      }
+    });
+
+    return FluentIterable.from(consoles).filter(new Predicate<RunContentDescriptor>() {
+      @Override
+      public boolean apply(RunContentDescriptor input) {
+        ProcessHandler handler = input.getProcessHandler();
+        return handler != null && !handler.isProcessTerminated();
+      }
+    }).transform(new Function<RunContentDescriptor, String>() {
+      @Override
+      public String apply(RunContentDescriptor input) {
+        return input.getDisplayName();
+      }
+    }).toList();
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
index 5078641..20b29c2 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
@@ -61,6 +61,15 @@
     myDescriptor = descriptor;
     myExecutor = executor;
     // see IDEADEV-698
+
+    if (descriptor.getRestarter() == null) {
+      descriptor.setRestarter(new Runnable() {
+        @Override
+        public void run() {
+          restart();
+        }
+      });
+    }
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
index ab9433e..bb6d206 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
@@ -206,12 +206,6 @@
     final RestartAction restartAction = new RestartAction(myExecutor, myRunner, contentDescriptor, getEnvironment());
     restartAction.registerShortcut(component);
     actionGroup.add(restartAction);
-    contentDescriptor.setRestarter(new Runnable() {
-      @Override
-      public void run() {
-        restartAction.restart();
-      }
-    });
 
     if (myExecutionResult instanceof DefaultExecutionResult) {
       final AnAction[] actions = ((DefaultExecutionResult)myExecutionResult).getRestartActions();
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
index 897d169..821d9db 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
@@ -1271,6 +1271,17 @@
     return null;
   }
 
+  @Nullable
+  public void restoreContent(final String key) {
+    for (AnAction action : myMinimizedViewActions.getChildren(null)) {
+      Content content = ((RestoreViewAction)action).getContent();
+      if (key.equals(content.getUserData(ViewImpl.ID))) {
+        action.actionPerformed(null);
+        return;
+      }
+    }
+  }
+
   public void setToDisposeRemovedContent(final boolean toDispose) {
     myToDisposeRemovedContent = toDispose;
   }
diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
index 8a36638..9613ac0 100644
--- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
+++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
@@ -392,6 +392,9 @@
     if (secondaryActionsAvailable()) {
       actionGroup.addAction(new ToggleInCommentsAction(this)).setAsSecondary(true);
       actionGroup.addAction(new ToggleInLiteralsOnlyAction(this)).setAsSecondary(true);
+      actionGroup.addAction(new ToggleExceptCommentsAction(this)).setAsSecondary(true);
+      actionGroup.addAction(new ToggleExceptLiteralsAction(this)).setAsSecondary(true);
+      actionGroup.addAction(new ToggleExceptCommentsAndLiteralsAction(this)).setAsSecondary(true);
     }
     actionGroup.addAction(new TogglePreserveCaseAction(this));
     actionGroup.addAction(new ToggleSelectionOnlyAction(this));
@@ -473,8 +476,7 @@
     to.setCaseSensitive(from.isCaseSensitive());
     to.setWholeWordsOnly(from.isWholeWordsOnly());
     to.setRegularExpressions(from.isRegularExpressions());
-    to.setInCommentsOnly(from.isInCommentsOnly());
-    to.setInStringLiteralsOnly(from.isInStringLiteralsOnly());
+    to.setSearchContext(from.getSearchContext());
     if (from.isReplaceState()) {
       to.setPreserveCase(from.isPreserveCase());
     }
diff --git a/platform/lang-impl/src/com/intellij/find/FindSettings.java b/platform/lang-impl/src/com/intellij/find/FindSettings.java
index 964670a..d61fd39 100644
--- a/platform/lang-impl/src/com/intellij/find/FindSettings.java
+++ b/platform/lang-impl/src/com/intellij/find/FindSettings.java
@@ -119,4 +119,13 @@
 
   public abstract boolean isInCommentsOnly();
   public abstract void setInCommentsOnly(boolean selected);
+
+  public abstract boolean isExceptStringLiterals();
+  public abstract void setExceptStringLiterals(boolean selected);
+
+  public abstract boolean isExceptComments();
+  public abstract void setExceptComments(boolean selected);
+
+  public abstract boolean isExceptCommentsAndLiterals();
+  public abstract void setExceptCommentsAndLiterals(boolean selected);
 }
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index edc9064..674358a 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java
@@ -321,7 +321,7 @@
 
   public static void searchBack(final Project project, final Editor editor, @Nullable DataContext context) {
     FindManager findManager = FindManager.getInstance(project);
-    if (!findManager.findWasPerformed()) {
+    if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
       new IncrementalFindAction().getHandler().execute(editor, context);
       return;
     }
@@ -363,7 +363,7 @@
 
   public static boolean searchAgain(final Project project, final Editor editor, @Nullable DataContext context) {
     FindManager findManager = FindManager.getInstance(project);
-    if (!findManager.findWasPerformed()) {
+    if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
       new IncrementalFindAction().getHandler().execute(editor, context);
       return false;
     }
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
new file mode 100644
index 0000000..ae60f31
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+  private static final String TEXT = "Except C&omments";
+
+  public ToggleExceptCommentsAction(EditorSearchComponent editorSearchComponent) {
+    super(editorSearchComponent, TEXT);
+  }
+
+  @Override
+  public boolean isSelected(AnActionEvent e) {
+    return getEditorSearchComponent().getFindModel().isExceptComments();
+  }
+
+  @Override
+  public void setSelected(AnActionEvent e, boolean state) {
+    getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS : FindModel.SearchContext.ANY);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
new file mode 100644
index 0000000..d3ff101
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAndLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+  private static final String TEXT = "Except Comments and Li&terals";
+
+  public ToggleExceptCommentsAndLiteralsAction(EditorSearchComponent editorSearchComponent) {
+    super(editorSearchComponent, TEXT);
+  }
+
+  @Override
+  public boolean isSelected(AnActionEvent e) {
+    return getEditorSearchComponent().getFindModel().isExceptCommentsAndStringLiterals();
+  }
+
+  @Override
+  public void setSelected(AnActionEvent e, boolean state) {
+    getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS : FindModel.SearchContext.ANY);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
new file mode 100644
index 0000000..4b7f09c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+  private static final String TEXT = "Except L&iterals";
+
+  public ToggleExceptLiteralsAction(EditorSearchComponent editorSearchComponent) {
+    super(editorSearchComponent, TEXT);
+  }
+
+  @Override
+  public boolean isSelected(AnActionEvent e) {
+    return getEditorSearchComponent().getFindModel().isExceptStringLiterals();
+  }
+
+  @Override
+  public void setSelected(AnActionEvent e, boolean state) {
+    getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_STRING_LITERALS : FindModel.SearchContext.ANY);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
index e6cae36..4d9d5ad 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
@@ -18,8 +18,6 @@
 
   @Override
   public void setSelected(AnActionEvent e, boolean state) {
-    FindModel findModel = getEditorSearchComponent().getFindModel();
-    findModel.setInCommentsOnly(state);
-    if (state) findModel.setInStringLiteralsOnly(false);
+    getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_COMMENTS : FindModel.SearchContext.ANY);
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
index c4d47e0..d8fc5d5 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
@@ -18,8 +18,6 @@
 
   @Override
   public void setSelected(AnActionEvent e, boolean state) {
-    FindModel findModel = getEditorSearchComponent().getFindModel();
-    findModel.setInStringLiteralsOnly(state);
-    if (state) findModel.setInCommentsOnly(false);
+    getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_STRING_LITERALS : FindModel.SearchContext.ANY);
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
index 7bc0e0c..d7f7665 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
@@ -25,6 +25,7 @@
 import com.intellij.find.replaceInProject.ReplaceInProjectManager;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
@@ -71,8 +72,14 @@
     findModel.setOpenInNewTab(toOpenInNewTab[0]);
     FindInProjectUtil.setDirectoryName(findModel, dataContext);
 
-    Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
-    FindUtil.initStringToFindWithSelection(findModel, editor);
+    String text = PlatformDataKeys.PREDEFINED_TEXT.getData(dataContext);
+    if (text != null) {
+      FindModel.initStringToFindNoMultiline(findModel, text);
+    }
+    else {
+      Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+      FindUtil.initStringToFindWithSelection(findModel, editor);
+    }
 
     findManager.showFindDialog(findModel, new Runnable() {
       @Override
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
index fe47fb8..3315eac 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
@@ -16,8 +16,8 @@
 
 package com.intellij.find.findUsages;
 
+import com.intellij.lang.HelpID;
 import com.intellij.lang.findUsages.DescriptiveNameUtil;
-import com.intellij.openapi.help.HelpManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
@@ -26,7 +26,9 @@
 import com.intellij.ui.SimpleColoredComponent;
 import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.usageView.UsageViewUtil;
+import com.intellij.util.ObjectUtils;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 
@@ -35,6 +37,7 @@
  */
 public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
   @NotNull protected final PsiElement myPsiElement;
+  @Nullable private final String myHelpId;
 
   public CommonFindUsagesDialog(@NotNull PsiElement element,
                                 @NotNull Project project,
@@ -46,6 +49,7 @@
     super(project, findUsagesOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, isTextSearch(element, isSingleFile, handler),
           !isSingleFile && !element.getManager().isInProject(element));
     myPsiElement = element;
+    myHelpId = ObjectUtils.chooseNotNull(handler.getHelpId(), HelpID.FIND_OTHER_USAGES);
     init();
   }
 
@@ -71,8 +75,9 @@
     coloredComponent.append(DescriptiveNameUtil.getDescriptiveName(myPsiElement), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
   }
 
+  @Nullable
   @Override
-  protected void doHelpAction() {
-    HelpManager.getInstance().invokeHelp(FindUsagesManager.getHelpID(myPsiElement));
+  protected String getHelpId() {
+    return myHelpId;
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
index a9291cf..b0dcc45 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
@@ -83,6 +83,11 @@
     return PsiElement.EMPTY_ARRAY;
   }
 
+  @Nullable
+  protected String getHelpId() {
+    return FindUsagesManager.getHelpID(myPsiElement);
+  }
+
   @NotNull
   public static FindUsagesOptions createFindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) {
     FindUsagesOptions findUsagesOptions = new FindUsagesOptions(project, dataContext);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index b6a6152..c25456d 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -35,7 +35,6 @@
 import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.*;
-import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
@@ -50,8 +49,6 @@
 import com.intellij.ui.EditorTextField;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.ui.StateRestoringCheckBox;
-import com.intellij.ui.components.labels.LinkLabel;
-import com.intellij.ui.components.labels.LinkListener;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.Consumer;
 import com.intellij.util.ui.UIUtil;
@@ -60,7 +57,6 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.text.BadLocationException;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.Arrays;
@@ -78,8 +74,7 @@
   private StateRestoringCheckBox myCbCaseSensitive;
   private StateRestoringCheckBox myCbPreserveCase;
   private StateRestoringCheckBox myCbWholeWordsOnly;
-  private StateRestoringCheckBox myCbInCommentsOnly;
-  private StateRestoringCheckBox myCbInStringLiteralsOnly;
+  private ComboBox mySearchContext;
   private StateRestoringCheckBox myCbRegularExpressions;
   private JRadioButton myRbGlobal;
   private JRadioButton myRbSelectedText;
@@ -223,7 +218,7 @@
     myReplacePrompt.setVisible(myModel.isReplaceState());
     myReplaceComboBox.setVisible(myModel.isReplaceState());
     if (myCbToSkipResultsWhenOneUsage != null) {
-      myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+      myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
     }
     myCbPreserveCase.setVisible(myModel.isReplaceState());
   }
@@ -354,9 +349,9 @@
       gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
       optionsPanel.add(createFilterPanel(),gbConstraints);
 
-      myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.usage.checkbox"));
+      myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.occurrence.checkbox"));
       optionsPanel.add(myCbToSkipResultsWhenOneUsage, gbConstraints);
-      myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+      myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
     }
     else {
       if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
@@ -476,6 +471,9 @@
     findSettings.setWholeWordsOnly(myModel.isWholeWordsOnly());
     findSettings.setInStringLiteralsOnly(myModel.isInStringLiteralsOnly());
     findSettings.setInCommentsOnly(myModel.isInCommentsOnly());
+    findSettings.setExceptComments(myModel.isExceptComments());
+    findSettings.setExceptStringLiterals(myModel.isExceptStringLiterals());
+    findSettings.setExceptCommentsAndLiterals(myModel.isExceptCommentsAndStringLiterals());
 
     findSettings.setRegularExpressions(myModel.isRegularExpressions());
     if (!myModel.isMultipleFiles()){
@@ -603,39 +601,26 @@
     regExPanel.setLayout(new BoxLayout(regExPanel, BoxLayout.X_AXIS));
     regExPanel.add(myCbRegularExpressions);
 
-    regExPanel.add(new LinkLabel("[Help]", null, new LinkListener() {
-      @Override
-      public void linkSelected(LinkLabel aSource, Object aLinkData) {
-        try {
-          final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup();
-          helpPopup.showInCenterOf(regExPanel);
-        }
-        catch (BadLocationException e) {
-          LOG.info(e);
-        }
-      }
-    }));
+    regExPanel.add(RegExHelpPopup.createRegExLink("[Help]", regExPanel, LOG));
 
     findOptionsPanel.add(regExPanel);
 
-    myCbInCommentsOnly = createCheckbox(FindBundle.message("find.options.comments.only"));
-    myCbInStringLiteralsOnly = createCheckbox(FindBundle.message("find.options.string.literals.only"));
-    ItemListener itemListener = new ItemListener() {
-      @Override
-      public void itemStateChanged(ItemEvent e) {
-        if (e.getSource() == myCbInCommentsOnly) {
-          if (myCbInCommentsOnly.isSelected()) myCbInStringLiteralsOnly.setSelected(false);
-        } else if (e.getSource() == myCbInStringLiteralsOnly) {
-          if (myCbInStringLiteralsOnly.isSelected()) myCbInCommentsOnly.setSelected(false);
-        }
-      }
-    };
-    myCbInCommentsOnly.addItemListener(itemListener);
-    myCbInStringLiteralsOnly.addItemListener(itemListener);
+    mySearchContext = new ComboBox(new Object[] {FindBundle.message("find.context.anywhere.scope.label", 200),
+      FindBundle.message("find.context.in.comments.scope.label"), FindBundle.message("find.context.in.literals.scope.label"),
+      FindBundle.message("find.context.except.comments.scope.label"),
+      FindBundle.message("find.context.except.literals.scope.label"),
+      FindBundle.message("find.context.except.comments.and.literals.scope.label")});
+    final JPanel searchContextPanel = new JPanel(new BorderLayout());
+    searchContextPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+    JLabel searchContextLabel = new JLabel(FindBundle.message("find.context.combo.label"));
+    searchContextLabel.setLabelFor(mySearchContext);
+    searchContextPanel.add(searchContextLabel, BorderLayout.WEST);
+
+    searchContextPanel.add(mySearchContext, BorderLayout.CENTER);
 
     if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
-      findOptionsPanel.add(myCbInCommentsOnly);
-      findOptionsPanel.add(myCbInStringLiteralsOnly);
+      findOptionsPanel.add(searchContextPanel);
     }
 
     ActionListener actionListener = new ActionListener() {
@@ -1000,9 +985,25 @@
     }
 
     model.setWholeWordsOnly(myCbWholeWordsOnly.isSelected());
-    model.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected());
 
-    model.setInCommentsOnly(myCbInCommentsOnly.isSelected());
+    String selectedSearchContextInUi = (String)mySearchContext.getSelectedItem();
+    FindModel.SearchContext searchContext = FindModel.SearchContext.ANY;
+    if (FindBundle.message("find.context.in.literals.scope.label").equals(selectedSearchContextInUi)) {
+      searchContext = FindModel.SearchContext.IN_STRING_LITERALS;
+    }
+    else if (FindBundle.message("find.context.in.comments.scope.label").equals(selectedSearchContextInUi)) {
+      searchContext = FindModel.SearchContext.IN_COMMENTS;
+    }
+    else if (FindBundle.message("find.context.except.comments.scope.label").equals(selectedSearchContextInUi)) {
+      searchContext = FindModel.SearchContext.EXCEPT_COMMENTS;
+    }
+    else if (FindBundle.message("find.context.except.literals.scope.label").equals(selectedSearchContextInUi)) {
+      searchContext = FindModel.SearchContext.EXCEPT_STRING_LITERALS;
+    } else if (FindBundle.message("find.context.except.comments.and.literals.scope.label").equals(selectedSearchContextInUi)) {
+      searchContext = FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS;
+    }
+
+    model.setSearchContext(searchContext);
 
     model.setRegularExpressions(myCbRegularExpressions.isSelected());
     String stringToFind = getStringToFind();
@@ -1068,8 +1069,14 @@
   private void initByModel() {
     myCbCaseSensitive.setSelected(myModel.isCaseSensitive());
     myCbWholeWordsOnly.setSelected(myModel.isWholeWordsOnly());
-    myCbInStringLiteralsOnly.setSelected(myModel.isInStringLiteralsOnly());
-    myCbInCommentsOnly.setSelected(myModel.isInCommentsOnly());
+    String searchContext = FindBundle.message("find.context.anywhere.scope.label");
+    if (myModel.isInCommentsOnly()) searchContext = FindBundle.message("find.context.in.comments.scope.label");
+    else if (myModel.isInStringLiteralsOnly()) searchContext = FindBundle.message("find.context.in.literals.scope.label");
+    else if (myModel.isExceptStringLiterals()) searchContext = FindBundle.message("find.context.except.literals.scope.label");
+    else if (myModel.isExceptComments()) searchContext = FindBundle.message("find.context.except.comments.scope.label");
+    else if (myModel.isExceptCommentsAndStringLiterals()) searchContext = FindBundle.message("find.context.except.comments.and.literals.scope.label");
+    mySearchContext.setSelectedItem(searchContext);
+
     myCbRegularExpressions.setSelected(myModel.isRegularExpressions());
 
     if (myModel.isMultipleFiles()) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
index 59adf1e..7e9e71d 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.Multiset;
 import com.intellij.find.FindBundle;
 import com.intellij.find.FindModel;
+import com.intellij.find.findInProject.FindInProjectManager;
 import com.intellij.find.ngrams.TrigramIndex;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -182,7 +183,7 @@
 
   private void searchInFiles(@NotNull Collection<PsiFile> psiFiles,
                              @NotNull FindUsagesProcessPresentation processPresentation,
-                             @NotNull Processor<UsageInfo> consumer) {
+                             @NotNull final Processor<UsageInfo> consumer) {
     int i = 0;
     long totalFilesSize = 0;
     int count = 0;
@@ -195,7 +196,8 @@
       long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
       if (fileLength == -1) continue; // Binary or invalid
 
-      if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
+      final boolean skipProjectFile = ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !myFindModel.isSearchInProjectFiles();
+      if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue;
 
       if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
         myLargeFiles.add(psiFile);
@@ -209,7 +211,24 @@
       myProgress.setText(text);
       myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
 
-      int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer);
+      int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, new Processor<UsageInfo>() {
+        @Override
+        public boolean process(UsageInfo info) {
+          return skipProjectFile || consumer.process(info);
+        }
+      });
+
+      if (countInFile > 0 && skipProjectFile) {
+        processPresentation.projectFileUsagesFound(new Runnable() {
+          @Override
+          public void run() {
+            FindModel model = myFindModel.clone();
+            model.setSearchInProjectFiles(true);
+            FindInProjectManager.getInstance(myProject).startFindInProject(model);
+          }
+        });
+        continue;
+      }
 
       count += countInFile;
       if (countInFile > 0) {
@@ -231,6 +250,7 @@
     final GlobalSearchScope globalCustomScope = toGlobal(customScope);
 
     final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+    final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
 
     class EnumContentIterator implements ContentIterator {
       final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();
@@ -238,8 +258,6 @@
       @Override
       public boolean processFile(@NotNull final VirtualFile virtualFile) {
         ApplicationManager.getApplication().runReadAction(new Runnable() {
-          final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
-
           @Override
           public void run() {
             ProgressManager.checkCanceled();
@@ -249,9 +267,6 @@
               return;
             }
 
-            if (virtualFile.getFileType().isBinary()) {
-              return;
-            }
             if (skipIndexed && isCoveredByIndex(virtualFile) &&
                 (fileIndex.isInContent(virtualFile) || fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile))) {
               return;
@@ -261,7 +276,9 @@
             if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) {
               PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement();
               if (sourceFile != null) psiFile = sourceFile;
-              myFiles.add(psiFile);
+              if (!psiFile.getFileType().isBinary()) {
+                myFiles.add(psiFile);
+              }
             }
           }
 
@@ -290,7 +307,9 @@
       for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
         iterator.processFile(file);
       }
-    } else if (customScope instanceof Iterable) {  // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+    }
+    else if (customScope instanceof Iterable) {  // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+      //noinspection unchecked
       for (VirtualFile file : (Iterable<VirtualFile>)customScope) {
         iterator.processFile(file);
       }
@@ -382,16 +401,14 @@
     return myFindModel.isWholeWordsOnly() && text.indexOf('$') < 0 && !StringUtil.getWordsInStringLongestFirst(text).isEmpty();
   }
 
-  private static boolean hasTrigrams(String text) {
-    if (TrigramIndex.ENABLED) {
-      return !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
-        @Override
-        public boolean execute(int value) {
-          return false;
-        }
-      });
-    }
-    return false;
+  private static boolean hasTrigrams(@NotNull String text) {
+    return TrigramIndex.ENABLED &&
+           !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
+             @Override
+             public boolean execute(int value) {
+               return false;
+             }
+           });
   }
 
 
@@ -430,6 +447,7 @@
         final List<VirtualFile> hits = new ArrayList<VirtualFile>();
         final GlobalSearchScope finalScope = scope;
         ApplicationManager.getApplication().runReadAction(new Runnable() {
+          @Override
           public void run() {
             FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits),
                                                          finalScope);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
index e4570b7..23f14c5 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
@@ -47,7 +47,6 @@
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
 import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.ui.content.Content;
@@ -55,7 +54,6 @@
 import com.intellij.usageView.UsageViewManager;
 import com.intellij.usages.ConfigurableUsageTarget;
 import com.intellij.usages.FindUsagesProcessPresentation;
-import com.intellij.usages.UsageView;
 import com.intellij.usages.UsageViewPresentation;
 import com.intellij.util.Function;
 import com.intellij.util.PatternUtil;
@@ -326,7 +324,7 @@
     return processPresentation;
   }
 
-  public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation, TypeSafeDataProvider {
+  public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation {
     @NotNull protected final Project myProject;
     @NotNull protected final FindModel myFindModel;
 
@@ -425,12 +423,5 @@
     public KeyboardShortcut getShortcut() {
       return ActionManager.getInstance().getKeyboardShortcut("FindInPath");
     }
-
-    @Override
-    public void calcData(DataKey key, DataSink sink) {
-      if (key == UsageView.USAGE_SCOPE) {
-        sink.put(UsageView.USAGE_SCOPE, GlobalSearchScope.allScope(myProject));
-      }
-    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index e327ec7..27e2b72 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -27,7 +27,6 @@
 import com.intellij.lang.Language;
 import com.intellij.lang.LanguageParserDefinitions;
 import com.intellij.lang.ParserDefinition;
-import com.intellij.lexer.LayeredLexer;
 import com.intellij.lexer.Lexer;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.actionSystem.ActionManager;
@@ -42,11 +41,6 @@
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
 import com.intellij.openapi.editor.ex.FoldingModelEx;
-import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
-import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.TextEditor;
@@ -58,15 +52,17 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
 import com.intellij.ui.LightweightHint;
 import com.intellij.ui.ReplacePromptDialog;
+import com.intellij.usages.ChunkExtractor;
 import com.intellij.usages.UsageViewManager;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
 import com.intellij.util.Consumer;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Predicate;
 import com.intellij.util.messages.MessageBus;
 import com.intellij.util.text.CharArrayUtil;
 import com.intellij.util.text.StringSearcher;
@@ -96,6 +92,7 @@
 
   private final FindUsagesManager myFindUsagesManager;
   private boolean isFindWasPerformed = false;
+  private boolean isSelectNextOccurrenceWasPerformed = false;
   private Point myReplaceInFilePromptPos = new Point(-1, -1);
   private Point myReplaceInProjectPromptPos = new Point(-1, -1);
   private final FindModel myFindInProjectModel = new FindModel();
@@ -257,7 +254,18 @@
   @Override
   public void setFindWasPerformed() {
     isFindWasPerformed = true;
-    //myFindUsagesManager.clearFindingNextUsageInFile();
+    isSelectNextOccurrenceWasPerformed = false;
+  }
+
+  @Override
+  public boolean selectNextOccurrenceWasPerformed() {
+    return isSelectNextOccurrenceWasPerformed;
+  }
+
+  @Override
+  public void setSelectNextOccurrenceWasPerformed() {
+    isSelectNextOccurrenceWasPerformed = true;
+    isFindWasPerformed = false;
   }
 
   @Override
@@ -270,7 +278,7 @@
     if (myFindNextModel == null) return null;
 
     final JComponent header = editor.getHeaderComponent();
-    if (header instanceof EditorSearchComponent) {
+    if (header instanceof EditorSearchComponent && !isSelectNextOccurrenceWasPerformed) {
       final EditorSearchComponent searchComponent = (EditorSearchComponent)header;
       final String textInField = searchComponent.getTextInField();
       if (!Comparing.equal(textInField, myFindInFileModel.getStringToFind()) && !textInField.isEmpty()) {
@@ -305,19 +313,23 @@
       LOG.debug(model.toString());
     }
 
-    final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
+    return findStringLoop(text, offset, model, file, getFindContextPredicate(model, file, text));
+  }
 
+  private FindResult findStringLoop(CharSequence text, int offset, FindModel model, VirtualFile file, @Nullable Predicate<FindResult> filter) {
+    final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
     while(true) {
       FindResult result = doFindString(text, textArray, offset, model, file);
-
-      if (!model.isWholeWordsOnly()) {
-        return result;
-      }
-      if (!result.isStringFound()){
-        return result;
-      }
-      if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())){
-        return result;
+      if (filter == null || filter.apply(result)) {
+        if (!model.isWholeWordsOnly()) {
+          return result;
+        }
+        if (!result.isStringFound()) {
+          return result;
+        }
+        if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())) {
+          return result;
+        }
       }
 
       offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
@@ -325,6 +337,80 @@
     }
   }
 
+  private class FindExceptCommentsOrLiteralsData implements Predicate<FindResult> {
+    private final VirtualFile myFile;
+    private final FindModel myFindModel;
+    private final TreeMap<Integer, Integer> mySkipRangesSet;
+
+    private FindExceptCommentsOrLiteralsData(VirtualFile file, FindModel model, CharSequence text) {
+      myFile = file;
+      myFindModel = model.clone();
+
+      TreeMap<Integer, Integer> result = new TreeMap<Integer, Integer>();
+
+      if (model.isExceptComments() || model.isExceptCommentsAndStringLiterals()) {
+        addRanges(file, model, text, result, FindModel.SearchContext.IN_COMMENTS);
+      }
+
+      if (model.isExceptStringLiterals() || model.isExceptCommentsAndStringLiterals()) {
+        addRanges(file, model, text, result, FindModel.SearchContext.IN_STRING_LITERALS);
+      }
+
+      mySkipRangesSet = result;
+    }
+
+    private void addRanges(VirtualFile file,
+                           FindModel model,
+                           CharSequence text,
+                           TreeMap<Integer, Integer> result,
+                           FindModel.SearchContext searchContext) {
+      FindModel clonedModel = model.clone();
+      clonedModel.setSearchContext(searchContext);
+      clonedModel.setForward(true);
+      int offset = 0;
+
+      while(true) {
+        FindResult customResult = findStringLoop(text, offset, clonedModel, file, null);
+        if (!customResult.isStringFound()) break;
+        result.put(customResult.getStartOffset(), customResult.getEndOffset());
+        offset = Math.max(customResult.getEndOffset(), offset + 1);  // avoid loop for zero size reg exps matches
+        if (offset >= text.length()) break;
+      }
+    }
+
+    boolean isAcceptableFor(FindModel model, VirtualFile file) {
+      return Comparing.equal(myFile, file) && myFindModel.equals(model);
+    }
+
+    @Override
+    public boolean apply(@Nullable FindResult input) {
+      if (input == null || !input.isStringFound()) return true;
+      NavigableMap<Integer, Integer> map = mySkipRangesSet.headMap(input.getStartOffset(), true);
+      for(Map.Entry<Integer, Integer> e:map.descendingMap().entrySet()) {
+        if (e.getKey() <= input.getStartOffset() && e.getValue() >= input.getEndOffset()) return false;
+        if (e.getValue() <= input.getStartOffset()) break;
+      }
+      return true;
+    }
+  }
+  private static Key<FindExceptCommentsOrLiteralsData> ourExceptCommentsOrLiteralsDataKey = Key.create("except.comments.literals.search.data");
+
+  private Predicate<FindResult> getFindContextPredicate(@NotNull FindModel model, VirtualFile file, CharSequence text) {
+    if (file == null) return null;
+    FindModel.SearchContext context = model.getSearchContext();
+    if( context == FindModel.SearchContext.ANY || context == FindModel.SearchContext.IN_COMMENTS ||
+        context == FindModel.SearchContext.IN_STRING_LITERALS) {
+      return null;
+    }
+
+    FindExceptCommentsOrLiteralsData data = model.getUserData(ourExceptCommentsOrLiteralsDataKey);
+    if (data == null || !data.isAcceptableFor(model, file)) {
+      model.putUserData(ourExceptCommentsOrLiteralsDataKey, data = new FindExceptCommentsOrLiteralsData(file, model, text));
+    }
+
+    return data;
+  }
+
   @Override
   public int showMalformedReplacementPrompt(@NotNull FindModel model, String title, MalformedReplacementStringException exception) {
     return showPromptDialogImpl(model, title, exception);
@@ -408,11 +494,15 @@
     return new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), model.isForward());
   }
 
+  public static void clearPreviousFindData(FindModel model) {
+    model.putUserData(ourCommentsLiteralsSearchDataKey, null);
+    model.putUserData(ourExceptCommentsOrLiteralsDataKey, null);
+  }
+
   private static class CommentsLiteralsSearchData {
     final VirtualFile lastFile;
     int startOffset = 0;
-    final SyntaxHighlighter highlighter;
-    final Lexer highlightingLexer;
+    final SyntaxHighlighterOverEditorHighlighter highlighter;
 
     TokenSet tokensOfInterest;
     final StringSearcher searcher;
@@ -420,8 +510,8 @@
     final Set<Language> relevantLanguages;
     final FindModel model;
 
-    public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages, SyntaxHighlighter highlighter,
-                                      Lexer lexer, TokenSet tokensOfInterest,
+    public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages,
+                                      SyntaxHighlighterOverEditorHighlighter highlighter, TokenSet tokensOfInterest,
                                       StringSearcher searcher, Matcher matcher, FindModel model) {
       this.lastFile = lastFile;
       this.highlighter = highlighter;
@@ -429,12 +519,11 @@
       this.searcher = searcher;
       this.matcher = matcher;
       this.relevantLanguages = relevantLanguages;
-      highlightingLexer = lexer;
       this.model = model;
     }
   }
 
-  public static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
+  private static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
 
   @NotNull
   private FindResult findInCommentsAndLiterals(@NotNull CharSequence text,
@@ -512,38 +601,15 @@
 
       Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null;
       StringSearcher searcher = matcher != null ? null: new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true);
-      LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
-      EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, file);
-      Lexer lexer;
-
-      try {
-        if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
-          lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
-        } else {
-          lexer = highlighter.getHighlightingLexer();
-        }
-      }
-      finally {
-        LayeredLexer.ourDisableLayersFlag.set(null);
-      }
-
-      data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighter, lexer, tokensOfInterest, searcher, matcher, (FindModel)model.clone());
-      lexer.start(text, 0, text.length(), 0);
+      SyntaxHighlighterOverEditorHighlighter highlighterAdapter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file, myProject);
+      data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighterAdapter, tokensOfInterest, searcher, matcher, model.clone());
+      data.highlighter.restart(text);
       model.putUserData(ourCommentsLiteralsSearchDataKey, data);
     }
 
     int initialStartOffset = model.isForward() && data.startOffset < offset ? data.startOffset : 0;
-    final Lexer lexer = data.highlightingLexer;
-    LayeredHighlighterIterator layeredHighlighterIterator = null;
-    if (lexer instanceof LexerEditorHighlighterLexer) {
-      ((LexerEditorHighlighterLexer)lexer).resetPosition(initialStartOffset);
-      HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
-      if (iterator instanceof LayeredHighlighterIterator) {
-        layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
-      }
-    } else {
-      lexer.start(text, initialStartOffset, text.length(), 0);
-    }
+    data.highlighter.resetPosition(initialStartOffset);
+    final Lexer lexer = data.highlighter.getHighlightingLexer();
 
     IElementType tokenType;
     TokenSet tokens = data.tokensOfInterest;
@@ -555,13 +621,11 @@
     while((tokenType = lexer.getTokenType()) != null) {
       if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart();
 
-      final SyntaxHighlighter activeSyntaxHighlighter =
-        layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : data.highlighter;
-      final TextAttributesKey[] keys = activeSyntaxHighlighter.getTokenHighlights(tokenType);
+      final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType);
 
       if (tokens.contains(tokenType) ||
-          (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) ||
-          (model.isInCommentsOnly() && isHighlightedAsDocComment(keys))
+          (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) ||
+          (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys))
         ) {
         int start = lexer.getTokenStart();
         int end = lexer.getTokenEnd();
@@ -634,32 +698,6 @@
     return prevFindResult;
   }
 
-  private static boolean isHighlightedAsDocComment(TextAttributesKey... keys) {
-    for (TextAttributesKey key : keys) {
-      if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || key == SyntaxHighlighterColors.DOC_COMMENT) {
-        return true;
-      }
-      final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
-      if (fallbackAttributeKey != null && isHighlightedAsDocComment(fallbackAttributeKey)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private static boolean isHighlightedAsString(TextAttributesKey... keys) {
-    for (TextAttributesKey key : keys) {
-      if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
-        return true;
-      }
-      final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
-      if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) {
     ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
     if (definition != null) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
index 2c37279..ee8d984 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
@@ -80,7 +80,7 @@
     Long data = myFindModel.getUserData(ourDocumentTimestampKey);
     if (data == null || data != myTimestamp) {
       data = myTimestamp;
-      myFindModel.putUserData(FindManagerImpl.ourCommentsLiteralsSearchDataKey, null);
+      FindManagerImpl.clearPreviousFindData(myFindModel);
     }
     myFindModel.putUserData(ourDocumentTimestampKey, data);
     FindResult result;
@@ -110,7 +110,13 @@
 
     assert result.isStringFound();
 
-    if (myFindModel.isRegularExpressions() || myFindModel.isInCommentsOnly() || myFindModel.isInStringLiteralsOnly()) {
+    if (myFindModel.isRegularExpressions() ||
+        myFindModel.isInCommentsOnly() ||
+        myFindModel.isInStringLiteralsOnly() ||
+        myFindModel.isExceptStringLiterals() ||
+        myFindModel.isExceptCommentsAndStringLiterals() ||
+        myFindModel.isExceptComments()
+      ) {
       myAnchor = SmartPointerManager.getInstance(getProject()).createSmartPsiFileRangePointer(file, TextRange.from(offset, 0));
     }
 
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
index 5fb74f1..c9c8e34 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
@@ -103,6 +103,9 @@
   @SuppressWarnings({"WeakerAccess"}) public boolean WHOLE_WORDS_ONLY = false;
   @SuppressWarnings({"WeakerAccess"}) public boolean COMMENTS_ONLY = false;
   @SuppressWarnings({"WeakerAccess"}) public boolean STRING_LITERALS_ONLY = false;
+  @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS = false;
+  @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS_AND_STRING_LITERALS = false;
+  @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_STRING_LITERALS = false;
   @SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_WHOLE_WORDS_ONLY = false;
   @SuppressWarnings({"WeakerAccess"}) public boolean REGULAR_EXPRESSIONS = false;
   @SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_REGULAR_EXPRESSIONS = false;
@@ -276,8 +279,18 @@
     model.setGlobal(isGlobal());
     model.setRegularExpressions(isRegularExpressions());
     model.setWholeWordsOnly(isWholeWordsOnly());
-    model.setInCommentsOnly(isInCommentsOnly());
-    model.setInStringLiteralsOnly(isInStringLiteralsOnly());
+    FindModel.SearchContext searchContext = isInCommentsOnly() ?
+                                      FindModel.SearchContext.IN_COMMENTS :
+                                      isInStringLiteralsOnly() ?
+                                      FindModel.SearchContext.IN_STRING_LITERALS :
+                                      isExceptComments() ?
+                                      FindModel.SearchContext.EXCEPT_COMMENTS :
+                                      isExceptStringLiterals() ?
+                                      FindModel.SearchContext.EXCEPT_STRING_LITERALS :
+                                      isExceptCommentsAndLiterals() ?
+                                      FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS :
+                                      FindModel.SearchContext.ANY;
+    model.setSearchContext(searchContext);
     model.setWithSubdirectories(isWithSubdirectories());
     model.setFileFilter(FILE_MASK);
 
@@ -384,4 +397,34 @@
   public void setCustomScope(final String SEARCH_SCOPE) {
     this.SEARCH_SCOPE = SEARCH_SCOPE;
   }
+
+  @Override
+  public boolean isExceptComments() {
+    return EXCEPT_COMMENTS;
+  }
+
+  @Override
+  public void setExceptCommentsAndLiterals(boolean selected) {
+    EXCEPT_COMMENTS_AND_STRING_LITERALS = selected;
+  }
+
+  @Override
+  public boolean isExceptCommentsAndLiterals() {
+    return EXCEPT_COMMENTS_AND_STRING_LITERALS;
+  }
+
+  @Override
+  public void setExceptComments(boolean selected) {
+    EXCEPT_COMMENTS = selected;
+  }
+
+  @Override
+  public boolean isExceptStringLiterals() {
+    return EXCEPT_STRING_LITERALS;
+  }
+
+  @Override
+  public void setExceptStringLiterals(boolean selected) {
+    EXCEPT_STRING_LITERALS = selected;
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
index 23dee12..0aace90 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -17,12 +17,19 @@
 
 import com.intellij.codeInsight.hint.HintUtil;
 import com.intellij.ide.BrowserUtil;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
 import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.ui.popup.util.MinimizeButton;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.components.labels.LinkLabel;
+import com.intellij.ui.components.labels.LinkListener;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.HyperlinkEvent;
@@ -331,6 +338,36 @@
     add(myScrollPane, BorderLayout.CENTER);
   }
 
+  @NotNull
+  public static LinkLabel createRegExLink(@NotNull String title, @Nullable final Component owner, @Nullable final Logger logger) {
+    return new LinkLabel(title, null, new LinkListener() {
+      JBPopup helpPopup;
+      @Override
+      public void linkSelected(LinkLabel aSource, Object aLinkData) {
+        try {
+          if (helpPopup != null && !helpPopup.isDisposed() && helpPopup.isVisible()) {
+            return;
+          }
+          helpPopup = createRegExHelpPopup();
+          Disposer.register(helpPopup, new Disposable() {
+            @Override
+            public void dispose() {
+              destroyPopup();
+            }
+          });
+          helpPopup.showInCenterOf(owner);
+        }
+        catch (BadLocationException e) {
+          if (logger != null) logger.info(e);
+        }
+      }
+
+      private void destroyPopup() {
+        helpPopup = null;
+      }
+    });
+  }
+
   @Override
   public Dimension getPreferredSize() {
     return new Dimension(600, 300);
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
index e9e8c13..f5417df 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -116,7 +116,14 @@
                                        TextRange affectedRange);
 
   public abstract void setProgressTask(@NotNull FormattingProgressTask progressIndicator);
-  
+
+  /**
+   * Calculates minimum spacing, allowed by formatting model (in columns) for a block starting at given offset,
+   * relative to its previous sibling block.
+   * Returns zero, if required block cannot be found at provided offset, or spacing cannot be calculated due to some other reason.
+   */
+  public abstract int getSpacingForBlockAtOffset(FormattingModel model, int offset);
+
   public interface IndentInfoStorage {
     void saveIndentInfo(@Nullable IndentInfo info, int startOffset);
 
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
index e136643..7b40b78 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
@@ -25,6 +25,7 @@
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
@@ -109,6 +110,58 @@
   }
 
   @Override
+  public int getSpacingForBlockAtOffset(FormattingModel model, int offset) {
+    Couple<Block> blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset);
+    if (blockWithParent == null) {
+      return 0;
+    }
+    Block parentBlock = blockWithParent.first;
+    Block targetBlock = blockWithParent.second;
+    if (parentBlock == null || targetBlock == null) {
+      return 0;
+    }
+    Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
+    if (prevBlock == null) {
+      return 0;
+    }
+    SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
+    if (spacing == null) {
+      return 0;
+    }
+    return Math.max(spacing.getMinSpaces(), 0);
+  }
+
+  private static Couple<Block> getBlockAtOffset(Block parent, Block block, int offset) {
+    TextRange textRange = block.getTextRange();
+    int startOffset = textRange.getStartOffset();
+    int endOffset = textRange.getEndOffset();
+    if (startOffset == offset) {
+      return Couple.of(parent, block);
+    }
+    if (startOffset > offset || endOffset < offset || block.isLeaf()) {
+      return null;
+    }
+    for (Block subBlock : block.getSubBlocks()) {
+      Couple<Block> result = getBlockAtOffset(block, subBlock, offset);
+      if (result != null) {
+        return result;
+      }
+    }
+    return null;
+  }
+
+  private static Block findPreviousSibling(Block parent, Block block) {
+    Block result = null;
+    for (Block subBlock : parent.getSubBlocks()) {
+      if (subBlock == block) {
+        return result;
+      }
+      result = subBlock;
+    }
+    return null;
+  }
+
+  @Override
   public void format(final FormattingModel model, final CodeStyleSettings settings,
                      final CommonCodeStyleSettings.IndentOptions indentOptions,
                      final CommonCodeStyleSettings.IndentOptions javaIndentOptions,
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
index 88d675b..6239cbb 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -28,17 +28,21 @@
 import com.intellij.openapi.ui.popup.PopupStep;
 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.ui.*;
 import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.border.CustomLineBorder;
 import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.border.EmptyBorder;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -66,15 +70,33 @@
   @NotNull
   public JComponent createComponent() {
     myEnabledDetectionCheckBox = new JCheckBox("Enable framework detection");
+    myEnabledDetectionCheckBox.setBorder(new EmptyBorder(10, 10, 0, 0));
     final JBList excludesList = new JBList(myModel);
-    excludesList.setCellRenderer(new ColoredListCellRenderer() {
+    final ColoredListCellRenderer renderer = new ColoredListCellRenderer() {
+      JPanel panel = new JPanel(new BorderLayout());
+      {
+        panel.setBorder(new EmptyBorder(2, 10, 2, 0));
+        panel.add(this);
+      }
+
       @Override
       protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+        setIconTextGap(4);
         if (value instanceof ExcludeListItem) {
           ((ExcludeListItem)value).renderItem(this);
+          setBorder(new EmptyBorder(0, 10, 0, 0));
         }
       }
-    });
+
+      @Override
+      public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+        super.getListCellRendererComponent(list, value, index, selected, hasFocus);
+        panel.setBackground(UIUtil.getListBackground(selected));
+        return panel;
+      }
+    };
+    renderer.setMyBorder(new EmptyBorder(0,0,0,0));
+    excludesList.setCellRenderer(renderer);
     final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(excludesList)
       .disableUpAction().disableDownAction()
       .setAddAction(new AnActionButtonRunnable() {
@@ -83,9 +105,12 @@
           doAddAction(button);
         }
       });
+    if (Registry.is("ide.new.project.settings")) {
+      decorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
+    }
     myMainPanel = new JPanel(new BorderLayout(0, 5));
     myMainPanel.add(myEnabledDetectionCheckBox, BorderLayout.NORTH);
-    final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), "Exclude from detection:");
+    final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), "   Exclude from detection:");
     myMainPanel.add(excludesComponent);
     myEnabledDetectionCheckBox.addActionListener(new ActionListener() {
       @Override
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
index 6848b03..0dcdde7 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
 
 import com.intellij.ui.ColoredListCellRenderer;
 import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.ui.EmptyIcon;
 
 /**
 * @author nik
@@ -51,6 +52,7 @@
     else {
       renderer.append(myFileUrl, SimpleTextAttributes.ERROR_ATTRIBUTES);
     }
+    renderer.setIcon(EmptyIcon.ICON_16);
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
index 6d734d5..e86caec 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.ide.actions;
 
+import com.intellij.codeInsight.navigation.NavigationUtil;
 import com.intellij.navigation.GotoRelatedItem;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.ui.popup.JBPopup;
@@ -25,22 +26,25 @@
 import java.util.List;
 
 /**
- * @deprecated API compatibility. Utility methods will be moved to NavigationUtil
+ * @deprecated API compatibility. Utility methods moved to NavigationUtil.
+ * todo [neuro] REMOVE-ME when September Ends..
  * @author gregsh
  */
 public class GotoRelatedFileAction {
 
   /**
-   * @deprecated This method will be moved to NavigationUtil
+   * @deprecated
+   * @see com.intellij.codeInsight.navigation.NavigationUtil#getRelatedItemsPopup(java.util.List, String)
    */
   public static JBPopup createPopup(List<? extends GotoRelatedItem> items, final String title) {
-    return GotoRelatedSymbolAction.createPopup(items, title);
+    return NavigationUtil.getRelatedItemsPopup(items, title);
   }
 
   /**
-   * @deprecated This method will be moved to NavigationUtil
+   * @deprecated
+   * @see com.intellij.codeInsight.navigation.NavigationUtil#collectRelatedItems(com.intellij.psi.PsiElement, com.intellij.openapi.actionSystem.DataContext)
    */
   public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
-    return GotoRelatedSymbolAction.getItems(contextElement, dataContext);
+    return NavigationUtil.collectRelatedItems(contextElement, dataContext);
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
index 2870f80..229531b 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
@@ -15,39 +15,19 @@
  */
 package com.intellij.ide.actions;
 
-import com.intellij.ide.util.DefaultPsiElementCellRenderer;
+import com.intellij.codeInsight.navigation.NavigationUtil;
 import com.intellij.navigation.GotoRelatedItem;
-import com.intellij.navigation.GotoRelatedProvider;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.PopupStep;
-import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.JBColor;
-import com.intellij.ui.SeparatorWithText;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.ui.popup.list.ListPopupImpl;
-import com.intellij.ui.popup.list.PopupListElementRenderer;
-import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.*;
 import java.util.List;
 
 /**
@@ -66,210 +46,20 @@
     PsiElement element = getContextElement(e.getDataContext());
     if (element == null) return;
 
-    List<GotoRelatedItem> items = getItems(element, e.getDataContext());
+    List<GotoRelatedItem> items = NavigationUtil.collectRelatedItems(element, e.getDataContext());
     if (items.isEmpty()) return;
 
     if (items.size() == 1 && items.get(0).getElement() != null) {
       items.get(0).navigate();
       return;
     }
-    createPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
-  }
-
-  public static JBPopup createPopup(final List<? extends GotoRelatedItem> items, final String title) {
-    Object[] elements = new Object[items.size()];
-    //todo[nik] move presentation logic to GotoRelatedItem class
-    final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
-    for (int i = 0; i < items.size(); i++) {
-      GotoRelatedItem item = items.get(i);
-      elements[i] = item.getElement() != null ? item.getElement() : item;
-      itemsMap.put(item.getElement(), item);
-    }
-
-    return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
-      @Override
-      public boolean process(Object element) {
-        if (element instanceof PsiElement) {
-          //noinspection SuspiciousMethodCalls
-          itemsMap.get(element).navigate();
-        }
-        else {
-          ((GotoRelatedItem)element).navigate();
-        }
-        return true;
-      }
-    }
-    );
-  }
-
-  private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
-                                           final String title, final Processor<Object> processor) {
-
-    final Ref<Boolean> hasMnemonic = Ref.create(false);
-    final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
-      {
-        setFocusBorderEnabled(false);
-      }
-
-      @Override
-      public String getElementText(PsiElement element) {
-        String customName = itemsMap.get(element).getCustomName();
-        return (customName != null ? customName : super.getElementText(element));
-      }
-
-      @Override
-      protected Icon getIcon(PsiElement element) {
-        Icon customIcon = itemsMap.get(element).getCustomIcon();
-        return customIcon != null ? customIcon : super.getIcon(element);
-      }
-
-      @Override
-      public String getContainerText(PsiElement element, String name) {
-        String customContainerName = itemsMap.get(element).getCustomContainerName();
-
-        if (customContainerName != null) {
-          return customContainerName;
-        }
-        PsiFile file = element.getContainingFile();
-        return file != null && !getElementText(element).equals(file.getName())
-               ? "(" + file.getName() + ")"
-               : null;
-      }
-
-      @Override
-      protected DefaultListCellRenderer getRightCellRenderer(Object value) {
-        return null;
-      }
-
-      @Override
-      protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
-                                                           JList list,
-                                                           Object value,
-                                                           int index,
-                                                           boolean selected,
-                                                           boolean hasFocus) {
-        final GotoRelatedItem item = (GotoRelatedItem)value;
-        Color color = list.getForeground();
-        final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
-        final String name = item.getCustomName();
-        if (name == null) return false;
-        renderer.append(name, nameAttributes);
-        renderer.setIcon(item.getCustomIcon());
-        return true;
-      }
-
-      @Override
-      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-        final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
-        if (!hasMnemonic.get()) return component;
-
-        final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
-        final int mnemonic = getMnemonic(value, itemsMap);
-        final JLabel label = new JLabel("");
-        if (mnemonic != -1) {
-          label.setText(mnemonic + ".");
-          label.setDisplayedMnemonicIndex(0);
-        }
-        label.setPreferredSize(new JLabel("8.").getPreferredSize());
-
-        final JComponent leftRenderer = (JComponent)component.getComponents()[0];
-        component.remove(leftRenderer);
-        panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
-        panelWithMnemonic.setBackground(leftRenderer.getBackground());
-        label.setBackground(leftRenderer.getBackground());
-        panelWithMnemonic.add(label, BorderLayout.WEST);
-        panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
-        component.add(panelWithMnemonic);
-        return component;
-      }
-    };
-    final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
-      @Override
-      public boolean isSpeedSearchEnabled() {
-        return true;
-      }
-
-      @Override
-      public String getIndexedString(Object value) {
-        if (value instanceof GotoRelatedItem) {
-          //noinspection ConstantConditions
-          return ((GotoRelatedItem)value).getCustomName();
-        }
-        final PsiElement element = (PsiElement)value;
-        return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
-      }
-
-      @Override
-      public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
-        processor.process(selectedValue);
-        return super.onChosen(selectedValue, finalChoice);
-      }
-    }) {
-    };
-    popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
-      Map<Object, String> separators = new HashMap<Object, String>();
-      {
-        final ListModel model = popup.getList().getModel();
-        String current = null;
-        boolean hasTitle = false;
-        for (int i = 0; i < model.getSize(); i++) {
-          final Object element = model.getElementAt(i);
-          final GotoRelatedItem item = itemsMap.get(element);
-          if (item != null && !StringUtil.equals(current, item.getGroup())) {
-            current = item.getGroup();
-            separators.put(element, current);
-            if (!hasTitle && !StringUtil.isEmpty(current)) {
-              hasTitle = true;
-            }
-          }
-        }
-
-        if (!hasTitle) {
-          separators.remove(model.getElementAt(0));
-        }
-      }
-      @Override
-      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-        final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
-        final String separator = separators.get(value);
-
-        if (separator != null) {
-          JPanel panel = new JPanel(new BorderLayout());
-          panel.add(component, BorderLayout.CENTER);
-          final SeparatorWithText sep = new SeparatorWithText() {
-            @Override
-            protected void paintComponent(Graphics g) {
-              g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
-              g.fillRect(0,0,getWidth(), getHeight());
-              super.paintComponent(g);
-            }
-          };
-          sep.setCaption(separator);
-          panel.add(sep, BorderLayout.NORTH);
-          return panel;
-        }
-        return component;
-      }
-    });
-
-    popup.setMinimumSize(new Dimension(200, -1));
-
-    for (Object item : elements) {
-      final int mnemonic = getMnemonic(item, itemsMap);
-      if (mnemonic != -1) {
-        final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
-        popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
-        popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
-        hasMnemonic.set(true);
-      }
-    }
-    return popup;
+    NavigationUtil.getRelatedItemsPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
   }
 
   @TestOnly
   @NotNull
   public static List<GotoRelatedItem> getItems(@NotNull PsiFile psiFile, @Nullable Editor editor, @Nullable DataContext dataContext) {
-    return getItems(getContextElement(psiFile, editor), dataContext);
+    return NavigationUtil.collectRelatedItems(getContextElement(psiFile, editor), dataContext);
   }
 
   @Nullable
@@ -294,65 +84,4 @@
     }
     return contextElement;
   }
-
-  @NotNull
-  public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
-    Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
-    for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
-      items.addAll(provider.getItems(contextElement));
-      if (dataContext != null) {
-        items.addAll(provider.getItems(dataContext));
-      }
-    }
-    sortByGroupNames(items);
-    return new ArrayList<GotoRelatedItem>(items);
-  }
-
-  private static void sortByGroupNames(Set<GotoRelatedItem> items) {
-    Map<String, List<GotoRelatedItem>> map = new HashMap<String, List<GotoRelatedItem>>();
-    for (GotoRelatedItem item : items) {
-      final String key = item.getGroup();
-      if (!map.containsKey(key)) {
-        map.put(key, new ArrayList<GotoRelatedItem>());
-      }
-      map.get(key).add(item);
-    }
-    final List<String> keys = new ArrayList<String>(map.keySet());
-    Collections.sort(keys, new Comparator<String>() {
-      @Override
-      public int compare(String o1, String o2) {
-        return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
-      }
-    });
-    items.clear();
-    for (String key : keys) {
-      items.addAll(map.get(key));
-    }
-  }
-
-  private static Action createNumberAction(final int mnemonic,
-                                           final ListPopupImpl listPopup,
-                                           final Map<PsiElement, GotoRelatedItem> itemsMap,
-                                           final Processor<Object> processor) {
-      return new AbstractAction() {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          for (final Object item : listPopup.getListStep().getValues()) {
-            if (getMnemonic(item, itemsMap) == mnemonic) {
-              listPopup.setFinalRunnable(new Runnable() {
-                @Override
-                public void run() {
-                  processor.process(item);
-                }
-              });
-              listPopup.closeOk(null);
-            }
-          }
-        }
-      };
-    }
-
-  private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
-    return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
-  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
index 3e28023..531f3e5 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -49,7 +49,8 @@
         public void run() {
           PsiDocumentManager.getInstance(project).commitAllDocuments();
           IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation();
-          if(FindManager.getInstance(project).findNextUsageInEditor(editor)) {
+          FindManager findManager = FindManager.getInstance(project);
+          if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findNextUsageInEditor(editor)) {
             return;
           }
 
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
index 4783205..5f6e0d9 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -46,7 +46,8 @@
         @Override
         public void run() {
           PsiDocumentManager.getInstance(project).commitAllDocuments();
-          if(FindManager.getInstance(project).findPreviousUsageInEditor(editor)) {
+          FindManager findManager = FindManager.getInstance(project);
+          if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findPreviousUsageInEditor(editor)) {
             return;
           }
           FindUtil.searchBack(project, editor, e.getDataContext());
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
index ae7ee43..d704e73 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -108,11 +108,9 @@
 import javax.swing.event.DocumentEvent;
 import java.awt.*;
 import java.awt.event.*;
-import java.lang.reflect.Field;
 import java.util.*;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * @author Konstantin Bulenkov
@@ -2120,13 +2118,7 @@
 
     private SearchListModel() {
       super();
-      try {
-        final Field field = DefaultListModel.class.getDeclaredField("delegate");
-        field.setAccessible(true);
-        myDelegate = (Vector)field.get(this);
-      }
-      catch (NoSuchFieldException ignore) {}
-      catch (IllegalAccessException ignore) {}
+      myDelegate = ReflectionUtil.getField(DefaultListModel.class, this, Vector.class, "delegate");
     }
 
     int next(int index) {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
index bb80f55..c4708c4 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
@@ -29,6 +29,7 @@
 import com.intellij.ide.projectView.impl.nodes.AbstractModuleNode;
 import com.intellij.ide.projectView.impl.nodes.AbstractProjectNode;
 import com.intellij.ide.projectView.impl.nodes.ModuleGroupNode;
+import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
 import com.intellij.ide.util.treeView.*;
 import com.intellij.injected.editor.VirtualFileWindow;
 import com.intellij.openapi.Disposable;
@@ -54,6 +55,7 @@
 import com.intellij.refactoring.move.MoveHandler;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.ReflectionUtil;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.tree.TreeUtil;
@@ -481,6 +483,27 @@
   }
 
   public PsiDirectory[] getSelectedDirectories() {
+    List<PsiDirectory> directories = ContainerUtil.newArrayList();
+    for (PsiDirectoryNode node : getSelectedNodes(PsiDirectoryNode.class)) {
+      PsiDirectory directory = node.getValue();
+      if (directory != null) {
+        directories.add(directory);
+        Object parentValue = node.getParent().getValue();
+        if (parentValue instanceof PsiDirectory) {
+          while (true) {
+            directory = directory.getParentDirectory();
+            if (directory == null || directory.equals(parentValue)) {
+              break;
+            }
+            directories.add(directory);
+          }
+        }
+      }
+    }
+    if (!directories.isEmpty()) {
+      return directories.toArray(new PsiDirectory[directories.size()]);
+    }
+
     final PsiElement[] elements = getSelectedPSIElements();
     if (elements.length == 1) {
       final PsiElement element = elements[0];
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
index 2aa89ad..2a6c396 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
@@ -65,7 +65,12 @@
 
     @Override
     public void changeListRenamed(final ChangeList list, final String oldName) {
-      setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+      AppUIUtil.invokeOnEdt(new Runnable() {
+        @Override
+        public void run() {
+          setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+        }
+      });
     }
 
     @Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
index f260c73..35f7f65 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
@@ -65,6 +65,7 @@
 import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
 import com.intellij.util.Alarm;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.containers.HashSet;
@@ -83,7 +84,6 @@
 import javax.swing.tree.TreePath;
 import java.awt.*;
 import java.awt.event.*;
-import java.lang.reflect.Field;
 import java.util.*;
 import java.util.List;
 
@@ -1018,22 +1018,13 @@
     public FileStructureTree(Object rootElement, boolean fastExpand) {
       super(new DefaultMutableTreeNode(rootElement));
       if (fastExpand) {
-        boolean newValueIsSet;
-        try {
-          final Field field = JTree.class.getDeclaredField("expandedState");
-          field.setAccessible(true);
-          field.set(this, new Hashtable() {
-            @Override
-            public synchronized Object get(Object key) {
-              return Boolean.TRUE;
-            }
-          });
-          newValueIsSet = true;
-        }
-        catch (Exception e) {
-          newValueIsSet = false;
-        }
-        fast = newValueIsSet;
+        Hashtable hashtable = new Hashtable() {
+          @Override
+          public synchronized Object get(Object key) {
+            return Boolean.TRUE;
+          }
+        };
+        fast = ReflectionUtil.setField(JTree.class, this, Hashtable.class, "expandedState", hashtable);
       }
       else {
         fast = false;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index dcc1429..3e90f23 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -35,6 +35,7 @@
 import com.intellij.openapi.application.ApplicationAdapter;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.fileTypes.UnknownFileType;
@@ -102,6 +103,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public abstract class ChooseByNameBase {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ChooseByNameBase");
   protected final Project myProject;
   protected final ChooseByNameModel myModel;
   protected ChooseByNameItemProvider myProvider;
@@ -133,7 +135,6 @@
 
   private final ListUpdater myListUpdater = new ListUpdater();
 
-  private volatile boolean myListIsUpToDate = false;
   private boolean myDisposedFlag = false;
   private ActionCallback myPostponedOkAction;
 
@@ -278,7 +279,7 @@
       if (PlatformDataKeys.HELP_ID.is(dataId)) {
         return myModel.getHelpId();
       }
-      if (!myListIsUpToDate) {
+      if (myCalcElementsThread != null) {
         return null;
       }
       if (CommonDataKeys.PSI_ELEMENT.is(dataId)) {
@@ -499,7 +500,7 @@
       myTextField.addFocusListener(new FocusAdapter() {
         @Override
         public void focusLost(@NotNull final FocusEvent e) {
-          cancelCalcElementsThread(); // cancel thread as early as possible
+          cancelListUpdater(); // cancel thread as early as possible
           myHideAlarm.addRequest(new Runnable() {
             @Override
             public void run() {
@@ -531,7 +532,7 @@
                 if (queue instanceof IdeEventQueue) {
                   if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) {
                     Component root = SwingUtilities.getRoot(myTextField);
-                    if (root != null) {
+                    if (root != null && root.isShowing()) {
                       root.requestFocus();
                       myTextField.requestFocus();
                       return;
@@ -759,24 +760,29 @@
   }
 
   protected void doClose(final boolean ok) {
-    try {
-      if (checkDisposed()) return;
+    if (checkDisposed()) return;
 
-      if (postponeCloseWhenListReady(ok)) return;
+    if (postponeCloseWhenListReady(ok)) return;
 
-      cancelListUpdater();
-      close(ok);
+    cancelListUpdater();
+    close(ok);
 
-      clearPostponedOkAction(ok);
-    }
-    finally {
-      myListModel.clear();
-      cancelCalcElementsThread();
-    }
+    clearPostponedOkAction(ok);
+    myListModel.clear();
   }
 
   protected void cancelListUpdater() {
-    cancelCalcElementsThread();
+    final CalcElementsThread calcElementsThread = myCalcElementsThread;
+    if (calcElementsThread != null && calcElementsThread.cancel()) {
+      UIUtil.invokeLaterIfNeeded(new Runnable() {
+        @Override
+        public void run() {
+          if (!checkDisposed() && calcElementsThread == myCalcElementsThread) {
+            backgroundCalculationFinished(Collections.emptyList(), 0);
+          }
+        }
+      });
+    }
     myListUpdater.cancelAll();
   }
 
@@ -784,7 +790,7 @@
     if (!isToFixLostTyping()) return false;
 
     final String text = myTextField.getText();
-    if (ok && !myListIsUpToDate && text != null && !text.trim().isEmpty()) {
+    if (ok && myCalcElementsThread != null && text != null && !text.trim().isEmpty()) {
       myPostponedOkAction = new ActionCallback();
       IdeFocusManager.getInstance(myProject).typeAheadUntil(myPostponedOkAction);
       return true;
@@ -885,7 +891,7 @@
     Disposer.register(myTextPopup, new Disposable() {
       @Override
       public void dispose() {
-        cancelCalcElementsThread();
+        cancelListUpdater();
       }
     });
     myTextPopup.show(layeredPane);
@@ -917,8 +923,6 @@
     return layeredPane;
   }
 
-  private final Object myRebuildMutex = new Object();
-
   protected void rebuildList(final int pos,
                              final int delay,
                              @NotNull final ModalityState modalityState,
@@ -928,11 +932,13 @@
       return;
     }
 
-    myListIsUpToDate = false;
     myAlarm.cancelAllRequests();
     myListUpdater.cancelAll();
 
-    cancelCalcElementsThread();
+    final CalcElementsThread calcElementsThread = myCalcElementsThread;
+    if (calcElementsThread != null) {
+      calcElementsThread.cancel();
+    }
 
     final String text = myTextField.getText();
     if (!canShowListForEmptyPattern() &&
@@ -960,24 +966,14 @@
         scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() {
           @Override
           public void consume(Set<?> elements) {
-            synchronized (myRebuildMutex) {
-              ApplicationManager.getApplication().assertIsDispatchThread();
-              if (checkDisposed()) {
-                return;
-              }
+            ApplicationManager.getApplication().assertIsDispatchThread();
+            if (checkDisposed()) {
+              return;
+            }
+            backgroundCalculationFinished(elements, pos);
 
-              myListIsUpToDate = true;
-              setElementsToList(pos, elements);
-              myList.repaint();
-              chosenElementMightChange();
-
-              if (elements.isEmpty()) {
-                myTextFieldPanel.hideHint();
-              }
-
-              if (postRunnable != null) {
-                postRunnable.run();
-              }
+            if (postRunnable != null) {
+              postRunnable.run();
             }
           }
         });
@@ -992,6 +988,17 @@
     }
   }
 
+  private void backgroundCalculationFinished(Collection<?> result, int toSelect) {
+    myCalcElementsThread = null;
+    setElementsToList(toSelect, result);
+    myList.repaint();
+    chosenElementMightChange();
+
+    if (result.isEmpty()) {
+      myTextFieldPanel.hideHint();
+    }
+  }
+
   public void scheduleCalcElements(String text,
                                    boolean checkboxState,
                                    ModalityState modalityState,
@@ -1008,16 +1015,7 @@
     return myShowListAfterCompletionKeyStroke;
   }
 
-  private CalcElementsThread cancelCalcElementsThread() {
-    CalcElementsThread calcElementsThread = myCalcElementsThread;
-    if (calcElementsThread != null) {
-      calcElementsThread.cancel();
-      myCalcElementsThread = null;
-    }
-    return calcElementsThread;
-  }
-
-  private void setElementsToList(int pos, @NotNull Set<?> elements) {
+  private void setElementsToList(int pos, @NotNull Collection<?> elements) {
     myListUpdater.cancelAll();
     if (checkDisposed()) return;
     if (elements.isEmpty()) {
@@ -1202,33 +1200,12 @@
   }
 
   protected List<Object> getChosenElements() {
-
-    List<Object> values = new ArrayList<Object>(Arrays.asList(myList.getSelectedValues()));
-    values.remove(EXTRA_ELEM);
-    values.remove(NON_PREFIX_SEPARATOR);
-
-    if (myListIsUpToDate || !values.isEmpty()) {
-      return values;
-    }
-
-    final String text = myTextField.getText();
-    if (text.length() == 0) return Collections.emptyList();
-    final boolean checkBoxState = myCheckBox.isSelected();
-    final String[] names = ourLoadNamesEachTime ? ensureNamesLoaded(checkBoxState) : getNamesSync(checkBoxState);
-    if (names == null) return Collections.emptyList();
-
-    Object uniqueElement = null;
-
-    for (final String name : names) {
-      if (text.equalsIgnoreCase(name)) {
-        final Object[] elements = myModel.getElementsByName(name, checkBoxState, text);
-        if (elements.length > 1) return Collections.emptyList();
-        if (elements.length == 0) continue;
-        if (uniqueElement != null) return Collections.emptyList();
-        uniqueElement = elements[0];
+    return ContainerUtil.filter(myList.getSelectedValues(), new Condition<Object>() {
+      @Override
+      public boolean value(Object o) {
+        return o != EXTRA_ELEM && o != NON_PREFIX_SEPARATOR;
       }
-    }
-    return uniqueElement == null ? Collections.emptyList() : Collections.singletonList(uniqueElement);
+    });
   }
 
   protected void chosenElementMightChange() {
@@ -1565,6 +1542,7 @@
             @Override
             public void run() {
               if (!myCancelled.isCanceled()) {
+                LOG.assertTrue(myCalcElementsThread == CalcElementsThread.this);
                 myCallback.consume(edt ? filter(elements) : filtered);
               }
             }
@@ -1622,8 +1600,12 @@
       return elementsArray.size() >= myMaximumListSizeLimit;
     }
 
-    private void cancel() {
+    private boolean cancel() {
+      if (myCancelled.isCanceled()) {
+        return false;
+      }
       myCancelled.cancel();
+      return true;
     }
 
   }
@@ -1705,7 +1687,7 @@
         final LinkedHashSet<Object> nonPrefixMatchElementsArray = new LinkedHashSet<Object>();
         hideHint();
         ProgressManager.getInstance().run(new Task.Modal(myProject, prefixPattern, true) {
-          private ChooseByNameBase.CalcElementsThread myCalcElementsThread;
+          private ChooseByNameBase.CalcElementsThread myCalcUsagesThread;
 
           @Override
           public void run(@NotNull final ProgressIndicator indicator) {
@@ -1716,7 +1698,7 @@
               @Override
               public void run() {
                 final boolean[] overFlow = {false};
-                myCalcElementsThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
+                myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
                   private final AtomicBoolean userAskedToAbort = new AtomicBoolean();
                   @Override
                   protected boolean isOverflow(@NotNull Set<Object> elementsArray) {
@@ -1734,11 +1716,11 @@
 
                 boolean anyPlace = isSearchInAnyPlace();
                 setSearchInAnyPlace(false);
-                myCalcElementsThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
+                myCalcUsagesThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
                 setSearchInAnyPlace(anyPlace);
 
                 if (anyPlace && !overFlow[0]) {
-                  myCalcElementsThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
+                  myCalcUsagesThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
                   nonPrefixMatchElementsArray.removeAll(prefixMatchElementsArray);
                 }
 
@@ -1756,7 +1738,7 @@
 
           @Override
           public void onCancel() {
-            cancelCalcElementsThread();
+            myCalcUsagesThread.cancel();
           }
         });
       }
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
index cb03b68..86d9c17 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
@@ -339,7 +339,7 @@
   }
 
   private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("([^:]+)(?::|@|,|)\\[?(\\d+)?(?:(?:\\D)(\\d+)?)?\\]?");
-  private static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
+  public static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
   private static final Pattern patternToDetectMembers = Pattern.compile("(.+)(#)(.*)");
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index aa6a360..cc5915c 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -189,6 +189,7 @@
 
   @NotNull
   private static String getQualifierPattern(@NotNull ChooseByNameBase base, @NotNull String pattern) {
+    pattern = base.transformPattern(pattern);
     final String[] separators = base.getModel().getSeparators();
     int lastSeparatorOccurrence = 0;
     for (String separator : separators) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
index a6e6c8f..99d3c9b 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
@@ -26,6 +26,7 @@
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
 import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.util.Function;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
@@ -128,17 +129,19 @@
     List<AnAction> actions = ContainerUtil.newArrayList();
     if (everywhere) {
       for (String id : ((ActionManagerImpl)myActionManager).getActionIds()) {
+        ProgressManager.checkCanceled();
         ContainerUtil.addIfNotNull(actions, myActionManager.getAction(id));
       }
     } else {
-      actions.addAll(myModel.myActionsMap.keySet());
+      actions.addAll(myModel.myActionGroups.keySet());
     }
 
     List<ActionWrapper> actionWrappers = ContainerUtil.newArrayList();
     for (AnAction action : actions) {
+      ProgressManager.checkCanceled();
       MatchMode mode = myModel.actionMatches(pattern, action);
       if (mode != MatchMode.NONE) {
-        actionWrappers.add(new ActionWrapper(action, myModel.myActionsMap.get(action), mode, dataContext));
+        actionWrappers.add(new ActionWrapper(action, myModel.myActionGroups.get(action), mode, dataContext));
       }
     }
     return processItems(pattern, actionWrappers, consumer);
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
index 91f0d33..348283d 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
@@ -66,16 +66,7 @@
   private Pattern myCompiledPattern;
 
   protected final SearchableOptionsRegistrar myIndex;
-  protected final Map<AnAction, String> myActionsMap = new TreeMap<AnAction, String>(new Comparator<AnAction>() {
-    @Override
-    public int compare(@NotNull AnAction o1, @NotNull AnAction o2) {
-      int compare = Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText());
-      if (compare == 0 && !o1.equals(o2)) {
-        return o1.hashCode() - o2.hashCode();
-      }
-      return compare;
-    }
-  });
+  protected final Map<AnAction, String> myActionGroups = ContainerUtil.newHashMap();
 
   protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
   private final Map<String, String> myConfigurablesNames = ContainerUtil.newTroveMap();
@@ -88,7 +79,7 @@
     myProject = project;
     myContextComponent = component;
     final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
-    collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
+    collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText());
     if (project != null && editor != null && file != null) {
       final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
       if (children != null) {
@@ -98,6 +89,9 @@
       }
     }
     myIndex = SearchableOptionsRegistrar.getInstance();
+    if (!EventQueue.isDispatchThread()) {
+      return;
+    }
     fillConfigurablesNames(ShowSettingsUtilImpl.getConfigurables(project, true));
   }
 
@@ -457,11 +451,14 @@
     else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) {
       return MatchMode.DESCRIPTION;
     }
-    final String groupName = myActionsMap.get(anAction);
-    if (groupName == null) {
-      return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
+    if (text == null) {
+      return MatchMode.NONE;
     }
-    return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
+    final String groupName = myActionGroups.get(anAction);
+    if (groupName == null) {
+      return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
+    }
+    return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
   }
 
   @Nullable
@@ -611,7 +608,7 @@
   PatternMatcher getMatcher() {
     return myMatcher.get();
   }
-  
+
   public static class ActionWrapper implements Comparable<ActionWrapper>{
     private final AnAction myAction;
     private final MatchMode myMode;
diff --git a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
index 63d8a60..6350642 100644
--- a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
+++ b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
@@ -22,7 +22,6 @@
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
@@ -53,7 +52,12 @@
   }
 
   public static void dumpLookupElementWeights(final LookupImpl lookup) {
-    String sb = StringUtil.join(getLookupElementWeights(lookup), "\n");
+    LookupElement selected = lookup.getCurrentItem();
+    String sb = "selected: " + selected;
+    if (selected != null) {
+      sb += "\nprefix: " + lookup.itemPattern(selected);
+    }
+    sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup), "\n");
     System.out.println(sb);
     LOG.info(sb);
   }
diff --git a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
index ad322c2..ccf63a4 100644
--- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
@@ -100,8 +100,7 @@
     if (!goodMarker) return false;
     ErrorState state = ErrorState.get(builder_);
 
-    Frame frame = state.frameStack.peekLast();
-    return frame == null || frame.errorReportedAt <= builder_.rawTokenIndex();
+    return !state.frameStack.isEmpty();
   }
 
   public static TokenSet create_token_set_(IElementType... tokenTypes_) {
@@ -399,6 +398,11 @@
   private static void enter_section_impl_(PsiBuilder builder_, int level, int modifiers, @Nullable String frameName) {
     ErrorState state = ErrorState.get(builder_);
     Frame frame = state.FRAMES.alloc().init(builder_, state, level, modifiers, frameName);
+    Frame prevFrame = state.frameStack.peekLast();
+    if (prevFrame != null && prevFrame.errorReportedAt > frame.position) {
+      // report error for previous unsuccessful frame
+      reportError(builder_, state, frame, true, false);
+    }
     if (((frame.modifiers & _LEFT_) | (frame.modifiers & _LEFT_INNER_)) != 0) {
       PsiBuilder.Marker left = (PsiBuilder.Marker)builder_.getLatestDoneMarker();
       if (invalid_left_marker_guard_(builder_, left, frameName)) {
@@ -456,10 +460,10 @@
       state.clearVariants(true, frame.variantCount);
       addVariantInner(state, initialPos, frame.name);
     }
+    int lastErrorPos = getLastVariantPos(state, initialPos);
     if (!state.suppressErrors && eatMore != null) {
       state.suppressErrors = true;
       final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1);
-      final int lastErrorPos = getLastVariantPos(state, initialPos);
       boolean eatMoreFlag = eatMoreFlagOnce || !result && frame.position == initialPos && lastErrorPos > frame.position;
 
       PsiBuilderImpl.ProductionMarker latestDoneMarker =
@@ -497,7 +501,7 @@
         errorReported = reportError(builder_, state, frame, true, true);
         parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore);
       }
-      else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex())) {
+      else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex()) || frame.errorReportedAt > initialPos) {
         errorReported = reportError(builder_, state, frame, true, false);
       }
       if (extensionMarker != null) {
@@ -512,10 +516,14 @@
     }
     else if (!result && pinned && frame.errorReportedAt < 0) {
       // do not report if there are errors beyond current position
-      if (getLastVariantPos(state, initialPos) == initialPos) {
+      if (lastErrorPos == initialPos) {
         // do not force, inner recoverRoot might have skipped some tokens
         reportError(builder_, state, frame, false, false);
       }
+      else if (lastErrorPos > initialPos) {
+        // set error pos here as if it is reported for future reference
+        frame.errorReportedAt = lastErrorPos;
+      }
     }
     // propagate errorReportedAt up the stack to avoid duplicate reporting
     Frame prevFrame = willFail && eatMore == null ? null : state.frameStack.peekLast();
@@ -607,7 +615,7 @@
       return;
     }
     int position = builder_.rawTokenIndex();
-    if (frame.errorReportedAt < position && getLastVariantPos(state, position) <= position) {
+    if (frame.errorReportedAt < position && getLastVariantPos(state, position + 1) <= position) {
       reportError(builder_, state, frame, true, advance);
     }
   }
@@ -865,7 +873,7 @@
         ((modifiers & _LEFT_INNER_) != 0? "_LEFT_INNER_, ": "") +
         ((modifiers & _AND_) != 0? "_AND_, ": "") +
         ((modifiers & _NOT_) != 0? "_NOT_, ": "");
-      return "<" + offset + ", " + mod + level + (errorReportedAt > -1 ? ", [" + errorReportedAt + "]" : "") + ">";
+      return String.format("{%s:%s:%d, %d, %s%s}", offset, position, level, errorReportedAt, mod, name);
     }
   }
 
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
index 3e284ff..ae2a4dc 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
@@ -42,8 +42,6 @@
 
     @Override
     public void doExecute(final Editor editor, @Nullable Caret c, DataContext dataContext) {
-      if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
       Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
 
       boolean wholeWordsSearch = false;
@@ -88,10 +86,5 @@
       }, caretShiftFromSelectionStart);
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
     }
-
-    @Override
-    protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
-      return new SelectAllAction(searchComponent);
-    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
index 7d3c408..74390f1 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
@@ -40,8 +40,6 @@
 
     @Override
     public void doExecute(Editor editor, @Nullable Caret c, DataContext dataContext) {
-      if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
       Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
       TextRange wordSelectionRange = getSelectionRange(editor, caret);
       boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
@@ -56,7 +54,7 @@
 
         FindModel model = getFindModel(selectedText, wholeWordSearch);
 
-        findManager.setFindWasPerformed();
+        findManager.setSelectNextOccurrenceWasPerformed();
         findManager.setFindNextModel(model);
 
         int searchStartOffset = notFoundPreviously ? 0 : caret.getSelectionEnd();
@@ -84,10 +82,5 @@
       }
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
     }
-
-    @Override
-    protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
-      return new AddOccurrenceAction(searchComponent);
-    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
index 7b18928..1858ef5 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
@@ -107,25 +107,4 @@
     model.setWholeWordsOnly(wholeWords);
     return model;
   }
-
-  protected boolean executeEquivalentFindPanelAction(Editor editor, DataContext context) {
-    if (editor.getHeaderComponent() instanceof EditorSearchComponent) {
-      EditorSearchComponent searchComponent = (EditorSearchComponent)editor.getHeaderComponent();
-      EditorHeaderAction action = getEquivalentFindPanelAction(searchComponent);
-      if (action != null) {
-        Presentation presentation = new Presentation();
-        AnActionEvent event = new AnActionEvent(null, context, ActionPlaces.MAIN_MENU, presentation, ActionManager.getInstance(), 0);
-        action.update(event);
-        if (presentation.isEnabled()) {
-          action.actionPerformed(event);
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
-    return null;
-  }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
index fffff56..a5657ff 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
@@ -15,9 +15,6 @@
  */
 package com.intellij.openapi.editor.actions;
 
-import com.intellij.find.EditorSearchComponent;
-import com.intellij.find.editorHeaderActions.EditorHeaderAction;
-import com.intellij.find.editorHeaderActions.RemoveOccurrenceAction;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
@@ -38,8 +35,6 @@
 
     @Override
     public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
-      if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
       if (editor.getCaretModel().getCaretCount() > 1) {
         editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
       }
@@ -49,10 +44,5 @@
       getAndResetNotFoundStatus(editor);
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
     }
-
-    @Override
-    protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
-      return new RemoveOccurrenceAction(searchComponent);
-    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
index 4fec393..c5fd559 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
@@ -16,10 +16,10 @@
 package com.intellij.openapi.editor.richcopy;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.ReflectionUtil;
 import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
-import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Locale;
@@ -46,20 +46,18 @@
       }
       Method findFontMethod = Class.forName("sun.font.FontManager").getMethod("findFont2D", String.class, int.class, int.class);
       for (String logicalFont : logicalFontsToMap) {
-        String physicalFont = null;
         Object font2D = findFontMethod.invoke(fontManager, logicalFont, Font.PLAIN, 0);
         if (font2D == null) {
           continue;
         }
         String fontClassName = font2D.getClass().getName();
+        String physicalFont = null;
         if ("sun.font.CompositeFont".equals(fontClassName)) { // Windows and Linux case
           Object physicalFontObject = Class.forName("sun.font.CompositeFont").getMethod("getSlotFont", int.class).invoke(font2D, 0);
           physicalFont = (String)Class.forName("sun.font.Font2D").getMethod("getFamilyName", Locale.class).invoke(physicalFontObject, Locale.getDefault());
         }
         else if ("sun.font.CFont".equals(fontClassName)) { // MacOS case
-          Field field = Class.forName("sun.font.CFont").getDeclaredField("nativeFontName");
-          field.setAccessible(true);
-          physicalFont = (String)field.get(font2D);
+          physicalFont = ReflectionUtil.getField(Class.forName("sun.font.CFont"), font2D, String.class, "nativeFontName");
         }
         if (physicalFont != null) {
           logicalToPhysicalMapping.put(logicalFont, physicalFont);
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
index 5440610..504496a 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.FontPreferences;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
 import com.intellij.openapi.editor.ex.DisposableIterator;
 import com.intellij.openapi.editor.ex.MarkupModelEx;
@@ -418,7 +419,7 @@
 
     private MarkupIterator(@NotNull CharSequence charSequence, @NotNull RangeIterator rangeIterator, @NotNull EditorColorsScheme colorsScheme) {
       myRangeIterator = rangeIterator;
-      mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getEditorFontName(), colorsScheme.getEditorFontSize());
+      mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getFontPreferences());
     }
 
     public boolean atEnd() {
@@ -812,8 +813,7 @@
 
   private static class SegmentIterator {
     private final CharSequence myCharSequence;
-    private final String myDefaultFontFamilyName;
-    private final int myFontSize;
+    private final FontPreferences myFontPreferences;
 
     private int myCurrentStartOffset;
     private int myCurrentOffset;
@@ -822,10 +822,9 @@
     private String myCurrentFontFamilyName;
     private String myNextFontFamilyName;
 
-    private SegmentIterator(CharSequence charSequence, String defaultFontFamilyName, int fontSize) {
+    private SegmentIterator(CharSequence charSequence, FontPreferences fontPreferences) {
       myCharSequence = charSequence;
-      myDefaultFontFamilyName = defaultFontFamilyName;
-      myFontSize = fontSize;
+      myFontPreferences = fontPreferences;
     }
 
     public void reset(int startOffset, int endOffset, int fontStyle) {
@@ -843,9 +842,8 @@
       myCurrentStartOffset = myCurrentOffset;
       for (; myCurrentOffset < myEndOffset; myCurrentOffset++) {
         FontInfo fontInfo = ComplementaryFontsRegistry.getFontAbleToDisplay(myCharSequence.charAt(myCurrentOffset),
-                                                                            myFontSize,
                                                                             myFontStyle,
-                                                                            myDefaultFontFamilyName);
+                                                                            myFontPreferences);
         String fontFamilyName = fontInfo.getFont().getFamily();
 
         if (myCurrentFontFamilyName == null) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
index b138568..09e489b 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
@@ -25,15 +25,14 @@
 import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
-import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.*;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.newvfs.BulkFileListener;
 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
 import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.Query;
 import com.intellij.util.containers.ConcurrentIntObjectMap;
 import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
@@ -43,6 +42,8 @@
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 public class DirectoryIndexImpl extends DirectoryIndex {
@@ -68,7 +69,7 @@
     });
   }
 
-  private void subscribeToFileChanges() {
+  protected void subscribeToFileChanges() {
     myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
       @Override
       public void fileTypesChanged(@NotNull FileTypeEvent event) {
@@ -98,7 +99,7 @@
     });
   }
 
-  private void markContentRootsForRefresh() {
+  protected void markContentRootsForRefresh() {
     Module[] modules = ModuleManager.getInstance(myProject).getModules();
     for (Module module : modules) {
       VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
@@ -110,7 +111,7 @@
     }
   }
 
-  private void dispatchPendingEvents() {
+  protected void dispatchPendingEvents() {
     myConnection.deliverImmediately();
   }
 
@@ -124,24 +125,27 @@
   private RootIndex getRootIndex() {
     RootIndex rootIndex = myRootIndex;
     if (rootIndex == null) {
-      myRootIndex = rootIndex = new RootIndex(myProject, new RootIndex.InfoCache() {
-        // Upsource can't use int-mapping because different files may have the same id there
-        private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
-        @Override
-        public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
-          myInfoCache.put(((NewVirtualFile)dir).getId(), info);
-        }
-
-        @Override
-        public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
-          return myInfoCache.get(((NewVirtualFile)dir).getId());
-        }
-      });
+      myRootIndex = rootIndex = new RootIndex(myProject, createRootInfoCache());
     }
     return rootIndex;
   }
 
-  @Override
+  protected RootIndex.InfoCache createRootInfoCache() {
+    return new RootIndex.InfoCache() {
+      // Upsource can't use int-mapping because different files may have the same id there
+      private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
+      @Override
+      public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
+        myInfoCache.put(((NewVirtualFile)dir).getId(), info);
+      }
+
+      @Override
+      public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
+        return myInfoCache.get(((NewVirtualFile)dir).getId());
+      }
+    };
+  }
+
   @TestOnly
   public void checkConsistency() {
     getRootIndex().checkConsistency();
@@ -181,6 +185,21 @@
     return getRootIndex().getPackageName(dir);
   }
 
+  @NotNull
+  @Override
+  public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) {
+    checkAvailability();
+    return getRootIndex().getOrderEntries(info);
+  }
+
+  @TestOnly
+  void assertConsistency(DirectoryInfo info) {
+    OrderEntry[] entries = getOrderEntries(info);
+    for (int i = 1; i < entries.length; i++) {
+      assert RootIndex.BY_OWNER_MODULE.compare(entries[i - 1], entries[i]) <= 0;
+    }
+  }
+
   private void checkAvailability() {
     if (myDisposed) {
       ProgressManager.checkCanceled();
@@ -188,4 +207,95 @@
     }
   }
 
+  @NotNull
+  private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) {
+    return new OrderEntry() {
+      @NotNull
+      @Override
+      public VirtualFile[] getFiles(OrderRootType type) {
+        throw new IncorrectOperationException();
+      }
+
+      @NotNull
+      @Override
+      public String[] getUrls(OrderRootType rootType) {
+        throw new IncorrectOperationException();
+      }
+
+      @NotNull
+      @Override
+      public String getPresentableName() {
+        throw new IncorrectOperationException();
+      }
+
+      @Override
+      public boolean isValid() {
+        throw new IncorrectOperationException();
+      }
+
+      @NotNull
+      @Override
+      public Module getOwnerModule() {
+        return ownerModule;
+      }
+
+      @Override
+      public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) {
+        throw new IncorrectOperationException();
+      }
+
+      @Override
+      public int compareTo(@NotNull OrderEntry o) {
+        throw new IncorrectOperationException();
+      }
+
+      @Override
+      public boolean isSynthetic() {
+        throw new IncorrectOperationException();
+      }
+    };
+  }
+
+  @Override
+  @Nullable
+  OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+    OrderEntry[] entries = getOrderEntries(info);
+    if (entries.length < 10) {
+      for (OrderEntry entry : entries) {
+        if (entry.getOwnerModule() == ownerModule) return entry;
+      }
+      return null;
+    }
+    int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+    return index < 0 ? null : entries[index];
+  }
+
+  @Override
+  @NotNull
+  List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+    OrderEntry[] entries = getOrderEntries(info);
+    if (entries.length == 0) return Collections.emptyList();
+
+    if (entries.length == 1) {
+      OrderEntry entry = entries[0];
+      return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
+    }
+    int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+    if (index < 0) {
+      return Collections.emptyList();
+    }
+    int firstIndex = index;
+    while (firstIndex - 1 >= 0 && entries[firstIndex - 1].getOwnerModule() == ownerModule) {
+      firstIndex--;
+    }
+    int lastIndex = index + 1;
+    while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) {
+      lastIndex++;
+    }
+
+    OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex];
+    System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex);
+
+    return Arrays.asList(subArray);
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
index 932204c..4ba8b7b 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
@@ -72,10 +72,8 @@
   private Set<LocalFileSystem.WatchRequest> myRootsToWatch = new THashSet<LocalFileSystem.WatchRequest>();
   private final boolean myDoLogCachesUpdate;
 
-  public ProjectRootManagerComponent(Project project,
-                                     DirectoryIndex directoryIndex,
-                                     StartupManager startupManager) {
-    super(project, directoryIndex);
+  public ProjectRootManagerComponent(Project project, StartupManager startupManager) {
+    super(project);
 
     myConnection = project.getMessageBus().connect(project);
     myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener() {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
deleted file mode 100644
index dd72da9..0000000
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.roots.libraries.ui.impl;
-
-import com.intellij.ui.CheckboxTree;
-import com.intellij.ui.CheckedTreeNode;
-import com.intellij.ui.ClickListener;
-import com.intellij.ui.dualView.TreeTableView;
-import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
-import com.intellij.ui.treeStructure.treetable.TreeTableTree;
-import com.intellij.util.ui.ColumnInfo;
-import com.intellij.util.ui.tree.TreeUtil;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreeModel;
-import javax.swing.tree.TreeNode;
-import javax.swing.tree.TreePath;
-import java.awt.*;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Enumeration;
-
-/**
- * @author nik
- */
-public class CheckboxTreeTable extends TreeTableView {
-  public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
-    super(new ListTreeTableModelOnColumns(root, columns));
-    initTree(getTree(), renderer);
-  }
-
-  //todo[nik] I hate to copy-paste but have to copy the code below from CheckboxTreeBase to support CheckboxTree inside TreeTable in IDEA 11.1.x branch
-  //todo[nik] I solemnly swear to get rid of this code in IDEA 12 branch
-  private void initTree(final TreeTableTree tree, final CheckboxTree.CheckboxTreeCellRenderer cellRenderer) {
-    tree.setCellRenderer(cellRenderer);
-    tree.setRootVisible(false);
-    tree.setShowsRootHandles(true);
-    tree.setLineStyleAngled();
-    TreeUtil.installActions(tree);
-
-    new ClickListener() {
-      @Override
-      public boolean onClick(@NotNull MouseEvent e, int clickCount) {
-        int row = tree.getRowForLocation(e.getX(), e.getY());
-        if (row < 0) return false;
-        final Object o = tree.getPathForRow(row).getLastPathComponent();
-        if (!(o instanceof CheckedTreeNode)) return false;
-        Rectangle rowBounds = tree.getRowBounds(row);
-        cellRenderer.setBounds(rowBounds);
-        Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
-        checkBounds.setLocation(rowBounds.getLocation());
-
-        if (checkBounds.height == 0) checkBounds.height = rowBounds.height;
-
-        final CheckedTreeNode node = (CheckedTreeNode)o;
-        if (checkBounds.contains(e.getPoint())) {
-          if (node.isEnabled()) {
-            toggleNode(node);
-            tree.setSelectionRow(row);
-            return true;
-          }
-        }
-
-        return false;
-      }
-    }.installOn(this);
-
-    addKeyListener(new KeyAdapter() {
-      @Override
-      public void keyPressed(KeyEvent e) {
-        if (isToggleEvent(e)) {
-          TreePath treePath = tree.getLeadSelectionPath();
-          if (treePath == null) return;
-          final Object o = treePath.getLastPathComponent();
-          if (!(o instanceof CheckedTreeNode)) return;
-          CheckedTreeNode firstNode = (CheckedTreeNode)o;
-          boolean checked = toggleNode(firstNode);
-
-          TreePath[] selectionPaths = tree.getSelectionPaths();
-          for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
-            final TreePath selectionPath = selectionPaths[i];
-            final Object o1 = selectionPath.getLastPathComponent();
-            if (!(o1 instanceof CheckedTreeNode)) continue;
-            CheckedTreeNode node = (CheckedTreeNode)o1;
-            checkNode(node, checked);
-            ((DefaultTreeModel)tree.getModel()).nodeChanged(node);
-          }
-
-          e.consume();
-        }
-      }
-    });
-
-    tree.setSelectionRow(0);
-  }
-
-  private static boolean isToggleEvent(KeyEvent e) {
-    return e.getKeyCode() == KeyEvent.VK_SPACE;
-  }
-
-  protected boolean toggleNode(CheckedTreeNode node) {
-    boolean checked = !node.isChecked();
-    checkNode(node, checked);
-
-    // notify model listeners about model change
-    final TreeModel model = getTree().getModel();
-    model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
-
-    return checked;
-  }
-
-  private void checkNode(CheckedTreeNode node, boolean checked) {
-    adjustParentsAndChildren(node, checked);
-    repaint();
-  }
-
-  private void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
-    changeNodeState(node, checked);
-    if (!checked) {
-      TreeNode parent = node.getParent();
-      while (parent != null) {
-        if (parent instanceof CheckedTreeNode) {
-          changeNodeState((CheckedTreeNode)parent, false);
-        }
-        parent = parent.getParent();
-      }
-      uncheckChildren(node);
-    }
-    else {
-      checkChildren(node);
-    }
-    repaint();
-  }
-
-  private static void changeNodeState(final CheckedTreeNode node, final boolean checked) {
-    if (node.isChecked() != checked) {
-      node.setChecked(checked);
-    }
-  }
-
-  private static void uncheckChildren(final CheckedTreeNode node) {
-    final Enumeration children = node.children();
-    while (children.hasMoreElements()) {
-      final Object o = children.nextElement();
-      if (!(o instanceof CheckedTreeNode)) continue;
-      CheckedTreeNode child = (CheckedTreeNode)o;
-      changeNodeState(child, false);
-      uncheckChildren(child);
-    }
-  }
-
-  private static void checkChildren(final CheckedTreeNode node) {
-    final Enumeration children = node.children();
-    while (children.hasMoreElements()) {
-      final Object o = children.nextElement();
-      if (!(o instanceof CheckedTreeNode)) continue;
-      CheckedTreeNode child = (CheckedTreeNode)o;
-      changeNodeState(child, true);
-      checkChildren(child);
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  public <T> T[] getCheckedNodes(final Class<T> nodeType) {
-    final ArrayList<T> nodes = new ArrayList<T>();
-    final Object root = getTree().getModel().getRoot();
-    if (!(root instanceof CheckedTreeNode)) {
-      throw new IllegalStateException("The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
-    }
-    new Object() {
-      @SuppressWarnings("unchecked")
-      public void collect(CheckedTreeNode node) {
-        if (node.isLeaf()) {
-          Object userObject = node.getUserObject();
-          if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
-            final T value = (T)userObject;
-            nodes.add(value);
-          }
-        }
-        else {
-          for (int i = 0; i < node.getChildCount(); i++) {
-            final TreeNode child = node.getChildAt(i);
-            if (child instanceof CheckedTreeNode) {
-              collect((CheckedTreeNode)child);
-            }
-          }
-        }
-      }
-    }.collect((CheckedTreeNode)root);
-    T[] result = (T[])Array.newInstance(nodeType, nodes.size());
-    nodes.toArray(result);
-    return result;
-  }
-}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
index ee44bdf..bf3d383 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
@@ -26,11 +26,13 @@
 import com.intellij.ui.*;
 import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
 import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.Convertor;
 import com.intellij.util.ui.ColumnInfo;
 import com.intellij.util.ui.ComboBoxCellEditor;
 import com.intellij.util.ui.tree.TreeUtil;
 import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -38,12 +40,11 @@
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;
+import javax.swing.tree.TreePath;
 import java.awt.*;
 import java.io.File;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.*;
 import java.util.List;
-import java.util.Map;
 
 /**
  * This dialog allows selecting paths inside selected archives or directories.
@@ -108,17 +109,17 @@
   private JScrollPane myPane;
   private String myDescription;
 
-  public DetectedRootsChooserDialog(Component component, List<SuggestedChildRootInfo> suggestedRoots) {
+  public DetectedRootsChooserDialog(Component component, Collection<SuggestedChildRootInfo> suggestedRoots) {
     super(component, true);
     init(suggestedRoots);
   }
 
-  public DetectedRootsChooserDialog(Project project, List<SuggestedChildRootInfo> suggestedRoots) {
+  public DetectedRootsChooserDialog(Project project, Collection<SuggestedChildRootInfo> suggestedRoots) {
     super(project, true);
     init(suggestedRoots);
   }
 
-  private void init(List<SuggestedChildRootInfo> suggestedRoots) {
+  private void init(Collection<SuggestedChildRootInfo> suggestedRoots) {
     myDescription = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getFullProductName() +
                     " just scanned files and detected the following " + StringUtil.pluralize("root", suggestedRoots.size()) + ".<br>" +
                     "Select items in the tree below or press Cancel to cancel operation.");
@@ -128,7 +129,7 @@
     init();
   }
 
-  private static CheckboxTreeTable createTreeTable(List<SuggestedChildRootInfo> suggestedRoots) {
+  private static CheckboxTreeTable createTreeTable(Collection<SuggestedChildRootInfo> suggestedRoots) {
     final CheckedTreeNode root = createRoot(suggestedRoots);
     CheckboxTreeTable treeTable = new CheckboxTreeTable(root, new CheckboxTree.CheckboxTreeCellRenderer(true) {
       @Override
@@ -189,14 +190,30 @@
     column.setPreferredWidth(width);
     column.setMaxWidth(width);
     treeTable.setRootVisible(false);
+    new TreeTableSpeedSearch(treeTable, new Convertor<TreePath, String>() {
+      @Override
+      public String convert(TreePath o) {
+        Object node = o.getLastPathComponent();
+        if (!(node instanceof VirtualFileCheckedTreeNode)) return "";
+        return ((VirtualFileCheckedTreeNode)node).getFile().getPresentableUrl();
+      }
+    });
     TreeUtil.expandAll(treeTable.getTree());
     return treeTable;
   }
 
-  private static CheckedTreeNode createRoot(List<SuggestedChildRootInfo> suggestedRoots) {
+  private static CheckedTreeNode createRoot(Collection<SuggestedChildRootInfo> suggestedRoots) {
+    SuggestedChildRootInfo[] sortedRoots = suggestedRoots.toArray(new SuggestedChildRootInfo[suggestedRoots.size()]);
+    Arrays.sort(sortedRoots, new Comparator<SuggestedChildRootInfo>() {
+      @Override
+      public int compare(@NotNull SuggestedChildRootInfo o1, @NotNull SuggestedChildRootInfo o2) {
+        return o1.getDetectedRoot().getFile().getPresentableUrl().compareTo(o2.getDetectedRoot().getFile().getPresentableUrl());
+      }
+    });
+
     CheckedTreeNode root = new CheckedTreeNode(null);
     Map<VirtualFile, CheckedTreeNode> rootCandidateNodes = new HashMap<VirtualFile, CheckedTreeNode>();
-    for (SuggestedChildRootInfo rootInfo : suggestedRoots) {
+    for (SuggestedChildRootInfo rootInfo : sortedRoots) {
       final VirtualFile rootCandidate = rootInfo.getRootCandidate();
       CheckedTreeNode parent = rootCandidateNodes.get(rootCandidate);
       if (parent == null) {
@@ -230,6 +247,12 @@
     return "DetectedRootsChooserDialog";
   }
 
+  @Nullable
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return myTreeTable;
+  }
+
   private static class VirtualFileCheckedTreeNode extends CheckedTreeNode {
     private final VirtualFile myFile;
 
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
index 743e408..7252166 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.roots.libraries.ui.DetectedLibraryRoot;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
 import java.util.Map;
@@ -32,17 +33,19 @@
   private final Map<LibraryRootType, String> myRootTypeNames;
   private LibraryRootType mySelectedRootType;
 
-  SuggestedChildRootInfo(VirtualFile rootCandidate, DetectedLibraryRoot detectedRoot, Map<LibraryRootType, String> rootTypeNames) {
+  SuggestedChildRootInfo(@NotNull VirtualFile rootCandidate, @NotNull DetectedLibraryRoot detectedRoot, @NotNull Map<LibraryRootType, String> rootTypeNames) {
     myRootCandidate = rootCandidate;
     myDetectedRoot = detectedRoot;
     myRootTypeNames = rootTypeNames;
     mySelectedRootType = detectedRoot.getTypes().get(0);
   }
 
+  @NotNull
   public VirtualFile getRootCandidate() {
     return myRootCandidate;
   }
 
+  @NotNull
   public DetectedLibraryRoot getDetectedRoot() {
     return myDetectedRoot;
   }
@@ -51,6 +54,7 @@
     return myRootTypeNames.get(type);
   }
 
+  @NotNull
   public LibraryRootType getSelectedRootType() {
     return mySelectedRootType;
   }
@@ -64,6 +68,7 @@
     }
   }
 
+  @NotNull
   public String[] getRootTypeNames() {
     final String[] types = ArrayUtil.toStringArray(myRootTypeNames.values());
     Arrays.sort(types, String.CASE_INSENSITIVE_ORDER);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
index 72f9c5a..04f908a 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -33,12 +33,15 @@
 import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
 import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
 import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
-import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter;
+import com.intellij.ui.JBSplitter;
+import com.intellij.ui.OnePixelSplitter;
 import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.border.CustomLineBorder;
 import com.intellij.ui.roots.ToolbarPanel;
 import com.intellij.util.Consumer;
 import com.intellij.util.ui.UIUtil;
@@ -48,6 +51,7 @@
 
 import javax.swing.*;
 import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
 import java.awt.*;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
@@ -146,7 +150,9 @@
     myContentEntryEditorListener = new MyContentEntryEditorListener();
 
     final JPanel mainPanel = new JPanel(new BorderLayout());
-    mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+    if (!Registry.is("ide.new.project.settings")) {
+      mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+    }
 
     addAdditionalSettingsToPanel(mainPanel);
 
@@ -159,21 +165,32 @@
 
     myEditorsPanel = new ScrollablePanel(new VerticalStackLayout());
     myEditorsPanel.setBackground(BACKGROUND_COLOR);
-    JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel);
-    entriesPanel.add(new ToolbarPanel(myScrollPane, group), BorderLayout.CENTER);
+    JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel, Registry.is("ide.new.project.settings"));
+    final ToolbarPanel toolbarPanel = new ToolbarPanel(myScrollPane, group);
+    if (Registry.is("ide.new.project.settings")) {
+      toolbarPanel.setBorder(new CustomLineBorder(1,0,0,0));
+    }
+    entriesPanel.add(toolbarPanel, BorderLayout.CENTER);
 
-    final Splitter splitter = new Splitter(false);
+    final JBSplitter splitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false) : new JBSplitter(false);
     splitter.setProportion(0.6f);
     splitter.setHonorComponentsMinimumSize(true);
 
     myRootTreeEditor = createContentEntryTreeEditor(project);
-    splitter.setFirstComponent(myRootTreeEditor.createComponent());
+    final JComponent component = myRootTreeEditor.createComponent();
+    if (Registry.is("ide.new.project.settings")) {
+      component.setBorder(new CustomLineBorder(1,0,0,0));
+    }
+
+    splitter.setFirstComponent(component);
     splitter.setSecondComponent(entriesPanel);
     JPanel contentPanel = new JPanel(new GridBagLayout());
-    contentPanel.setBorder(BorderFactory.createEtchedBorder());
+    if (!Registry.is("ide.new.project.settings")) {
+      contentPanel.setBorder(BorderFactory.createEtchedBorder());
+    }
     final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myRootTreeEditor.getEditingActionsGroup(), true);
     contentPanel.add(new JLabel("Mark as:"),
-                     new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 5, 0, 5), 0, 0));
+                     new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 10, 0, 10), 0, 0));
     contentPanel.add(actionToolbar.getComponent(),
                      new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                                             new Insets(0, 0, 0, 0), 0, 0));
@@ -236,7 +253,11 @@
     if (componentBorder != null) {
       border = BorderFactory.createCompoundBorder(border, componentBorder);
     }
-    component.setBorder(border);
+    if (Registry.is("ide.new.project.settings")) {
+      component.setBorder(new EmptyBorder(0,0,0,0));
+    } else {
+      component.setBorder(border);
+    }
     myEditorsPanel.add(component);
   }
 
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
index 469d966..bc10302 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -36,6 +36,7 @@
 import com.intellij.ui.roots.ResizingWrapper;
 import com.intellij.uiDesigner.core.GridConstraints;
 import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.util.NotNullProducer;
 import com.intellij.util.containers.MultiMap;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
@@ -59,10 +60,22 @@
  */
 public abstract class ContentRootPanel extends JPanel {
   private static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED);
-  private static final Color SELECTED_HEADER_COLOR = new JBColor(new Color(0xDEF2FF), UIUtil.getPanelBackground().darker());
+  private static final Color SELECTED_HEADER_COLOR = new JBColor(new NotNullProducer<Color>() {
+    @NotNull
+    @Override
+    public Color produce() {
+      return  UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground().darker() : new Color(0xDEF2FF);
+    }
+  });
   private static final Color HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82);
   private static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF);
-  private static final Color CONTENT_COLOR = new JBColor(Color.WHITE, UIUtil.getPanelBackground());
+  private static final Color CONTENT_COLOR = new JBColor(new NotNullProducer<Color>() {
+    @NotNull
+    @Override
+    public Color produce() {
+      return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : Gray._255;
+    }
+  });
   private static final Color UNSELECTED_TEXT_COLOR = Gray._51;
 
   protected final ActionCallback myCallback;
@@ -140,7 +153,7 @@
     headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD));
     headerLabel.setOpaque(false);
     if (getContentEntry().getFile() == null) {
-      headerLabel.setForeground(Color.RED);
+      headerLabel.setForeground(JBColor.RED);
     }
     final IconActionComponent deleteIconComponent = new IconActionComponent(AllIcons.Modules.DeleteContentRoot,
                                                                             AllIcons.Modules.DeleteContentRootRollover,
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
deleted file mode 100644
index d924452..0000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 14-May-2009
- */
-package com.intellij.profile.codeInspection.ui;
-
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInspection.ex.Descriptor;
-import com.intellij.codeInspection.ex.InspectionProfileImpl;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
-import com.intellij.codeInspection.ex.ScopeToolState;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
-import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.ui.treeStructure.treetable.TreeTable;
-import com.intellij.util.ArrayUtil;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import java.util.*;
-
-public class AddScopeUtil {
-  public static ScopeToolState performAddScope(final TreeTable treeTable,
-                                               final Project project,
-                                               final InspectionProfileImpl inspectionProfile,
-                                               final Collection<InspectionConfigTreeNode> selectedNodes) {
-    final List<InspectionConfigTreeNode> nodes = new ArrayList<InspectionConfigTreeNode>();
-    final List<Descriptor> descriptors = new ArrayList<Descriptor>();
-    for (final InspectionConfigTreeNode node : selectedNodes) {
-      collect(descriptors, nodes, node);
-    }
-
-    final List<String> availableScopes = getAvailableScopes(descriptors, project, inspectionProfile);
-    final int idx = Messages.showChooseDialog(treeTable, "Scope:", "Choose Scope", ArrayUtil.toStringArray(availableScopes), availableScopes.get(0), Messages.getQuestionIcon());
-    if (idx == -1) return null;
-    final NamedScope chosenScope = NamedScopesHolder.getScope(project, availableScopes.get(idx));
-
-    ScopeToolState scopeToolState = null;
-    final Tree tree = treeTable.getTree();
-
-    for (final InspectionConfigTreeNode node : nodes) {
-      final Descriptor descriptor = node.getDefaultDescriptor();
-      final InspectionToolWrapper toolWrapper = descriptor.getToolWrapper().createCopy(); //copy
-      final HighlightDisplayLevel level = inspectionProfile.getErrorLevel(descriptor.getKey(), chosenScope, project);
-      final boolean enabled = inspectionProfile.isToolEnabled(descriptor.getKey());
-      scopeToolState = inspectionProfile.addScope(toolWrapper, chosenScope, level, enabled, project);
-      node.dropCache();
-      ((DefaultTreeModel)tree.getModel()).reload(node);
-      tree.expandPath(new TreePath(node.getPath()));
-    }
-    tree.revalidate();
-    return scopeToolState;
-  }
-
-  private static void collect(final List<Descriptor> descriptors,
-                              final List<InspectionConfigTreeNode> nodes,
-                              final InspectionConfigTreeNode node) {
-    final ToolDescriptors currentDescriptors = node.getDescriptors();
-    if (currentDescriptors != null) {
-      nodes.add(node);
-      descriptors.add(currentDescriptors.getDefaultDescriptor());
-      descriptors.addAll(currentDescriptors.getNonDefaultDescriptors());
-    } else if (node.getUserObject() instanceof String) {
-      for(int i = 0; i < node.getChildCount(); i++) {
-        final InspectionConfigTreeNode childNode = (InspectionConfigTreeNode)node.getChildAt(i);
-        collect(descriptors, nodes, childNode);
-      }
-    }
-  }
-
-  private static List<String> getAvailableScopes(final List<Descriptor> descriptors, final Project project, final InspectionProfileImpl inspectionProfile) {
-    final ArrayList<NamedScope> scopes = new ArrayList<NamedScope>();
-    for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(project)) {
-      Collections.addAll(scopes, holder.getScopes());
-    }
-    scopes.remove(CustomScopesProviderEx.getAllScope());
-
-    CustomScopesProviderEx.filterNoSettingsScopes(project, scopes);
-
-    final Set<NamedScope> used = new HashSet<NamedScope>();
-    for (final Descriptor descriptor : descriptors) {
-      final List<ScopeToolState> nonDefaultTools = inspectionProfile.getNonDefaultTools(descriptor.getKey().toString(), project);
-      if (nonDefaultTools != null) {
-        for (final ScopeToolState state : nonDefaultTools) {
-          used.add(state.getScope(project));
-        }
-      }
-    }
-    scopes.removeAll(used);
-
-    final List<String> availableScopes = new ArrayList<String>();
-    for (final NamedScope scope : scopes) {
-      availableScopes.add(scope.getName());
-    }
-    return availableScopes;
-  }
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
new file mode 100644
index 0000000..b074676
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
+import com.intellij.ui.LayeredIcon;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.util.Consumer;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.EmptyIcon;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class AdvancedSettingsAction extends AnAction {
+  private final int myCheckBoxIndent;
+  private Project myProject;
+  private InspectionConfigTreeNode myRoot;
+
+  public AdvancedSettingsAction(final Project project, InspectionConfigTreeNode root) {
+    super("Advanced Settings");
+    getTemplatePresentation().setIcon(AllIcons.General.Gear);
+    myProject = project;
+    myRoot = root;
+    myCheckBoxIndent = calculateCheckBoxIndent();
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    super.update(e);
+    final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+    final Icon icon = AllIcons.General.Gear;
+    e.getPresentation().setIcon(
+      (inspectionProfile != null && inspectionProfile.isProfileLocked()) ? LayeredIcon.create(icon, PlatformIcons.LOCKED_ICON) : icon);
+  }
+
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    final ListPopupImpl actionGroupPopup = (ListPopupImpl)JBPopupFactory.getInstance().createListPopup(
+      new BaseListPopupStep<MyAction>(null, ContainerUtil.list(new MyDisableNewInspectionsAction(), new MyResetAction())) {
+        @Override
+        public PopupStep onChosen(MyAction selectedValue, boolean finalChoice) {
+          if (selectedValue.enabled()) {
+            selectedValue.actionPerformed();
+          }
+          return FINAL_CHOICE;
+        }
+      });
+    actionGroupPopup.getList().setCellRenderer(new ListCellRenderer() {
+      @Override
+      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        return ((MyAction)value).createCustomComponent(isSelected);
+      }
+    });
+    final Component component = e.getInputEvent().getComponent();
+    actionGroupPopup.show(new RelativePoint(component, new Point(component.getWidth() - 1, 0)));
+  }
+
+  private JLabel installLeftIndentToLabel(final JLabel label) {
+    label.setBorder(BorderFactory.createEmptyBorder(0, myCheckBoxIndent, 0, 0));
+    return label;
+  }
+
+  private class MyResetAction extends MyAction {
+
+    protected MyResetAction() {
+      super("All your changes will be lost");
+    }
+
+    @Override
+    protected JComponent createBaseComponent() {
+      return installLeftIndentToLabel(new JLabel("Reset to Defaults Settings"));
+    }
+
+    @Override
+    public void actionPerformed() {
+      final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+      if (inspectionProfile == null) {
+        return;
+      }
+      inspectionProfile.resetToBase(myProject);
+      postProcessModification();
+    }
+
+    @Override
+    protected boolean enabled() {
+      return myRoot.isProperSetting();
+    }
+  }
+
+  private class MyDisableNewInspectionsAction extends MyAction {
+    public MyDisableNewInspectionsAction() {
+      super("New inspections may appear when " + ApplicationNamesInfo.getInstance().getFullProductName() + " is updated");
+    }
+
+    @Override
+    protected JComponent createBaseComponent() {
+      final JCheckBox checkBox = new JCheckBox("Disable new inspections by default");
+      final InspectionProfileImpl profile = getInspectionProfile();
+      checkBox.setEnabled(profile != null);
+      if (profile != null) {
+        checkBox.setSelected(profile.isProfileLocked());
+      }
+      checkBox.setOpaque(false);
+      return checkBox;
+    }
+
+    @Override
+    public void actionPerformed() {
+      final InspectionProfileImpl profile = getInspectionProfile();
+      if (profile != null) {
+        profile.lockProfile(!profile.isProfileLocked());
+      }
+    }
+
+
+    @Override
+    protected boolean enabled() {
+      return true;
+    }
+  }
+
+  private abstract class MyAction {
+    private final String myDescription;
+
+    protected MyAction(String description) {
+      myDescription = description;
+    }
+
+    protected abstract JComponent createBaseComponent();
+
+    protected abstract void actionPerformed();
+
+    protected abstract boolean enabled();
+
+    public JComponent createCustomComponent(final boolean selected) {
+      JPanel panel = new JPanel();
+      panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+      panel.add(createBaseComponent());
+      panel.add(installLeftIndentToLabel(new JBLabel(myDescription, UIUtil.ComponentStyle.MINI)));
+      panel.setBackground(selected ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground());
+      panel.setForeground(selected ? UIUtil.getListSelectionForeground() : UIUtil.getListForeground());
+      UIUtil.setEnabled(panel, enabled(), true);
+      return panel;
+    }
+  }
+
+  protected abstract InspectionProfileImpl getInspectionProfile();
+
+  protected abstract void postProcessModification();
+
+  private static int calculateCheckBoxIndent() {
+    JCheckBox checkBox = new JCheckBox();
+    Icon icon = checkBox.getIcon();
+    int indent = 0;
+    if (icon == null) {
+      icon = UIManager.getIcon("CheckBox.icon");
+    }
+    if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
+      icon = EmptyIcon.create(20, 18);
+    }
+    if (icon != null) {
+      final Insets i = checkBox.getInsets();
+      final Rectangle r = checkBox.getBounds();
+      final Rectangle r1 = new Rectangle();
+      r1.x = i.left;
+      r1.y = i.top;
+      r1.width = r.width - (i.right + r1.x);
+      r1.height = r.height - (i.bottom + r1.y);
+      final Rectangle iconRect = new Rectangle();
+      SwingUtilities.layoutCompoundLabel(
+        checkBox, checkBox.getFontMetrics(checkBox.getFont()), checkBox.getText(), icon,
+        checkBox.getVerticalAlignment(), checkBox.getHorizontalAlignment(),
+        checkBox.getVerticalTextPosition(), checkBox.getHorizontalTextPosition(),
+        r1, new Rectangle(), iconRect,
+        checkBox.getText() == null ? 0 : checkBox.getIconTextGap());
+      indent = iconRect.x;
+    }
+    return indent + checkBox.getIconTextGap();
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
index 7949452..efc60c6 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
@@ -151,7 +151,7 @@
               final Set<String> levels = new HashSet<String>();
               for (Object o : rootElement.getChildren("inspection_tool")) {
                 final Element inspectElement = (Element)o;
-                levels.add(inspectElement.getAttributeValue("l"));
+                levels.add(inspectElement.getAttributeValue("level"));
                 for (Object s : inspectElement.getChildren("scope")) {
                   levels.add(((Element)s).getAttributeValue("level"));
                 }
@@ -532,6 +532,6 @@
   public JComponent getPreferredFocusedComponent() {
     final InspectionProfileImpl inspectionProfile = getSelectedObject();
     assert inspectionProfile != null : configuredProfiles();
-    return getProfilePanel(inspectionProfile).getTree();
+    return getProfilePanel(inspectionProfile).getPreferredFocusedComponent();
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
index 1067a60..df3b8bd 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
@@ -43,7 +43,11 @@
   private HighlightSeverity myChosen = null;
 
   public LevelChooserAction(final InspectionProfileImpl profile) {
-    mySeverityRegistrar = ((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar();
+    this(((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar());
+  }
+
+  public LevelChooserAction(final SeverityRegistrar severityRegistrar) {
+    mySeverityRegistrar = severityRegistrar;
   }
 
   @NotNull
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
deleted file mode 100644
index 2bf9096..0000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.profile.codeInspection.ui;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MultiScopeSeverityIcon implements Icon {
-  private final int mySize;
-  private final List<Color> myColors;
-
-  public MultiScopeSeverityIcon(final int size, final List<Color> colors) {
-    mySize = size;
-    myColors = colors;
-  }
-
-  @Override
-  public void paintIcon(final Component c, final Graphics g, final int i, final int j) {
-    final int iconWidth = getIconWidth();
-    final int iconHeightCoordinate = j + getIconHeight();
-
-    final int partWidth = iconWidth / myColors.size();
-
-    for (int idx = 0; idx < myColors.size(); idx++) {
-      final Color color = myColors.get(idx);
-      g.setColor(color);
-      final int x = i + partWidth * idx;
-      g.fillRect(x, j, x + partWidth, iconHeightCoordinate);
-    }
-  }
-
-  @Override
-  public int getIconWidth() {
-    return mySize;
-  }
-
-  @Override
-  public int getIconHeight() {
-    return mySize;
-  }
-}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
new file mode 100644
index 0000000..f2d8c5e
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.util.ArrayUtil;
+
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopeOrderComparator implements Comparator<String> {
+  private final String[] myScopesOrder;
+
+  public ScopeOrderComparator(final InspectionProfileImpl inspectionProfile) {
+    this(inspectionProfile.getScopesOrder());
+  }
+
+  public ScopeOrderComparator(String[] scopesOrder) {
+    myScopesOrder = scopesOrder;
+  }
+
+  private int getKey(String scope) {
+    return myScopesOrder == null ? -1 : ArrayUtil.indexOf(myScopesOrder, scope);
+  }
+
+  @Override
+  public int compare(String scope1, String scope2) {
+    final int key = getKey(scope1);
+    final int key1 = getKey(scope2);
+    if (key >= 0) {
+      if (key1 >= 0) {
+        return key - key1;
+      }
+      else {
+        return -1;
+      }
+    }
+    else {
+      if (key1 >= 0) {
+        return 1;
+      }
+      else {
+        return scope1.compareTo(scope2);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
index 4932e7f..fde3b14 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
@@ -22,13 +22,16 @@
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
 import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
 import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
 import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.util.ArrayList;
+import java.util.Set;
 import java.util.List;
 import java.util.Collections;
 
@@ -36,22 +39,28 @@
  * @author Dmitry Batkovich
  */
 public abstract class ScopesChooser extends ComboBoxAction {
+  public static final String TITLE = "Select a scope to change its settings";
 
   private final List<Descriptor> myDefaultDescriptors;
   private final InspectionProfileImpl myInspectionProfile;
   private final Project myProject;
+  private final Set<String> myExcludedScopeNames;
 
-  public ScopesChooser(final List<Descriptor> defaultDescriptors, final InspectionProfileImpl inspectionProfile, final Project project) {
+  public ScopesChooser(final List<Descriptor> defaultDescriptors,
+                       final InspectionProfileImpl inspectionProfile,
+                       final Project project,
+                       final String[] excludedScopeNames) {
     myDefaultDescriptors = defaultDescriptors;
     myInspectionProfile = inspectionProfile;
     myProject = project;
-    setPopupTitle("Select a scope to change its settings");
+    myExcludedScopeNames = excludedScopeNames == null ? Collections.<String>emptySet() : ContainerUtil.newHashSet(excludedScopeNames);
+    setPopupTitle(TITLE);
     getTemplatePresentation().setText("In All Scopes");
   }
 
   @NotNull
   @Override
-  protected DefaultActionGroup createPopupActionGroup(final JComponent button) {
+  public DefaultActionGroup createPopupActionGroup(final JComponent component) {
     final DefaultActionGroup group = new DefaultActionGroup();
 
     final List<NamedScope> predefinedScopes = new ArrayList<NamedScope>();
@@ -61,30 +70,47 @@
       predefinedScopes.addAll(holder.getPredefinedScopes());
     }
     predefinedScopes.remove(CustomScopesProviderEx.getAllScope());
-    fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile);
-    group.addSeparator();
-    fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile);
+    for (NamedScope predefinedScope : predefinedScopes) {
+      if (predefinedScope instanceof NonProjectFilesScope) {
+        predefinedScopes.remove(predefinedScope);
+        break;
+      }
+    }
 
-    //TODO edit scopes order
-    //group.addSeparator();
-    //group.add(new AnAction("Edit Scopes Order...") {
-    //  @Override
-    //  public void actionPerformed(final AnActionEvent e) {
-    //
-    //  }
-    //});
+    fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
+    group.addSeparator();
+    fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
+
+    group.addSeparator();
+    group.add(new AnAction("Edit Scopes Order...") {
+      @Override
+      public void actionPerformed(final AnActionEvent e) {
+        final ScopesOrderDialog dlg = new ScopesOrderDialog(component, myInspectionProfile, myProject);
+        dlg.show();
+        if (dlg.isOK()) {
+          onScopesOrderChanged();
+        }
+      }
+    });
 
     return group;
   }
 
+  protected abstract void onScopesOrderChanged();
+
   protected abstract void onScopeAdded();
 
   private void fillActionGroup(final DefaultActionGroup group,
-                                      final List<NamedScope> scopes,
-                                      final List<Descriptor> defaultDescriptors,
-                                      final InspectionProfileImpl inspectionProfile) {
+                               final List<NamedScope> scopes,
+                               final List<Descriptor> defaultDescriptors,
+                               final InspectionProfileImpl inspectionProfile,
+                               final Set<String> excludedScopeNames) {
     for (final NamedScope scope : scopes) {
-      group.add(new AnAction(scope.getName()) {
+      final String scopeName = scope.getName();
+      if (excludedScopeNames.contains(scopeName)) {
+        continue;
+      }
+      group.add(new AnAction(scopeName) {
         @Override
         public void actionPerformed(final AnActionEvent e) {
           for (final Descriptor defaultDescriptor : defaultDescriptors) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
new file mode 100644
index 0000000..c69a3e5
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
+import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
+import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.ui.*;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopesOrderDialog extends DialogWrapper {
+
+  private final JList myOptionsList = new JBList();
+
+  private final InspectionProfileImpl myInspectionProfile;
+  private final Project myProject;
+  private final JPanel myPanel;
+
+  public ScopesOrderDialog(final @NotNull Component parent,
+                           final InspectionProfileImpl inspectionProfile,
+                           final Project project) {
+    super(parent, true);
+    myInspectionProfile = inspectionProfile;
+    myProject = project;
+
+    final JPanel listPanel = ToolbarDecorator.createDecorator(myOptionsList).setMoveDownAction(new AnActionButtonRunnable() {
+      @Override
+      public void run(AnActionButton anActionButton) {
+        ListUtil.moveSelectedItemsDown(myOptionsList);
+      }
+    }).setMoveUpAction(new AnActionButtonRunnable() {
+      @Override
+      public void run(AnActionButton anActionButton) {
+        ListUtil.moveSelectedItemsUp(myOptionsList);
+      }
+    }).disableRemoveAction().disableAddAction().createPanel();
+    final JLabel descr = new JLabel("<html><p>If file appears in two or more scopes, it will be" +
+                                           "inspected with settings of the topmost scope in list above.</p><p/>" +
+                                           "<p>Scope order is set globally for all inspections in the profile.</p></html>");
+    descr.setPreferredSize(new Dimension(300, 100));
+    UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, descr);
+    myPanel = new JPanel();
+    myPanel.setLayout(new BorderLayout());
+    myPanel.add(listPanel, BorderLayout.CENTER);
+    myPanel.add(descr, BorderLayout.SOUTH);
+    fillList();
+    init();
+    setTitle("Scopes Order");
+  }
+
+  private void fillList() {
+    DefaultListModel model = new DefaultListModel();
+    model.removeAllElements();
+
+    final List<String> scopes = new ArrayList<String>();
+    for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(myProject)) {
+      for (final NamedScope scope : holder.getScopes()) {
+        if (!(scope instanceof NonProjectFilesScope)) {
+          scopes.add(scope.getName());
+        }
+      }
+    }
+    scopes.remove(CustomScopesProviderEx.getAllScope().getName());
+    Collections.sort(scopes, new ScopeOrderComparator(myInspectionProfile));
+    for (String scopeName : scopes) {
+      model.addElement(scopeName);
+    }
+    myOptionsList.setModel(model);
+    myOptionsList.setSelectedIndex(0);
+  }
+
+  @Nullable
+  @Override
+  protected JComponent createCenterPanel() {
+    return myPanel;
+  }
+
+  @Override
+  protected void doOKAction() {
+    final int size = myOptionsList.getModel().getSize();
+    final String[] newScopeOrder = new String[size];
+    for (int i = 0; i < size; i++) {
+      final String scopeName = (String) myOptionsList.getModel().getElementAt(i);
+      newScopeOrder[i] = scopeName;
+    }
+    if (!Arrays.equals(newScopeOrder, myInspectionProfile.getScopesOrder())) {
+      myInspectionProfile.setScopesOrder(newScopeOrder);
+    }
+    super.doOKAction();
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
index ce5f308..2da5c80 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
@@ -132,6 +132,8 @@
   private Splitter myRightSplitter;
   private Splitter myMainSplitter;
 
+  private String[] myInitialScopesOrder;
+
   public SingleInspectionProfilePanel(@NotNull InspectionProjectProfileManager projectProfileManager,
                                       @NotNull String inspectionProfileName,
                                       @NotNull ModifiableModel profile) {
@@ -186,8 +188,10 @@
     if (myTreeTable != null) {
       final TreePath selectionPath = myTreeTable.getTree().getSelectionPath();
       if (selectionPath != null) {
-        TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode)selectionPath.getLastPathComponent());
-        TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(selectionPath), false);
+        TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode) selectionPath.getLastPathComponent());
+        final int rowForPath = myTreeTable.getTree().getRowForPath(selectionPath);
+        TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+        scrollToCenter();
       }
     }
   }
@@ -258,6 +262,7 @@
       if (!accept(state.getTool())) continue;
       myInitialToolDescriptors.add(ToolDescriptors.fromScopeToolState(state, profile, project));
     }
+    myInitialScopesOrder = mySelectedProfile.getScopesOrder();
   }
 
   protected boolean accept(InspectionToolWrapper entry) {
@@ -364,24 +369,6 @@
 
     actions.add(actionManager.createExpandAllAction(myTreeExpander, myTreeTable));
     actions.add(actionManager.createCollapseAllAction(myTreeExpander, myTreeTable));
-
-    actions.add(new AnAction(CommonBundle.message("button.reset.to.default"), CommonBundle.message("button.reset.to.default"),
-                             AllIcons.General.Reset) {
-      {
-        registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK)), myTreeTable);
-      }
-      @Override
-      public void update(AnActionEvent e) {
-        e.getPresentation().setEnabled(myRoot.isProperSetting());
-      }
-
-      @Override
-      public void actionPerformed(AnActionEvent e) {
-        mySelectedProfile.resetToBase(myProjectProfileManager.getProject());
-        postProcessModification();
-      }
-    });
-
     actions.add(new AnAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){
 
       @Override
@@ -396,18 +383,19 @@
       }
     });
 
-    actions.add(new ToggleAction("Lock Profile", "Lock profile", AllIcons.Nodes.Padlock) {
+    actions.add(new AdvancedSettingsAction(myProjectProfileManager.getProject(), myRoot) {
       @Override
-      public boolean isSelected(AnActionEvent e) {
-        return mySelectedProfile != null && mySelectedProfile.isProfileLocked();
+      protected InspectionProfileImpl getInspectionProfile() {
+        return mySelectedProfile;
       }
 
       @Override
-      public void setSelected(AnActionEvent e, boolean state) {
-        mySelectedProfile.lockProfile(state);
+      protected void postProcessModification() {
+        SingleInspectionProfilePanel.this.postProcessModification();
       }
     });
 
+
     final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, true);
     actionToolbar.setTargetComponent(this);
     return actionToolbar;
@@ -424,11 +412,24 @@
   public void selectInspectionTool(String name) {
     final InspectionConfigTreeNode node = findNodeByKey(name, myRoot);
     if (node != null) {
-      TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(new TreePath(node.getPath())) - 1, true);//myTree.isRootVisible ? 0 : 1;
       TreeUtil.selectNode(myTreeTable.getTree(), node);
+      final int rowForPath = myTreeTable.getTree().getRowForPath(new TreePath(node.getPath()));
+      TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+      scrollToCenter();
     }
   }
 
+  private void scrollToCenter() {
+    ListSelectionModel selectionModel = myTreeTable.getSelectionModel();
+    int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+    final int maxColumnSelectionIndex = Math.max(0, myTreeTable.getColumnModel().getSelectionModel().getMinSelectionIndex());
+    Rectangle maxCellRect = myTreeTable.getCellRect(maxSelectionIndex, maxColumnSelectionIndex, false);
+
+    final Point selectPoint = maxCellRect.getLocation();
+    final int allHeight = myTreeTable.getVisibleRect().height;
+    myTreeTable.scrollRectToVisible(new Rectangle(new Point(0, Math.max(0, selectPoint.y - allHeight / 2)), new Dimension(0, allHeight)));
+  }
+
   @Nullable
   private static InspectionConfigTreeNode findNodeByKey(String name, InspectionConfigTreeNode root) {
     for (int i = 0; i < root.getChildCount(); i++) {
@@ -524,6 +525,7 @@
 
 
     final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTreeTable);
+    myTreeTable.getTree().setShowsRootHandles(true);
     scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
     TreeUtil.collapseAll(myTreeTable.getTree(), 1);
 
@@ -684,14 +686,15 @@
   }
 
   private void updateOptionsAndDescriptionPanel(final TreePath... paths) {
-    if (paths == null || paths.length == 0) {
+    if (mySelectedProfile == null || paths == null || paths.length == 0) {
       return;
     }
     final TreePath path = paths[0];
     if (path == null) return;
     final List<InspectionConfigTreeNode> nodes = InspectionsAggregationUtil.getInspectionsNodes(paths);
     if (!nodes.isEmpty()) {
-      final InspectionConfigTreeNode singleNode = nodes.size() == 1 ? ContainerUtil.getFirstItem(nodes) : null;
+      final InspectionConfigTreeNode singleNode = paths.length == 1 && ((InspectionConfigTreeNode)paths[0].getLastPathComponent()).getDefaultDescriptor() != null
+                                                  ? ContainerUtil.getFirstItem(nodes) : null;
       if (singleNode != null && singleNode.getDefaultDescriptor().loadDescription() != null) {
         // need this in order to correctly load plugin-supplied descriptions
         final Descriptor defaultDescriptor = singleNode.getDefaultDescriptor();
@@ -721,7 +724,7 @@
       }
       else {
         try {
-          myBrowser.read(new StringReader(EMPTY_HTML), null);
+          myBrowser.read(new StringReader("<html><body>Multiple inspections are selected. You can edit them as a single inspection.</body></html>"), null);
         }
         catch (IOException e1) {
           //Can't be
@@ -733,7 +736,6 @@
       final JPanel severityPanel = new JPanel(new GridBagLayout());
       final double severityPanelWeightY;
       final JPanel configPanelAnchor = new JPanel(new GridLayout());
-      configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
 
       final Set<String> scopesNames = new THashSet<String>();
       for (final InspectionConfigTreeNode node : nodes) {
@@ -754,7 +756,7 @@
                 final HighlightDisplayKey key = node.getDefaultDescriptor().getKey();
                 final NamedScope scope = node.getDefaultDescriptor().getScope();
                 final boolean toUpdate = mySelectedProfile.getErrorLevel(key, scope, project) != level;
-                mySelectedProfile.setErrorLevel(key, level, -1, project);
+                mySelectedProfile.setErrorLevel(key, level, null, project);
                 if (toUpdate) node.dropCache();
               }
 
@@ -774,7 +776,13 @@
           public Descriptor fun(final InspectionConfigTreeNode node) {
             return node.getDefaultDescriptor();
           }
-        }), mySelectedProfile, project) {
+        }), mySelectedProfile, project, null) {
+          @Override
+          protected void onScopesOrderChanged() {
+            myTreeTable.getTree().updateUI();
+            updateOptionsAndDescriptionPanel();
+          }
+
           @Override
           protected void onScopeAdded() {
             updateOptionsAndDescriptionPanel();
@@ -812,12 +820,19 @@
             }
 
             @Override
-            protected void onChange() {
+            protected void onSettingsChanged() {
               myTreeTable.getTree().updateUI();
             }
 
             @Override
             protected void onScopeAdded() {
+              updateOptionsAndDescriptionPanel();
+            }
+
+            @Override
+            protected void onScopesOrderChanged() {
+              myTreeTable.getTree().updateUI();
+              updateOptionsAndDescriptionPanel();
             }
 
             @Override
@@ -829,8 +844,9 @@
           });
 
 
-        final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable);
+        final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable).disableUpDownActions();
         final JPanel panel = wrappedTable.createPanel();
+        panel.setMinimumSize(new Dimension(getMinimumSize().width, 3 * scopesAndScopesAndSeveritiesTable.getRowHeight()));
         severityPanel.add(new JBLabel("Scopes & Severities"),
                           new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
                                                  new Insets(5, 0, 2, 10), 0, 0));
@@ -842,8 +858,13 @@
         severityPanelWeightY = 0.3;
       }
       myOptionsPanel.add(severityPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, severityPanelWeightY, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
-      myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
-                                                                   new Insets(0, 0, 0, 0), 0, 0));
+      if (configPanelAnchor.getComponentCount() != 0) {
+        configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
+      }
+      if (configPanelAnchor.getComponentCount() != 0 || scopesNames.isEmpty()) {
+        myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
+                                                                     new Insets(0, 0, 0, 0), 0, 0));
+      }
       myOptionsPanel.revalidate();
       GuiUtils.enableChildren(myOptionsPanel, isThoughOneNodeEnabled(nodes));
     }
@@ -887,7 +908,10 @@
 
   private static void setConfigPanel(final JPanel configPanelAnchor, final ScopeToolState state) {
     configPanelAnchor.removeAll();
-    configPanelAnchor.add(state.getAdditionalConfigPanel());
+    final JComponent additionalConfigPanel = state.getAdditionalConfigPanel();
+    if (additionalConfigPanel != null) {
+      configPanelAnchor.add(ScrollPaneFactory.createScrollPane(additionalConfigPanel, SideBorder.NONE));
+    }
   }
 
   private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath) {
@@ -1001,6 +1025,7 @@
     if (mySelectedProfile.isChanged()) return true;
     if (myShareProfile != (mySelectedProfile.getProfileManager() == myProjectProfileManager)) return true;
     if (!Comparing.strEqual(myInitialProfile, mySelectedProfile.getName())) return true;
+    if (!Comparing.equal(myInitialScopesOrder, mySelectedProfile.getScopesOrder())) return true;
     if (descriptorsAreChanged()) {
       return true;
     }
@@ -1111,10 +1136,6 @@
     return false;
   }
 
-  public Tree getTreeTable() {
-    return myTreeTable.getTree();
-  }
-
   public boolean isProfileShared() {
     return myShareProfile;
   }
@@ -1176,15 +1197,15 @@
                                 final boolean showOptionsAndDescriptorPanels,
                                 @NotNull HighlightDisplayLevel level) {
     final HighlightDisplayKey key = child.getDefaultDescriptor().getKey();
-    mySelectedProfile.setErrorLevel(key, level, -1, myProjectProfileManager.getProject());
+    mySelectedProfile.setErrorLevel(key, level, null, myProjectProfileManager.getProject());
     child.dropCache();
     if (showOptionsAndDescriptorPanels) {
       updateOptionsAndDescriptionPanel(new TreePath(child.getPath()));
     }
   }
 
-  public JComponent getTree() {
-    return myTreeTable.getTree();
+  public JComponent getPreferredFocusedComponent() {
+    return myTreeTable;
   }
 
   private class MyFilterComponent extends FilterComponent {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
index cbd1c24..bccd2db 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
@@ -20,7 +20,6 @@
 import com.intellij.codeInspection.ex.InspectionProfileImpl;
 import com.intellij.icons.AllIcons;
 import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.actionSystem.ex.CheckboxAction;
@@ -60,6 +59,23 @@
     addSeparator();
 
     add(new ShowAvailableOnlyOnAnalyzeInspectionsAction());
+    add(new ShowOnlyCleanupInspectionsAction());
+  }
+
+  private class ShowOnlyCleanupInspectionsAction extends CheckboxAction {
+    public ShowOnlyCleanupInspectionsAction() {
+      super("Show Only Cleanup Inspections");
+    }
+
+    @Override
+    public boolean isSelected(final AnActionEvent e) {
+      return myInspectionsFilter.isShowOnlyCleanupInspections();
+    }
+
+    @Override
+    public void setSelected(final AnActionEvent e, final boolean state) {
+      myInspectionsFilter.setShowOnlyCleanupInspections(state);
+    }
   }
 
   private class ShowAvailableOnlyOnAnalyzeInspectionsAction extends CheckboxAction {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
index 432ef56..117cd77 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
@@ -33,11 +33,16 @@
   private final Set<HighlightSeverity> mySuitableSeverities = new HashSet<HighlightSeverity>();
   private Boolean mySuitableInspectionsStates;
   private boolean myAvailableOnlyForAnalyze;
+  private boolean myShowOnlyCleanupInspections;
 
   public boolean isAvailableOnlyForAnalyze() {
     return myAvailableOnlyForAnalyze;
   }
 
+  public boolean isShowOnlyCleanupInspections() {
+    return myShowOnlyCleanupInspections;
+  }
+
   public Boolean getSuitableInspectionsStates() {
     return mySuitableInspectionsStates;
   }
@@ -46,6 +51,11 @@
     return mySuitableSeverities.contains(severity);
   }
 
+  public void setShowOnlyCleanupInspections(final boolean showOnlyCleanupInspections) {
+    myShowOnlyCleanupInspections = showOnlyCleanupInspections;
+    filterChanged();
+  }
+
   public void setAvailableOnlyForAnalyze(final boolean availableOnlyForAnalyze) {
     myAvailableOnlyForAnalyze = availableOnlyForAnalyze;
     filterChanged();
@@ -67,10 +77,17 @@
   }
 
   public boolean isEmptyFilter() {
-    return mySuitableInspectionsStates == null && !myAvailableOnlyForAnalyze && mySuitableSeverities.isEmpty();
+    return mySuitableInspectionsStates == null
+           && !myAvailableOnlyForAnalyze
+           && !myShowOnlyCleanupInspections
+           && mySuitableSeverities.isEmpty();
   }
 
   public boolean matches(final Tools tools) {
+    if (myShowOnlyCleanupInspections && !tools.getTool().isCleanupTool()) {
+      return false;
+    }
+
     if (mySuitableInspectionsStates != null && mySuitableInspectionsStates != tools.isEnabled()) {
       return false;
     }
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
index 966a456..92cb62f 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
@@ -28,17 +28,21 @@
 import com.intellij.profile.codeInspection.ui.InspectionsAggregationUtil;
 import com.intellij.profile.codeInspection.ui.table.ScopesAndSeveritiesTable;
 import com.intellij.profile.codeInspection.ui.table.ThreeStateCheckBoxRenderer;
+import com.intellij.ui.DoubleClickListener;
 import com.intellij.ui.treeStructure.treetable.TreeTable;
 import com.intellij.ui.treeStructure.treetable.TreeTableModel;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableColumn;
 import javax.swing.tree.DefaultTreeModel;
 import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
 import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
 import java.util.*;
 import java.util.List;
 
@@ -60,8 +64,8 @@
 
     final TableColumn isEnabledColumn = getColumnModel().getColumn(IS_ENABLED_COLUMN);
     isEnabledColumn.setMaxWidth(20);
-    isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
-    isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+    isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+    isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
 
     addMouseMotionListener(new MouseAdapter() {
       @Override
@@ -76,10 +80,42 @@
         if (maybeIcon instanceof MultiScopeSeverityIcon) {
           final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap =
             ((MultiScopeSeverityIcon)maybeIcon).getScopeToAverageSeverityMap();
-          IdeTooltipManager.getInstance().show(new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
+          IdeTooltipManager.getInstance().show(
+            new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
         }
       }
     });
+
+    new DoubleClickListener() {
+      @Override
+      protected boolean onDoubleClick(MouseEvent event) {
+        final TreePath path = getTree().getPathForRow(getTree().getLeadSelectionRow());
+        if (path != null) {
+          final InspectionConfigTreeNode node = (InspectionConfigTreeNode)path.getLastPathComponent();
+          if (node.isLeaf()) {
+            swapInspectionEnableState();
+          }
+        }
+        return true;
+      }
+    }.installOn(this);
+
+    registerKeyboardAction(new ActionListener() {
+                             public void actionPerformed(ActionEvent e) {
+                               swapInspectionEnableState();
+                               updateUI();
+                             }
+                           }, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), JComponent.WHEN_FOCUSED);
+
+    getEmptyText().setText("No enabled inspections available");
+  }
+
+  private void swapInspectionEnableState() {
+    for (int selectedRow : getSelectedRows()) {
+      final Object value = getValueAt(selectedRow, IS_ENABLED_COLUMN);
+      final boolean newValue = !Boolean.TRUE.equals(value);
+      setValueAt(newValue, selectedRow, IS_ENABLED_COLUMN);
+    }
   }
 
   public abstract static class InspectionsConfigTreeTableSettings {
@@ -107,6 +143,7 @@
   private static class InspectionsConfigTreeTableModel extends DefaultTreeModel implements TreeTableModel {
 
     private final InspectionsConfigTreeTableSettings mySettings;
+    private TreeTable myTreeTable;
 
     public InspectionsConfigTreeTableModel(final InspectionsConfigTreeTableSettings settings) {
       super(settings.getRoot());
@@ -154,7 +191,7 @@
                      mySettings.getInspectionProfile().getNonDefaultTools(toolId, mySettings.getProject()));
           }
         }
-        return sink.constructIcon();
+        return sink.constructIcon(mySettings.getInspectionProfile());
       } else if (column == IS_ENABLED_COLUMN) {
         return isEnabled(inspectionsKeys);
       }
@@ -195,26 +232,34 @@
         aNode.dropCache();
         mySettings.onChanged(aNode);
       }
+      if (myTreeTable != null) {
+        UIUtil.invokeLaterIfNeeded(new Runnable() {
+          public void run() {
+            ((AbstractTableModel)myTreeTable.getModel()).fireTableDataChanged();
+          }
+        });
+      }
     }
 
     @Override
     public void setTree(final JTree tree) {
+      myTreeTable = ((TreeTableTree)tree).getTreeTable();
     }
   }
 
   private static class MultiColoredHighlightSeverityIconSink {
 
-    private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+    private final Map<String, HighlightSeverity> myScopeToAverageSeverityMap = new HashMap<String, HighlightSeverity>();
 
+    private String myDefaultScopeName;
     private boolean myIsFirst = true;
 
-    public Icon constructIcon() {
+    public Icon constructIcon(final InspectionProfileImpl inspectionProfile) {
       if (myScopeToAverageSeverityMap.isEmpty()) {
         return null;
       }
-      //TODO order scopes
       return !allScopesHasMixedSeverity()
-             ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap)
+             ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap, myDefaultScopeName, inspectionProfile)
              : ScopesAndSeveritiesTable.MIXED_FAKE_LEVEL.getIcon();
     }
 
@@ -229,6 +274,9 @@
 
     public void put(final ScopeToolState defaultState, final Collection<ScopeToolState> nonDefault) {
       putOne(defaultState);
+      if (myDefaultScopeName == null) {
+        myDefaultScopeName = defaultState.getScopeName();
+      }
       for (final ScopeToolState scopeToolState : nonDefault) {
         putOne(scopeToolState);
       }
@@ -237,7 +285,7 @@
       }
     }
 
-    public void putOne(final ScopeToolState state) {
+    private void putOne(final ScopeToolState state) {
       final Icon icon = state.getLevel().getIcon();
       final String scopeName = state.getScopeName();
       if (icon instanceof HighlightDisplayLevel.SingleColorIconWithMask) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
index 6f093ca..099dbb6 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
@@ -17,13 +17,15 @@
 
 
 import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
 import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
 import com.intellij.ui.JBColor;
 
 import javax.swing.*;
 import java.awt.*;
-import java.util.Collection;
-import java.util.LinkedHashMap;
+import java.util.*;
+import java.util.List;
 
 /**
  * @author Dmitry Batkovich
@@ -35,8 +37,17 @@
 
   private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap;
 
-  public MultiScopeSeverityIcon(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
-    myScopeToAverageSeverityMap = scopeToAverageSeverityMap;
+  public MultiScopeSeverityIcon(final Map<String, HighlightSeverity> scopeToAverageSeverityMap,
+                                final String defaultScopeName,
+                                final InspectionProfileImpl inspectionProfile) {
+    final List<String> sortedScopeNames = new ArrayList<String>(scopeToAverageSeverityMap.keySet());
+    myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+    Collections.sort(sortedScopeNames, new ScopeOrderComparator(inspectionProfile));
+    sortedScopeNames.remove(defaultScopeName);
+    sortedScopeNames.add(defaultScopeName);
+    for (final String scopeName : sortedScopeNames) {
+      myScopeToAverageSeverityMap.put(scopeName, scopeToAverageSeverityMap.get(scopeName));
+    }
   }
 
   public LinkedHashMap<String, HighlightSeverity> getScopeToAverageSeverityMap() {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
index 05cb7ab..68c7f20 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
@@ -19,10 +19,12 @@
 import com.intellij.lang.annotation.HighlightSeverity;
 import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
 import com.intellij.ui.table.JBTable;
+import com.intellij.util.ui.UIUtil;
 
 import javax.swing.*;
 import javax.swing.table.AbstractTableModel;
 import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
 import java.awt.*;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -38,9 +40,20 @@
   public ScopesAndSeveritiesHintTable(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
     super(new MyModel(scopeToAverageSeverityMap));
 
-    final DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
-    cellRenderer.setOpaque(false);
-    getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(cellRenderer);
+    getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
+      @Override
+      public Component getTableCellRendererComponent(JTable table,
+                                                     Object value,
+                                                     boolean isSelected,
+                                                     boolean hasFocus,
+                                                     int row,
+                                                     int column) {
+        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+        setOpaque(false);
+        UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
+        return this;
+      }
+    });
 
     getColumnModel().getColumn(SEVERITY_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
       @Override
@@ -55,6 +68,7 @@
         setIcon(HighlightDisplayLevel.find(severity).getIcon());
         setText(SingleInspectionProfilePanel.renderSeverity(severity));
         setOpaque(false);
+        UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
         return this;
       }
     });
@@ -62,6 +76,16 @@
     setRowSelectionAllowed(false);
     setColumnSelectionAllowed(false);
     setOpaque(false);
+
+    for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
+      int w = 0;
+      final TableColumn column = getColumnModel().getColumn(i);
+      for (int j = 0; j < getModel().getRowCount(); j++) {
+        final Component component = prepareRenderer(column.getCellRenderer(), j, i);
+        w = Math.max(component.getPreferredSize().width, w);
+      }
+      column.setPreferredWidth(w);
+    }
   }
 
   private final static class MyModel extends AbstractTableModel {
@@ -96,7 +120,7 @@
     @Override
     public Object getValueAt(final int rowIndex, final int columnIndex) {
       switch (columnIndex) {
-        case SCOPE_COLUMN: return myScopes.get(rowIndex);
+        case SCOPE_COLUMN: return rowIndex < getRowCount() - 1 ? myScopes.get(rowIndex) : "Everywhere else";
         case SEVERITY_COLUMN: return myScopeToAverageSeverityMap.get(myScopes.get(rowIndex));
         default: throw new IllegalArgumentException();
       }
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
index ad7dc94..3b2c36b 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
@@ -17,20 +17,30 @@
 
 import com.intellij.codeHighlighting.HighlightDisplayLevel;
 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInspection.ex.Descriptor;
 import com.intellij.codeInspection.ex.InspectionProfileImpl;
 import com.intellij.codeInspection.ex.ScopeToolState;
 import com.intellij.icons.AllIcons;
+import com.intellij.ide.DataManager;
 import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.ListPopup;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.profile.codeInspection.ui.AddScopeUtil;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
+import com.intellij.profile.codeInspection.ui.ScopesChooser;
 import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.ui.awt.RelativePoint;
 import com.intellij.ui.table.JBTable;
 import com.intellij.ui.treeStructure.treetable.TreeTable;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
 import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.EditableModel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -41,8 +51,8 @@
 import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableColumn;
 import javax.swing.table.TableColumnModel;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
+import java.awt.*;
+import java.util.*;
 import java.util.List;
 
 /**
@@ -66,8 +76,8 @@
 
     final TableColumn scopeEnabledColumn = columnModel.getColumn(SCOPE_ENABLED_COLUMN);
     scopeEnabledColumn.setMaxWidth(30);
-    scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
-    scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+    scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+    scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
 
     final TableColumn severityColumn = columnModel.getColumn(SEVERITY_COLUMN);
     severityColumn.setCellRenderer(SeverityRenderer.create(tableSettings.getInspectionProfile()));
@@ -94,6 +104,8 @@
 
     setStriped(true);
     setShowGrid(false);
+
+    ((MyTableModel)getModel()).setTable(this);
   }
 
   public abstract static class TableSettings {
@@ -148,11 +160,13 @@
 
     protected abstract void onScopeAdded();
 
+    protected abstract void onScopesOrderChanged();
+
     protected abstract void onScopeRemoved(final int scopesCount);
 
     protected abstract void onScopeChosen(final @NotNull ScopeToolState scopeToolState);
 
-    protected abstract void onChange();
+    protected abstract void onSettingsChanged();
   }
 
   @NotNull
@@ -177,7 +191,9 @@
     private final Project myProject;
     private final TableSettings myTableSettings;
     private final List<HighlightDisplayKey> myKeys;
+    private final Comparator<String> myScopeComparator;
 
+    private JTable myTable;
     private String[] myScopeNames;
 
     public MyTableModel(final TableSettings tableSettings) {
@@ -188,12 +204,24 @@
       myKeyNames = tableSettings.getKeyNames();
       myNodes = tableSettings.getNodes();
       myTreeTable = tableSettings.getTreeTable();
+      myScopeComparator = new ScopeOrderComparator(myInspectionProfile);
       refreshAggregatedScopes();
     }
 
+    public void setTable(JTable table) {
+      myTable = table;
+    }
+
     @Override
     public boolean isCellEditable(final int rowIndex, final int columnIndex) {
-      return columnIndex != SCOPE_NAME_COLUMN;
+      if (columnIndex == SCOPE_NAME_COLUMN) {
+        return false;
+      } else if (columnIndex == SCOPE_ENABLED_COLUMN) {
+        return true;
+      }
+      assert columnIndex == SEVERITY_COLUMN;
+      final ExistedScopesStatesAndNonExistNames scopeToolState = getScopeToolState(rowIndex);
+      return scopeToolState.getNonExistNames().isEmpty();
     }
 
     @Override
@@ -221,7 +249,7 @@
         return String.class;
       }
       if (SEVERITY_COLUMN == columnIndex) {
-        return HighlightSeverity.class;
+        return SeverityState.class;
       }
       throw new IllegalArgumentException();
     }
@@ -235,9 +263,9 @@
         case SCOPE_ENABLED_COLUMN:
           return isEnabled(rowIndex);
         case SCOPE_NAME_COLUMN:
-          return getScope(rowIndex).getName();
+          return rowIndex == lastRowIndex() ? "Everywhere else" : getScope(rowIndex).getName();
         case SEVERITY_COLUMN:
-          return getSeverity(rowIndex);
+          return getSeverityState(rowIndex);
         default:
           throw new IllegalArgumentException("Invalid column index " + columnIndex);
       }
@@ -248,12 +276,12 @@
     }
 
     @NotNull
-    private HighlightSeverity getSeverity(final int rowIndex) {
+    private SeverityState getSeverityState(final int rowIndex) {
       final ExistedScopesStatesAndNonExistNames existedScopesStatesAndNonExistNames = getScopeToolState(rowIndex);
       if (!existedScopesStatesAndNonExistNames.getNonExistNames().isEmpty()) {
-        return MIXED_FAKE_SEVERITY;
+        return new SeverityState(MIXED_FAKE_SEVERITY, false);
       }
-      return ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates());
+      return new SeverityState(ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates()), true);
     }
 
     @Nullable
@@ -314,6 +342,7 @@
         }
       }
       myScopeNames = ArrayUtil.toStringArray(scopesNames);
+      Arrays.sort(myScopeNames, myScopeComparator);
     }
 
     private int lastRowIndex() {
@@ -326,13 +355,14 @@
         return;
       }
       if (columnIndex == SEVERITY_COLUMN) {
-        final HighlightDisplayLevel level = HighlightDisplayLevel.find(((HighlightSeverity)value).getName());
+        final SeverityState severityState = (SeverityState)value;
+        final HighlightDisplayLevel level = HighlightDisplayLevel.find(severityState.getSeverity().getName());
         if (level == null) {
-          LOG.error("no display level found for name " + ((HighlightSeverity)value).getName());
+          LOG.error("no display level found for name " + severityState.getSeverity().getName());
           return;
         }
-        final int idx = rowIndex == lastRowIndex() ? -1 : rowIndex;
-        myInspectionProfile.setErrorLevel(myKeys, level, idx, myProject);
+        final String scopeName = rowIndex == lastRowIndex() ? null : getScope(rowIndex).getName();
+        myInspectionProfile.setErrorLevel(myKeys, level, scopeName, myProject);
       }
       else if (columnIndex == SCOPE_ENABLED_COLUMN) {
         final NamedScope scope = getScope(rowIndex);
@@ -354,7 +384,7 @@
           }
         }
       }
-      myTableSettings.onChange();
+      myTableSettings.onSettingsChanged();
     }
 
     @Override
@@ -368,9 +398,31 @@
 
     @Override
     public void addRow() {
-      AddScopeUtil.performAddScope(myTreeTable, myProject, myInspectionProfile, myNodes);
-      myTableSettings.onScopeAdded();
-      refreshAggregatedScopes();
+      final List<Descriptor> descriptors = ContainerUtil.map(myTableSettings.getNodes(), new Function<InspectionConfigTreeNode, Descriptor>() {
+        @Override
+        public Descriptor fun(InspectionConfigTreeNode inspectionConfigTreeNode) {
+          return inspectionConfigTreeNode.getDefaultDescriptor();
+        }
+      });
+      final ScopesChooser scopesChooser = new ScopesChooser(descriptors, myInspectionProfile, myProject, myScopeNames) {
+        @Override
+        protected void onScopeAdded() {
+          myTableSettings.onScopeAdded();
+          refreshAggregatedScopes();
+        }
+
+        @Override
+        protected void onScopesOrderChanged() {
+          myTableSettings.onScopesOrderChanged();
+        }
+      };
+      DataContext dataContext = DataManager.getInstance().getDataContext(myTable);
+      final JComponent component = (JComponent)PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
+      final ListPopup popup = JBPopupFactory.getInstance()
+        .createActionGroupPopup(ScopesChooser.TITLE, scopesChooser.createPopupActionGroup(myTable), dataContext,
+                                JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false);
+      final RelativePoint point = new RelativePoint(myTable, new Point(myTable.getWidth() - popup.getContent().getPreferredSize().width, 0));
+      popup.show(point);
     }
 
     @Override
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
index 2fe95e6..e1b3d54 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
@@ -22,6 +22,8 @@
 import com.intellij.profile.codeInspection.SeverityProvider;
 import com.intellij.profile.codeInspection.ui.LevelChooserAction;
 import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -32,33 +34,40 @@
 /**
  * @author Dmitry Batkovich
  */
-public class SeverityRenderer extends ComboBoxTableRenderer<HighlightSeverity> {
-  public SeverityRenderer(final HighlightSeverity[] values) {
+public class SeverityRenderer extends ComboBoxTableRenderer<SeverityState> {
+  public SeverityRenderer(final SeverityState[] values) {
     super(values);
   }
 
   public static SeverityRenderer create(final InspectionProfileImpl inspectionProfile) {
     final SortedSet<HighlightSeverity> severities =
       LevelChooserAction.getSeverities(((SeverityProvider)inspectionProfile.getProfileManager()).getOwnSeverityRegistrar());
-    return new SeverityRenderer(severities.toArray(new HighlightSeverity[severities.size()]));
-  }
-
-
-  @Override
-  protected String getTextFor(@NotNull final HighlightSeverity value) {
-    return SingleInspectionProfilePanel.renderSeverity(value);
+    return new SeverityRenderer(ContainerUtil.map2Array(severities, new SeverityState[severities.size()], new Function<HighlightSeverity, SeverityState>() {
+      @Override
+      public SeverityState fun(HighlightSeverity severity) {
+        return new SeverityState(severity, true);
+      }
+    }));
   }
 
   @Override
-  protected Icon getIconFor(@NotNull final HighlightSeverity value) {
-    return HighlightDisplayLevel.find(value).getIcon();
+  protected void customizeComponent(SeverityState value, JTable table, boolean isSelected) {
+    super.customizeComponent(value, table, isSelected);
+    setPaintArrow(value.isEnabledForEditing());
+  }
+
+  @Override
+  protected String getTextFor(@NotNull final SeverityState value) {
+    return SingleInspectionProfilePanel.renderSeverity(value.getSeverity());
+  }
+
+  @Override
+  protected Icon getIconFor(@NotNull final SeverityState value) {
+    return HighlightDisplayLevel.find(value.getSeverity()).getIcon();
   }
 
   @Override
   public boolean isCellEditable(final EventObject event) {
-    if (event instanceof MouseEvent) {
-      return ((MouseEvent)event).getClickCount() >= 1;
-    }
-    return true;
+    return !(event instanceof MouseEvent) || ((MouseEvent)event).getClickCount() >= 1;
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
new file mode 100644
index 0000000..2aefde0
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package com.intellij.profile.codeInspection.ui.table;
+
+import com.intellij.lang.annotation.HighlightSeverity;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class SeverityState {
+
+  private final HighlightSeverity mySeverity;
+  private final boolean myEnabledForEditing;
+
+  public SeverityState(HighlightSeverity severity, boolean enabledForEditing) {
+    mySeverity = severity;
+    myEnabledForEditing = enabledForEditing;
+  }
+
+  public HighlightSeverity getSeverity() {
+    return mySeverity;
+  }
+
+  public boolean isEnabledForEditing() {
+    return myEnabledForEditing;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
index 7d8cfdf..455e2a6 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
@@ -15,11 +15,9 @@
  */
 package com.intellij.profile.codeInspection.ui.table;
 
-import com.intellij.ui.ClickListener;
 import com.intellij.util.SmartList;
 import com.intellij.util.ui.ThreeStateCheckBox;
 import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -28,7 +26,7 @@
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 import java.awt.*;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
 import java.util.EventObject;
 import java.util.List;
 
@@ -39,10 +37,16 @@
 
   private final List<CellEditorListener> myListeners = new SmartList<CellEditorListener>();
 
-  public ThreeStateCheckBoxRenderer() {
+  public ThreeStateCheckBoxRenderer(final boolean isEditor) {
     setThirdStateEnabled(false);
     setHorizontalAlignment(CENTER);
     setVerticalAlignment(CENTER);
+    addItemListener(new ItemListener() {
+      @Override
+      public void itemStateChanged(ItemEvent e) {
+        stopCellEditing();
+      }
+    });
   }
 
   @Override
@@ -69,16 +73,6 @@
     } else {
       setSelected((Boolean) value);
     }
-    new ClickListener() {
-      @Override
-      public boolean onClick(@NotNull final MouseEvent event, final int clickCount) {
-        if (clickCount == 1) {
-          stopCellEditing();
-          return true;
-        }
-        return false;
-      }
-    }.installOn(this);
     return this;
   }
 
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
index 1b17faf..42dcb46 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -149,7 +149,7 @@
       SourceTreeToPsiMap.psiElementToTree(CodeStyleManagerImpl.findElementInTreeWithFormatterEnabled(file, offset));
     if (elementAtOffset == null) {
       int significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t ");
-      return new TextRange(significantRangeStart, offset);
+      return new TextRange(Math.max(significantRangeStart, 0), offset);
     }
 
     final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index 27089fa..fdc434d 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
@@ -16,6 +16,7 @@
 
 package com.intellij.psi.impl.source.tree.injected;
 
+import com.intellij.extapi.psi.PsiFileBase;
 import com.intellij.injected.editor.*;
 import com.intellij.lang.Language;
 import com.intellij.lang.LanguageUtil;
@@ -48,8 +49,10 @@
  * @author cdr
  */
 public class InjectedLanguageUtil {
-  static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS");
-  public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect
+  static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS =
+    Key.create("HIGHLIGHT_TOKENS");
+  public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION");
+  // meaning: injected file text is probably incorrect
 
   public static void forceInjectionOnElement(@NotNull PsiElement host) {
     enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@@ -113,9 +116,9 @@
    * @return true if enumerated successfully
    */
   public static boolean enumerate(@NotNull PsiElement host,
-                               @NotNull PsiFile containingFile,
-                               boolean probeUp,
-                               @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
+                                  @NotNull PsiFile containingFile,
+                                  boolean probeUp,
+                                  @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
     //do not inject into nonphysical files except during completion
     if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
       final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile);
@@ -175,6 +178,32 @@
     return null;
   }
 
+  /**
+   * Finds injected language in expression
+   *
+   * @param expression  where to find
+   * @param classToFind class that represents language we look for
+   * @param <T>         class that represents language we look for
+   * @return instance of class that represents language we look for or null of not found
+   */
+  @Nullable
+  @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom)
+  public static <T extends PsiFileBase> T findInjectedFile(@NotNull final PsiElement expression,
+                                                           @NotNull final Class<T> classToFind) {
+    final List<Pair<PsiElement, TextRange>> files =
+      InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression);
+    if (files == null) {
+      return null;
+    }
+    for (final Pair<PsiElement, TextRange> fileInfo : files) {
+      final PsiElement injectedFile = fileInfo.first;
+      if (classToFind.isAssignableFrom(injectedFile.getClass())) {
+        return (T)injectedFile;
+      }
+    }
+    return null;
+  }
+
   public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) {
     if (editor == null || file == null || editor instanceof EditorWindow) return editor;
     PsiFile injectedFile = findInjectedPsiNoCommit(file, offset);
@@ -200,7 +229,9 @@
         }
       }
     }
-    if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+    if (!documentWindow.isValid()) {
+      return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+    }
     return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
   }
 
@@ -284,7 +315,8 @@
           ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue =
             CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false);
 
-          CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
+          CachedValueProvider.Result<MultiHostRegistrarImpl> result =
+            CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
           ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result);
 
           e.putUserData(INJECTED_PSI, cachedValue);
@@ -307,7 +339,9 @@
   // returns (injected psi, leaf element at the offset, language of the leaf element)
   // since findElementAt() is expensive, we trying to reuse its result
   @NotNull
-  private static Trinity<PsiElement,PsiElement,Language> tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) {
+  private static Trinity<PsiElement, PsiElement, Language> tryOffset(@NotNull PsiFile hostFile,
+                                                                     final int offset,
+                                                                     @NotNull PsiDocumentManager documentManager) {
     FileViewProvider provider = hostFile.getViewProvider();
     Language leafLanguage = null;
     PsiElement leafElement = null;
@@ -319,11 +353,11 @@
           leafElement = element;
         }
         PsiElement injected = findInside(element, hostFile, offset, documentManager);
-        if (injected != null) return Trinity.create(injected,element, language);
+        if (injected != null) return Trinity.create(injected, element, language);
       }
       // maybe we are at the border between two psi elements, then try to find injection at the end of the left element
       if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) {
-        PsiElement leftElement = provider.findElementAt(offset-1, language);
+        PsiElement leftElement = provider.findElementAt(offset - 1, language);
         if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) {
           PsiElement injected = findInside(leftElement, hostFile, offset, documentManager);
           if (injected != null) return Trinity.create(injected, element, language);
@@ -334,7 +368,10 @@
     return Trinity.create(null, leafElement, leafLanguage);
   }
 
-  private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) {
+  private static PsiElement findInside(@NotNull PsiElement element,
+                                       @NotNull PsiFile hostFile,
+                                       final int hostOffset,
+                                       @NotNull final PsiDocumentManager documentManager) {
     final Ref<PsiElement> out = new Ref<PsiElement>();
     enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
       @Override
@@ -361,10 +398,12 @@
     // modification of cachedInjectedDocuments must be under PsiLock only
     ConcurrentList<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
     if (injected == null) {
-      injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
+      injected =
+        ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
     }
     return injected;
   }
+
   public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
     file.putUserData(INJECTED_DOCS_KEY, null);
   }
@@ -426,10 +465,12 @@
     }
     return containingFile;
   }
+
   @NotNull
   public static Editor getTopLevelEditor(@NotNull Editor editor) {
     return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
   }
+
   public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) {
     PsiFile injectedFile = element.getContainingFile();
     if (injectedFile == null) return false;
@@ -461,13 +502,13 @@
   public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) {
     final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
     if (manager.getInjectionHost(file) == null) {
-      return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(),
-                                      endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset());
+      return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(),
+                                      endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset());
     }
     final StringBuilder sb = new StringBuilder();
     file.accept(new PsiRecursiveElementWalkingVisitor() {
 
-      Boolean myState = startElement == null? Boolean.TRUE : null;
+      Boolean myState = startElement == null ? Boolean.TRUE : null;
 
       @Override
       public void visitElement(PsiElement element) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
index 99ac9f7..232ddd7 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
@@ -28,7 +28,7 @@
         if (toggleStrategy) {
           final int size = comboBox.getModel().getSize();
           int next = comboBox.getSelectedIndex() + 1;
-          if (next < 0 || next >= size) {
+          if (size > 0 && (next < 0 || next >= size)) {
             if (!UISettings.getInstance().CYCLE_SCROLLING) {
               return;
             }
diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
index 1301079..6e37711 100644
--- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
@@ -151,6 +151,7 @@
         getEditor().getSettings().setRefrainFromScrolling(false);
         getEditor().getSettings().setLineNumbersShown(true);
         getEditor().getSettings().setFoldingOutlineShown(false);
+        ((EditorEx)getEditor()).getFoldingModel().setFoldingEnabled(false);
 
         add(getEditor().getComponent(), BorderLayout.CENTER);
       }
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
index 34f80da..451b0e7 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
@@ -84,7 +84,7 @@
     messageDigest.update((byte)0);
     messageDigest.update(String.valueOf(bytes.length).getBytes(defaultCharset));
     messageDigest.update((byte)0);
-    messageDigest.update((charset != null ? charset.displayName():"null_charset").getBytes(defaultCharset));
+    messageDigest.update((charset != null ? charset.name():"null_charset").getBytes(defaultCharset));
     messageDigest.update((byte)0);
 
     messageDigest.update(bytes, 0, bytes.length);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
index 6c866ad..09aeea3 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
@@ -31,7 +31,7 @@
 
   public static final boolean EXTRA_SANITY_CHECKS = SystemProperties.getBooleanProperty(
     "intellij.idea.indices.debug.extra.sanity",
-    true
+    DEBUG
   );
 
   public static void assertTrue(boolean value) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index 5242ee3..8507738 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -1964,34 +1964,39 @@
           // For 'normal indices' schedule the file for update and reset stamps for all affected indices (there
           // can be client that used indices between before and after events, in such case indices are up to date due to force update
           // with old content)
-          if (!fileIsDirectory && !isTooLarge(file)) {
-            FileTypeManagerImpl.cacheFileType(file, file.getFileType());
-            try {
-              final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
-              //noinspection ForLoopReplaceableByForEach
-              boolean scheduleForUpdate = false;
-              boolean resetStamp = false;
+          if (!fileIsDirectory) {
+            if (isTooLarge(file)) {
+              // large file might be scheduled for update in before event when its size was not large
+              myChangedFilesCollector.myFilesToUpdate.remove(file);
+            } else {
+              FileTypeManagerImpl.cacheFileType(file, file.getFileType());
+              try {
+                final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
+                //noinspection ForLoopReplaceableByForEach
+                boolean scheduleForUpdate = false;
+                boolean resetStamp = false;
 
-              //noinspection ForLoopReplaceableByForEach
-              for (int i = 0, size = candidates.size(); i < size; ++i) {
-                final ID<?, ?> indexId = candidates.get(i);
-                if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
-                  if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
-                    IndexingStamp.setFileIndexedStateOutdated(file, indexId);
-                    resetStamp = true;
+                //noinspection ForLoopReplaceableByForEach
+                for (int i = 0, size = candidates.size(); i < size; ++i) {
+                  final ID<?, ?> indexId = candidates.get(i);
+                  if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
+                    if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
+                      IndexingStamp.setFileIndexedStateOutdated(file, indexId);
+                      resetStamp = true;
+                    }
+                    scheduleForUpdate = true;
                   }
-                  scheduleForUpdate = true;
+                }
+
+                if (scheduleForUpdate) {
+                  if (resetStamp) IndexingStamp.flushCache(file);
+                  scheduleForUpdate(file);
                 }
               }
-
-              if (scheduleForUpdate) {
-                if (resetStamp) IndexingStamp.flushCache(file);
-                scheduleForUpdate(file);
+              finally {
+                FileTypeManagerImpl.cacheFileType(file, null);
               }
             }
-            finally {
-              FileTypeManagerImpl.cacheFileType(file, null);
-            }
           }
 
           return true;
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
index 6bdd55b..5ef1379 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -59,7 +59,7 @@
   private static final long UNINDEXED_STAMP = -1L; // we don't store trivial "absent" state
   private static final long INDEX_DATA_OUTDATED_STAMP = -2L;
 
-  private static final int VERSION = 12;
+  private static final int VERSION = 13;
   private static final ConcurrentHashMap<ID<?, ?>, Long> ourIndexIdToCreationStamp = new ConcurrentHashMap<ID<?, ?>, Long>();
   private static volatile long ourLastStamp; // ensure any file index stamp increases
 
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
index ebb7911..6427765 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -354,7 +354,7 @@
         FileContent fileContent = (FileContent)content;
         hashId = getHashOfContent(fileContent);
         if (doReadSavedPersistentData) {
-          if (!myContents.isBusyReading()) { // avoid blocking read, we can calculate index value
+          if (!myContents.isBusyReading() || DebugAssertions.EXTRA_SANITY_CHECKS) { // avoid blocking read, we can calculate index value
             ByteSequence bytes = myContents.get(hashId);
             if (bytes != null) {
               data = deserializeSavedPersistentData(bytes);
@@ -367,7 +367,7 @@
                     "Unexpected difference in indexing of %s by index %s, file type %s, charset %s\ndiff %s\nprevious indexed info %s",
                     fileContent.getFile(),
                     myIndexId,
-                    fileContent.getFileType(),
+                    fileContent.getFileType().getName(),
                     ((FileContentImpl)fileContent).getCharset(),
                     buildDiff(data, contentData),
                     myIndexingTrace.get(hashId)
@@ -396,7 +396,7 @@
 
           FileContent fileContent = (FileContent)content;
           try {
-            myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType()+"," + fileContent.getFile().getPath() + "," +
+            myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType().getName()+"," + fileContent.getFile().getPath() + "," +
                                         ExceptionUtil.getThrowableText(new Throwable()));
           } catch (IOException ex) {
             LOG.error(ex);
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
index 18961ca..fcbaa21 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
 package com.intellij.webcore.packaging;
 
 import com.intellij.icons.AllIcons;
@@ -93,6 +108,7 @@
           public void run() {
             try {
               myController.reloadAllPackages();
+              initModel();
               myPackages.setPaintBusy(false);
             }
             catch (final IOException e) {
@@ -310,6 +326,7 @@
             @Override
             public void run() {
               myPackages.setModel(myPackagesModel);
+              ((MyPackageFilter)myFilter).filter();
               doSelectPackage(mySelectedPackageName);
               setDownloadStatus(false);
             }
@@ -473,6 +490,7 @@
       final Object pyPackage = myPackages.getSelectedValue();
       if (pyPackage instanceof RepoPackage) {
         final String packageName = ((RepoPackage)pyPackage).getName();
+        mySelectedPackageName = packageName;
         myVersionComboBox.removeAllItems();
         if (myVersionCheckBox.isEnabled()) {
           myController.fetchPackageVersions(packageName, new CatchingConsumer<List<String>, Exception>() {
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
index cb281cb..1513bb4 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
@@ -8,6 +8,7 @@
 import com.intellij.ui.HyperlinkAdapter;
 import com.intellij.ui.ScrollPaneFactory;
 import com.intellij.ui.components.JBLabel;
+import com.intellij.util.ui.SwingHelper;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -22,18 +23,17 @@
  * @author yole
  */
 public class PackagesNotificationPanel {
-  private final JEditorPane myEditorPane = new MyNotificationPane();
   private final Project myProject;
+  private final JEditorPane myHtmlViewer;
   private final Map<String, Runnable> myLinkHandlers = new HashMap<String, Runnable>();
   private String myErrorTitle;
   private String myErrorDescription;
 
-  public PackagesNotificationPanel(Project project) {
+  public PackagesNotificationPanel(@NotNull Project project) {
     myProject = project;
-    myEditorPane.setBackground(UIManager.getColor("ArrowButton.background"));
-    myEditorPane.setContentType("text/html");
-    myEditorPane.setEditable(false);
-    myEditorPane.addHyperlinkListener(new HyperlinkAdapter() {
+    myHtmlViewer = SwingHelper.createHtmlViewer(true, null, null, null);
+    myHtmlViewer.setVisible(false);
+    myHtmlViewer.addHyperlinkListener(new HyperlinkAdapter() {
       @Override
       protected void hyperlinkActivated(HyperlinkEvent e) {
         final Runnable handler = myLinkHandlers.get(e.getDescription());
@@ -76,11 +76,18 @@
 
   public void showResult(String packageName, @Nullable String errorDescription) {
     if (StringUtil.isEmpty(errorDescription)) {
-      showSuccess("Package successfully installed.");
+      String message = "Package installed successfully";
+      if (packageName != null) {
+        message = "Package '" + packageName + "' installed successfully";
+      }
+      showSuccess(message);
     }
     else {
-      String title = "Install packages failed";
-      final String firstLine = title + ": Error occurred when installing package " + packageName + ". ";
+      String title = "Failed to install packages";
+      if (packageName != null) {
+        title = "Failed to install package '" + packageName + "'";
+      }
+      String firstLine = "Error occurred when installing package '" + packageName + "'. ";
       showError(firstLine + "<a href=\"xxx\">Details...</a>",
                 title,
                 firstLine + errorDescription);
@@ -96,19 +103,18 @@
   }
 
   public JComponent getComponent() {
-    return myEditorPane;
+    return myHtmlViewer;
   }
 
   public void showSuccess(String text) {
     showContent(text, MessageType.INFO.getPopupBackground());
   }
 
-  private void showContent(String text, final Color background) {
-    myEditorPane.removeAll();
+  private void showContent(@NotNull String text, @NotNull Color background) {
     String htmlText = text.startsWith("<html>") ? text : UIUtil.toHtml(text);
-    myEditorPane.setText(htmlText);
-    myEditorPane.setBackground(background);
-    myEditorPane.setVisible(true);
+    myHtmlViewer.setText(htmlText);
+    myHtmlViewer.setBackground(background);
+    setVisibleEditorPane(true);
     myErrorTitle = null;
     myErrorDescription = null;
   }
@@ -124,24 +130,22 @@
   }
 
   public void hide() {
-    myEditorPane.setVisible(false);
+    setVisibleEditorPane(false);
+  }
+
+  private void setVisibleEditorPane(boolean visible) {
+    boolean oldVisible = myHtmlViewer.isVisible();
+    myHtmlViewer.setVisible(visible);
+    if (oldVisible != visible) {
+      myHtmlViewer.revalidate();
+      myHtmlViewer.repaint();
+    }
   }
 
   public boolean hasLinkHandler(String key) {
     return myLinkHandlers.containsKey(key);
   }
 
-  private static class MyNotificationPane extends JEditorPane {
-    @Override
-    public Dimension getPreferredSize() {
-      // This trick makes text component to carry text over to the next line
-      // iff the text line width exceeds parent's width
-      Dimension dimension = super.getPreferredSize();
-      dimension.width = 0;
-      return dimension;
-    }
-  }
-
   public void removeLinkHandler(String key) {
     myLinkHandlers.remove(key);
   }
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
new file mode 100644
index 0000000..f1733f5
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
@@ -0,0 +1,4 @@
+class A {
+  void foo() {
+  }
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
new file mode 100644
index 0000000..5fd4239
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
@@ -0,0 +1,5 @@
+class A {
+  void foo() {
+  }
+
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
new file mode 100644
index 0000000..3284439
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
@@ -0,0 +1,3 @@
+class Foo {
+  int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
new file mode 100644
index 0000000..2576608
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
@@ -0,0 +1,4 @@
+class Foo {
+  int
+  <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
new file mode 100644
index 0000000..3284439
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
@@ -0,0 +1,3 @@
+class Foo {
+  int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
new file mode 100644
index 0000000..29e2260
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
@@ -0,0 +1,4 @@
+class Foo {
+  int
+<caret>  i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
new file mode 100644
index 0000000..3284439
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
@@ -0,0 +1,3 @@
+class Foo {
+  int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
new file mode 100644
index 0000000..6c1bbe8
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
@@ -0,0 +1,4 @@
+class Foo {
+  int
+<caret>i;
+}
diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
new file mode 100644
index 0000000..f51179d
--- /dev/null
+++ b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.io.IOException;
+
+public class IndentingBackspaceHandlerUncommittedDocumentTest extends LightPlatformCodeInsightTestCase {
+  public void testSequentialBackspaceInvocation() throws IOException {
+    configureFromFileText(getTestName(false) + ".java",
+                          "class Foo {\n" +
+                          "\n" +
+                          "\n" +
+                          "<caret>}");
+    backspace();
+    backspace();
+    checkResultByText("class Foo {\n" +
+                      "<caret>}");
+  }
+
+  public void testMulticaretSequentialBackspaceInvocation() throws IOException {
+    configureFromFileText(getTestName(false) + ".java",
+                          "class Foo {\n" +
+                          "    void m1() {\n" +
+                          "    \n" +
+                          "    <caret>}\n" +
+                          "    void m2() {\n" +
+                          "    \n" +
+                          "    <caret>}\n" +
+                          "}");
+    backspace();
+    backspace();
+    checkResultByText("class Foo {\n" +
+                      "    void m1() {<caret>}\n" +
+                      "    void m2() {<caret>}\n" +
+                      "}");
+  }
+}
\ No newline at end of file
diff --git a/platform/lvcs-impl/src/com/intellij/history/core/Paths.java b/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
index 440fd69..bd98591 100644
--- a/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
+++ b/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
@@ -67,9 +67,18 @@
   }
 
   public static Iterable<String> split(String path) {
-    Iterable<String> result = StringUtil.tokenize(path, String.valueOf(DELIM));
-    if (path.indexOf(DELIM) == 0) {
-      result = ContainerUtil.concat(Collections.singleton(String.valueOf(DELIM)), result);
+    //must be consistent with LocalFileSystemBase.extractRootPath()
+    int prefixLen = 0;
+    if (path.startsWith("//")) {
+      prefixLen = path.indexOf(DELIM, 2);
+      if (prefixLen == -1) prefixLen = path.length();
+    }
+    else if (StringUtil.startsWithChar(path, DELIM)) {
+      prefixLen = 1;
+    }
+    Iterable<String> result = StringUtil.tokenize(path.substring(prefixLen), String.valueOf(DELIM));
+    if (prefixLen > 0) {
+      result = ContainerUtil.concat(Collections.singleton(path.substring(0, prefixLen)), result);
     }
     return result;
   }
diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
index 90308f5..cd1d1b0 100644
--- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
+++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
@@ -20,6 +20,7 @@
 import com.intellij.ide.browsers.BrowserLauncher;
 import com.intellij.ide.browsers.BrowserLauncherAppless;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -106,6 +107,10 @@
     getBrowserLauncher().browse(uri);
   }
 
+  public static void browse(@NotNull String url, @Nullable Project project) {
+    getBrowserLauncher().browse(url, null, project);
+  }
+
   @SuppressWarnings("UnusedDeclaration")
   @NotNull
   @Deprecated
@@ -145,6 +150,9 @@
     else if (SystemInfo.isMac) {
       return "open";
     }
+    else if (SystemInfo.isUnix) {
+      return "/usr/bin/firefox";
+    }
     else {
       return "";
     }
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
index f6826b5..f767ec9 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
@@ -35,9 +35,9 @@
   private final Icon myIcon;
 
   BrowserFamily(@NotNull String name,
-                @NotNull final String windowsPath,
-                @Nullable final String unixPath,
-                @Nullable final String macPath,
+                @NotNull String windowsPath,
+                @Nullable String unixPath,
+                @Nullable String macPath,
                 @NotNull Icon icon) {
     myName = name;
     myWindowsPath = windowsPath;
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
index 0c34152..736dcd8 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
@@ -74,10 +74,10 @@
            Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action);
   }
 
-  public static boolean canStartDefaultBrowser() {
+  public static boolean canUseSystemDefaultBrowserPolicy() {
     return isDesktopActionSupported(Desktop.Action.BROWSE) ||
            SystemInfo.isMac || SystemInfo.isWindows ||
-           SystemInfo.isUnix && SystemInfo.hasXdgOpen();
+           (SystemInfo.isUnix && SystemInfo.hasXdgOpen());
   }
 
   private static GeneralSettings getGeneralSettingsInstance() {
@@ -109,7 +109,7 @@
 
   @Override
   public void open(@NotNull String url) {
-    openOrBrowse(url, false);
+    openOrBrowse(url, false, null);
   }
 
   @Override
@@ -119,6 +119,10 @@
 
   @Override
   public void browse(@NotNull URI uri) {
+    browse(uri, null);
+  }
+
+  public void browse(@NotNull URI uri, @Nullable Project project) {
     LOG.debug("Launch browser: [" + uri + "]");
 
     GeneralSettings settings = getGeneralSettingsInstance();
@@ -136,15 +140,19 @@
 
       List<String> command = getDefaultBrowserCommand();
       if (command != null) {
-        doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY, null);
+        doLaunch(uri.toString(), command, null, project, ArrayUtil.EMPTY_STRING_ARRAY, null);
         return;
       }
     }
 
-    browseUsingPath(uri.toString(), settings.getBrowserPath(), null, null, ArrayUtil.EMPTY_STRING_ARRAY);
+    browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project);
   }
 
-  private void openOrBrowse(@NotNull String url, boolean browse) {
+  protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) {
+    browseUsingPath(uri.toString(), settings.getBrowserPath(), null, project, ArrayUtil.EMPTY_STRING_ARRAY);
+  }
+
+  private void openOrBrowse(@NotNull String url, boolean browse, @Nullable Project project) {
     url = url.trim();
 
     if (url.startsWith("jar:")) {
@@ -181,7 +189,7 @@
     }
 
     if (uri == null) {
-      doShowError(IdeBundle.message("error.malformed.url", url), null, null, null, null);
+      doShowError(IdeBundle.message("error.malformed.url", url), null, project, null, null);
     }
     else {
       browse(uri);
@@ -380,7 +388,7 @@
   @Override
   public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) {
     if (browser == null) {
-      openOrBrowse(url, true);
+      openOrBrowse(url, true, project);
     }
     else {
       for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) {
@@ -436,8 +444,8 @@
 
   private boolean doLaunch(@Nullable String url,
                            @NotNull List<String> command,
-                           @Nullable final WebBrowser browser,
-                           @Nullable final Project project,
+                           @Nullable WebBrowser browser,
+                           @Nullable Project project,
                            @NotNull String[] additionalParameters,
                            @Nullable Runnable launchTask) {
     GeneralCommandLine commandLine = new GeneralCommandLine(command);
@@ -454,7 +462,13 @@
       commandLine.addParameter(url);
     }
 
-    addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters);
+    final BrowserSpecificSettings browserSpecificSettings = browser == null ? null : browser.getSpecificSettings();
+    if (browserSpecificSettings != null) {
+      commandLine.getEnvironment().putAll(browserSpecificSettings.getEnvironmentVariables());
+    }
+
+    addArgs(commandLine, browserSpecificSettings, additionalParameters);
+
     try {
       Process process = commandLine.createProcess();
       checkCreatedProcess(browser, project, commandLine, process, launchTask);
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
index 826ca80..b7fd90e 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
@@ -20,6 +20,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 public abstract class BrowserSpecificSettings implements Cloneable {
   @NotNull
@@ -30,6 +31,11 @@
     return Collections.emptyList();
   }
 
+  @NotNull
+  public Map<String, String> getEnvironmentVariables() {
+    return Collections.emptyMap();
+  }
+
   @Override
   public BrowserSpecificSettings clone() {
     try {
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
index b6ca3e7..555097b 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
@@ -21,7 +21,9 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.PathUtil;
 import com.intellij.util.execution.ParametersListUtil;
+import com.intellij.util.xmlb.annotations.MapAnnotation;
 import com.intellij.util.xmlb.annotations.Tag;
+import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -33,6 +35,7 @@
   private @Nullable String myCommandLineOptions;
   private @Nullable String myUserDataDirectoryPath;
   private boolean myUseCustomProfile;
+  private @NotNull THashMap<String, String> myEnvironmentVariables = new THashMap<String, String>();
 
   public ChromeSettings() {
   }
@@ -85,6 +88,18 @@
     return cliOptions;
   }
 
+  @Override
+  @NotNull
+  @Tag("environment-variables")
+  @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false)
+  public THashMap<String, String> getEnvironmentVariables() {
+    return myEnvironmentVariables;
+  }
+
+  public void setEnvironmentVariables(@NotNull final THashMap<String, String> environmentVariables) {
+    myEnvironmentVariables = environmentVariables;
+  }
+
   @NotNull
   @Override
   public ChromeSettingsConfigurable createConfigurable() {
@@ -92,6 +107,13 @@
   }
 
   @Override
+  public ChromeSettings clone() {
+    ChromeSettings clone = (ChromeSettings)super.clone();
+    clone.myEnvironmentVariables = myEnvironmentVariables.clone();
+    return clone;
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (this == o) {
       return true;
@@ -103,6 +125,7 @@
     ChromeSettings settings = (ChromeSettings)o;
     return myUseCustomProfile == settings.myUseCustomProfile &&
            Comparing.equal(myCommandLineOptions, settings.myCommandLineOptions) &&
-           (!myUseCustomProfile || Comparing.equal(myUserDataDirectoryPath, settings.myUserDataDirectoryPath));
+           (!myUseCustomProfile || Comparing.equal(myUserDataDirectoryPath, settings.myUserDataDirectoryPath)) &&
+           myEnvironmentVariables.equals(settings.myEnvironmentVariables);
   }
 }
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
index ef95f7c..c28b7e4 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
@@ -26,7 +26,6 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.DocumentAdapter;
-import com.intellij.util.ObjectUtils;
 import com.intellij.util.PathUtil;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.Nullable;
@@ -48,7 +47,7 @@
   private final FirefoxSettings mySettings;
   private String myLastProfilesIniPath;
   private String myDefaultProfilesIniPath;
-  private String myDefaultProfile;
+  private String defaultProfile;
 
   public FirefoxSettingsConfigurable(FirefoxSettings settings) {
     mySettings = settings;
@@ -89,11 +88,8 @@
 
   @Nullable
   private String getConfiguredProfileName() {
-    final String selected = (String)myProfileCombobox.getSelectedItem();
-    if (Comparing.equal(myDefaultProfile, selected)) {
-      return null;
-    }
-    return selected;
+    String selected = (String)myProfileCombobox.getSelectedItem();
+    return Comparing.equal(defaultProfile, selected) ? null : selected;
   }
 
   @Override
@@ -110,7 +106,9 @@
     String path = mySettings.getProfilesIniPath();
     myProfilesIniPathField.setText(path != null ? FileUtilRt.toSystemDependentName(path) : myDefaultProfilesIniPath);
     updateProfilesList();
-    myProfileCombobox.setSelectedItem(ObjectUtils.notNull(mySettings.getProfile(), myDefaultProfile));
+
+    String profile = mySettings.getProfile();
+    myProfileCombobox.setSelectedItem(profile == null ? defaultProfile : profile);
   }
 
   private void updateProfilesList() {
@@ -122,7 +120,7 @@
     myProfileCombobox.removeAllItems();
     final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath));
     final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles);
-    myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
+    this.defaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
     for (FirefoxProfile profile : profiles) {
       //noinspection unchecked
       myProfileCombobox.addItem(profile.getName());
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
index 1d4fea4..049bde5 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
@@ -36,6 +36,8 @@
   @NonNls String ACTION_EDITOR_SELECT_WORD_AT_CARET = "EditorSelectWord";
   @NonNls String ACTION_EDITOR_UNSELECT_WORD_AT_CARET = "EditorUnSelectWord";
   @NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace";
+  @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection";
+  @NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection";
   @NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp";
   @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft";
   @NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown";
@@ -269,7 +271,7 @@
   String ACTION_UNDO = "$Undo";
   String ACTION_REDO = "$Redo";
   String GROUP_REFACTOR = "RefactoringMenu";
-  String SELECTED_CHANGES_ROLLBACK = "RollbackLineStatusChanges";
+  String SELECTED_CHANGES_ROLLBACK = "Vcs.RollbackChangedLines";
   String CHANGES_VIEW_ROLLBACK = "ChangesView.Rollback";
 
   String CONSOLE_CLEAR_ALL = "ConsoleView.ClearAll";
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
index 92a1d9c..7398bf7 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
@@ -110,10 +110,10 @@
     private boolean myMouseInside = false;
     private JBPopup myPopup;
     private boolean myForceTransparent = false;
-    private Boolean myForceEnabled = null;
 
     public ComboBoxButton(Presentation presentation) {
       myPresentation = presentation;
+      setEnabled(myPresentation.isEnabled());
       setModel(new MyButtonModel());
       setHorizontalAlignment(LEFT);
       setFocusable(false);
@@ -207,12 +207,6 @@
       }
     }
 
-    @Override
-    public void setEnabled(final boolean enabled) {
-      super.setEnabled(enabled);
-      myForceEnabled = enabled;
-    }
-
     public void setForceTransparent(boolean transparent) {
       myForceTransparent = transparent;
     }
@@ -282,7 +276,6 @@
 
     private void initButton() {
       setIcon(myPresentation.getIcon());
-      setEnabled(myPresentation.isEnabled());
       setText(myPresentation.getText());
       updateTooltipText(myPresentation.getDescription());
       updateButtonSize();
@@ -383,7 +376,7 @@
       final Dimension size = getSize();
       final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
 
-      final Color textColor = (myForceEnabled == null ? myPresentation.isEnabled() : myForceEnabled)
+      final Color textColor = isEnabled()
                       ? UIManager.getColor("Panel.foreground")
                       : UIUtil.getInactiveTextColor();
       if (myForceTransparent) {
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
index 78f07a0..e2c9175 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff;
 
 import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
@@ -59,4 +60,12 @@
                                                      Project project,
                                                      @Nullable ActionButtonPresentation okButtonPresentation,
                                                      @Nullable ActionButtonPresentation cancelButtonPresentation);
+
+  public abstract MergeRequest create3WayDiffRequest(String leftText,
+                                                     String rightText,
+                                                     String originalContent,
+                                                     @Nullable FileType type,
+                                                     Project project,
+                                                     @Nullable ActionButtonPresentation okButtonPresentation,
+                                                     @Nullable ActionButtonPresentation cancelButtonPresentation);
 }
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
index 2653731..d630bad 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
@@ -41,18 +41,28 @@
   private final FileType myType;
   private final MyDocumentsSynchronizer mySynchonizer;
   public static final Key<Document> ORIGINAL_DOCUMENT = new Key<Document>("ORIGINAL_DOCUMENT");
+  private final boolean myForceReadOnly;
 
   public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file) {
-    this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null);
+    this(original, range, project, file, false);
+  }
+
+  public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file, boolean forceReadOnly) {
+    this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null, forceReadOnly);
   }
 
   public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType) {
+    this(original, range, project, fileType, false);
+  }
+
+  public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType, boolean forceReadOnly) {
     RangeMarker rangeMarker = original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true);
     rangeMarker.setGreedyToLeft(true);
     rangeMarker.setGreedyToRight(true);
     mySynchonizer = new MyDocumentsSynchronizer(project, rangeMarker);
     myOriginal = original;
     myType = fileType;
+    myForceReadOnly = forceReadOnly;
   }
 
   public FragmentContent(DiffContent original, TextRange range, Project project) {
@@ -152,7 +162,7 @@
       String textInRange =
         originalDocument.getCharsSequence().subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()).toString();
       final Document result = EditorFactory.getInstance().createDocument(textInRange);
-      result.setReadOnly(!originalDocument.isWritable());
+      result.setReadOnly(myForceReadOnly || !originalDocument.isWritable());
       result.putUserData(ORIGINAL_DOCUMENT, originalDocument);
       return result;
     }
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
index 29243f7..ce8d560 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
@@ -25,7 +25,7 @@
  * @see DiffRequestFactory#createMergeRequest
  */
 public abstract class MergeRequest extends DiffRequest {
-  protected MergeRequest(Project project) {
+  protected MergeRequest(@Nullable Project project) {
     super(project);
   }
 
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java b/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java
deleted file mode 100644
index 7095080..0000000
--- a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.openapi.editor;
-
-import com.intellij.codeInsight.editorActions.TextBlockTransferable;
-import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.ide.CopyPasteManager;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.text.LineTokenizer;
-import com.intellij.util.Producer;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.StringSelection;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-public class CopyPasteSupport {
-  private static final Logger LOG = Logger.getInstance(CopyPasteSupport.class);
-
-  private CopyPasteSupport() { }
-
-  public static void copySelectionToClipboard(@NotNull Editor editor) {
-    ApplicationManager.getApplication().assertIsDispatchThread();
-    List<TextBlockTransferableData> extraData = new ArrayList<TextBlockTransferableData>();
-    String s = editor.getCaretModel().supportsMultipleCarets() ? getSelectedTextForClipboard(editor, extraData)
-                                                               : editor.getSelectionModel().getSelectedText();
-    if (s == null) return;
-
-    s = TextBlockTransferable.convertLineSeparators(s, "\n", extraData);
-    Transferable contents = editor.getCaretModel().supportsMultipleCarets() ? new TextBlockTransferable(s, extraData, null) : new StringSelection(s);
-    CopyPasteManager.getInstance().setContents(contents);
-  }
-
-  public static String getSelectedTextForClipboard(@NotNull Editor editor, @NotNull Collection<TextBlockTransferableData> extraDataCollector) {
-    final StringBuilder buf = new StringBuilder();
-    String separator = "";
-    List<Caret> carets = editor.getCaretModel().getAllCarets();
-    int[] startOffsets = new int[carets.size()];
-    int[] endOffsets = new int[carets.size()];
-    for (int i = 0; i < carets.size(); i++) {
-      buf.append(separator);
-      String caretSelectedText = carets.get(i).getSelectedText();
-      startOffsets[i] = buf.length();
-      if (caretSelectedText != null) {
-        buf.append(caretSelectedText);
-      }
-      endOffsets[i] = buf.length();
-      separator = "\n";
-    }
-    extraDataCollector.add(new CaretStateTransferableData(startOffsets, endOffsets));
-    return buf.toString();
-  }
-
-
-  public static TextRange pasteFromClipboard(Editor editor) {
-    return pasteTransferable(editor, (Producer<Transferable>)null);
-  }
-
-  public static TextRange pasteTransferable(Editor editor, final Transferable content) {
-    return pasteTransferable(editor, new Producer<Transferable>() {
-      @Nullable
-      @Override
-      public Transferable produce() {
-        return content;
-      }
-    });
-  }
-
-  @Nullable
-  public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) {
-    Transferable content = getTransferable(producer);
-    if (content == null) return null;
-    String text = getStringContent(content);
-    if (text == null) return null;
-
-    if (editor.getCaretModel().supportsMultipleCarets()) {
-      int caretCount = editor.getCaretModel().getCaretCount();
-      if (caretCount == 1 && editor.isColumnMode()) {
-        int pastedLineCount = LineTokenizer.calcLineCount(text, true);
-        EditorModificationUtil.deleteSelectedText(editor);
-        Caret caret = editor.getCaretModel().getPrimaryCaret();
-        for (int i = 0; i < pastedLineCount - 1; i++) {
-          caret = caret.clone(false);
-          if (caret == null) {
-            break;
-          }
-        }
-        caretCount = editor.getCaretModel().getCaretCount();
-      }
-      CaretStateTransferableData caretData = null;
-      try {
-        caretData = content.isDataFlavorSupported(CaretStateTransferableData.FLAVOR)
-                    ? (CaretStateTransferableData)content.getTransferData(CaretStateTransferableData.FLAVOR) : null;
-      }
-      catch (Exception e) {
-        LOG.error(e);
-      }
-      final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretData, caretCount).iterator();
-      editor.getCaretModel().runForEachCaret(new CaretAction() {
-        @Override
-        public void perform(Caret caret) {
-          EditorModificationUtil.insertStringAtCaret(editor, segments.next(), false, true);
-        }
-      });
-      return null;
-    }
-    else {
-      int caretOffset = editor.getCaretModel().getOffset();
-      EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
-      return new TextRange(caretOffset, caretOffset + text.length());
-    }
-  }
-
-  public static void pasteTransferableAsBlock(Editor editor, @Nullable Producer<Transferable> producer) {
-    Transferable content = getTransferable(producer);
-    if (content == null) return;
-    String text = getStringContent(content);
-    if (text == null) return;
-
-    int caretLine = editor.getCaretModel().getLogicalPosition().line;
-    int originalCaretLine = caretLine;
-    int selectedLinesCount = 0;
-
-    final SelectionModel selectionModel = editor.getSelectionModel();
-    if (selectionModel.hasBlockSelection()) {
-      final LogicalPosition start = selectionModel.getBlockStart();
-      final LogicalPosition end = selectionModel.getBlockEnd();
-      assert start != null;
-      assert end != null;
-      LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
-      selectedLinesCount = Math.abs(end.line - start.line);
-      caretLine = caret.line;
-
-      EditorModificationUtil.deleteSelectedText(editor);
-      editor.getCaretModel().moveToLogicalPosition(caret);
-    }
-
-    LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
-
-    String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
-    if (lines.length > 1 || selectedLinesCount == 0) {
-      int longestLineLength = 0;
-      for (int i = 0; i < lines.length; i++) {
-        String line = lines[i];
-        longestLineLength = Math.max(longestLineLength, line.length());
-        editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
-        EditorModificationUtil.insertStringAtCaret(editor, line, false, true);
-      }
-      caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
-    }
-    else {
-      for (int i = 0; i <= selectedLinesCount; i++) {
-        editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
-        EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
-      }
-      caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + text.length());
-    }
-
-    editor.getCaretModel().moveToLogicalPosition(caretToRestore);
-    EditorModificationUtil.zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
-  }
-
-  @Nullable
-  private static String getStringContent(@NotNull Transferable content) {
-    RawText raw = RawText.fromTransferable(content);
-    if (raw != null) return raw.rawText;
-
-    try {
-      return (String)content.getTransferData(DataFlavor.stringFlavor);
-    }
-    catch (UnsupportedFlavorException ignore) { }
-    catch (IOException ignore) { }
-
-    return null;
-  }
-
-  private static Transferable getTransferable(Producer<Transferable> producer) {
-    Transferable content = null;
-    if (producer != null) {
-      content = producer.produce();
-    }
-    else {
-      CopyPasteManager manager = CopyPasteManager.getInstance();
-      if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
-        content = manager.getContents();
-      }
-    }
-    return content;
-  }
-}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java
new file mode 100644
index 0000000..f698d34
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.datatransfer.Transferable;
+
+/**
+ * Support for data transfer between editor and clipboard.
+ */
+public abstract class EditorCopyPasteHelper {
+  public static EditorCopyPasteHelper getInstance() {
+    return ServiceManager.getService(EditorCopyPasteHelper.class);
+  }
+
+  /**
+   * Copies text selected in editor to clipboard.
+   */
+  public abstract void copySelectionToClipboard(@NotNull Editor editor);
+
+  /**
+   * Pastes from clipboard into editor at caret(s) position.
+   *
+   * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise
+   */
+  @Nullable
+  public abstract TextRange[] pasteFromClipboard(@NotNull Editor editor);
+
+  /**
+   * Pastes given Transferable instance into editor at caret(s) position.
+   *
+   * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise
+   */
+  @Nullable
+  public abstract TextRange[] pasteTransferable(@NotNull Editor editor, @NotNull Transferable content);
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
index ee55279..6ba31d7 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
@@ -19,14 +19,19 @@
 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
 import com.intellij.openapi.editor.event.DocumentEvent;
 import com.intellij.openapi.editor.event.MockDocumentEvent;
+import com.intellij.openapi.ide.CopyPasteManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.LineTokenizer;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.util.Producer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
 import java.util.List;
 
 public class EditorModificationUtil {
@@ -176,22 +181,100 @@
   }
 
   /**
-   * @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferable(Editor, com.intellij.util.Producer)} instead.
+   * @deprecated Use {@link com.intellij.openapi.editor.EditorCopyPasteHelper} methods instead.
    * (to remove in IDEA 15)
    */
   @Nullable
   public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) {
-    return CopyPasteSupport.pasteTransferable(editor, producer);
+    EditorCopyPasteHelper helper = EditorCopyPasteHelper.getInstance();
+    if (producer == null) {
+      TextRange[] ranges = helper.pasteFromClipboard(editor);
+      return ranges != null && ranges.length == 1 ? ranges[0] : null;
+    }
+    Transferable transferable = producer.produce();
+    if (transferable == null) {
+      return null;
+    }
+    TextRange[] ranges = helper.pasteTransferable(editor, transferable);
+    return ranges != null && ranges.length == 1 ? ranges[0] : null;
   }
 
-  /**
-   * @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferableAsBlock(Editor, com.intellij.util.Producer)} instead.
-   * (to remove in IDEA 15)
-   */
   public static void pasteTransferableAsBlock(Editor editor, @Nullable Producer<Transferable> producer) {
-    CopyPasteSupport.pasteTransferableAsBlock(editor, producer);
+    Transferable content = getTransferable(producer);
+    if (content == null) return;
+    String text = getStringContent(content);
+    if (text == null) return;
+
+    int caretLine = editor.getCaretModel().getLogicalPosition().line;
+    int originalCaretLine = caretLine;
+    int selectedLinesCount = 0;
+
+    final SelectionModel selectionModel = editor.getSelectionModel();
+    if (selectionModel.hasBlockSelection()) {
+      final LogicalPosition start = selectionModel.getBlockStart();
+      final LogicalPosition end = selectionModel.getBlockEnd();
+      assert start != null;
+      assert end != null;
+      LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
+      selectedLinesCount = Math.abs(end.line - start.line);
+      caretLine = caret.line;
+
+      deleteSelectedText(editor);
+      editor.getCaretModel().moveToLogicalPosition(caret);
+    }
+
+    LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
+
+    String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
+    if (lines.length > 1 || selectedLinesCount == 0) {
+      int longestLineLength = 0;
+      for (int i = 0; i < lines.length; i++) {
+        String line = lines[i];
+        longestLineLength = Math.max(longestLineLength, line.length());
+        editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+        insertStringAtCaret(editor, line, false, true);
+      }
+      caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
+    }
+    else {
+      for (int i = 0; i <= selectedLinesCount; i++) {
+        editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+        insertStringAtCaret(editor, text, false, true);
+      }
+      caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + text.length());
+    }
+
+    editor.getCaretModel().moveToLogicalPosition(caretToRestore);
+    zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
   }
 
+  @Nullable
+  private static String getStringContent(@NotNull Transferable content) {
+    RawText raw = RawText.fromTransferable(content);
+    if (raw != null) return raw.rawText;
+
+    try {
+      return (String)content.getTransferData(DataFlavor.stringFlavor);
+    }
+    catch (UnsupportedFlavorException ignore) { }
+    catch (IOException ignore) { }
+
+    return null;
+  }
+
+  private static Transferable getTransferable(Producer<Transferable> producer) {
+    Transferable content = null;
+    if (producer != null) {
+      content = producer.produce();
+    }
+    else {
+      CopyPasteManager manager = CopyPasteManager.getInstance();
+      if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+        content = manager.getContents();
+      }
+    }
+    return content;
+  }
   /**
    * Calculates difference in columns between current editor caret position and end of the logical line fragment displayed
    * on a current visual line.
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
index 3780e3a..942a33a 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
@@ -15,276 +15,19 @@
  */
 package com.intellij.openapi.editor;
 
-import com.intellij.codeStyle.CodeStyleFacade;
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.WeakList;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import java.util.List;
-
-public class LazyRangeMarkerFactory {
-  private final Project myProject;
-  private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY");
-
+public abstract class LazyRangeMarkerFactory {
   public static LazyRangeMarkerFactory getInstance(Project project) {
     return ServiceManager.getService(project, LazyRangeMarkerFactory.class);
   }
 
-  public LazyRangeMarkerFactory(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
-    myProject = project;
-
-    EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
-      @Override
-      public void beforeDocumentChange(DocumentEvent e) {
-        transformRangeMarkers(e);
-      }
-
-      @Override
-      public void documentChanged(DocumentEvent e) {
-        transformRangeMarkers(e);
-      }
-
-      private void transformRangeMarkers(@NotNull DocumentEvent e) {
-        Document document = e.getDocument();
-        VirtualFile file = fileDocumentManager.getFile(document);
-        if (file == null) {
-          return;
-        }
-
-        WeakList<LazyMarker> lazyMarkers = file.getUserData(LAZY_MARKERS_KEY);
-        if (lazyMarkers == null) {
-          return;
-        }
-
-        List<LazyMarker> markers = lazyMarkers.toStrongList();
-        List<LazyMarker> markersToRemove = null;
-        for (LazyMarker marker : markers) {
-          if (file.equals(marker.getFile()) && marker.documentChanged(document) != null) {
-            if (markersToRemove == null) {
-              markersToRemove = new SmartList<LazyMarker>();
-            }
-            markersToRemove.add(marker);
-          }
-        }
-        if (markersToRemove != null) {
-          lazyMarkers.removeAll(markersToRemove);
-        }
-      }
-    }, project);
-  }
-
-  private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
-    WeakList<LazyMarker> markers = file.getUserData(LAZY_MARKERS_KEY);
-
-    if (markers == null) {
-      markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
-    }
-    markers.add(marker);
-  }
+  @NotNull
+  public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset);
 
   @NotNull
-  public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) {
-    return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
-      @Override
-      public RangeMarker compute() {
-        // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor
-        final LazyMarker marker = new OffsetLazyMarker(file, offset);
-        addToLazyMarkersList(marker, file);
-        return marker;
-      }
-    });
-  }
-
-  @NotNull
-  public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) {
-    return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
-      @Override
-      public RangeMarker compute() {
-        final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
-        if (document != null) {
-          final int offset = calculateOffset(myProject, file, document, line, column);
-          return document.createRangeMarker(offset, offset, persistent);
-        }
-
-        final LazyMarker marker = new LineColumnLazyMarker(file, line, column);
-        addToLazyMarkersList(marker, file);
-        return marker;
-      }
-    });
-  }
-
-  private abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker {
-    private RangeMarker myDelegate;
-    private final VirtualFile myFile;
-    protected final int myInitialOffset;
-
-    private LazyMarker(@NotNull VirtualFile file, int offset) {
-      myFile = file;
-      myInitialOffset = offset;
-    }
-
-    @NotNull
-    public VirtualFile getFile() {
-      return myFile;
-    }
-
-    @Nullable
-    protected final RangeMarker getOrCreateDelegate() {
-      if (myDelegate == null) {
-        Document document = FileDocumentManager.getInstance().getDocument(myFile);
-        if (document == null) {
-          return null;
-        }
-        myDelegate = createDelegate(myFile, document);
-      }
-      return myDelegate;
-    }
-
-    @Nullable
-    protected final RangeMarker documentChanged(@NotNull Document document) {
-      if (myDelegate == null) {
-        myDelegate = createDelegate(myFile, document);
-      }
-      return myDelegate;
-    }
-
-    @Nullable
-    protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
-
-    @Override
-    @NotNull
-    public Document getDocument() {
-      RangeMarker delegate = getOrCreateDelegate();
-      if (delegate == null) {
-        //noinspection ConstantConditions
-        return FileDocumentManager.getInstance().getDocument(myFile);
-      }
-      return delegate.getDocument();
-    }
-
-    @Override
-    public int getStartOffset() {
-      return myDelegate == null ? myInitialOffset : myDelegate.getStartOffset();
-    }
-
-
-    @Override
-    public int getEndOffset() {
-      return myDelegate == null ? myInitialOffset : myDelegate.getEndOffset();
-    }
-
-    @Override
-    public boolean isValid() {
-      RangeMarker delegate = getOrCreateDelegate();
-      return delegate != null && delegate.isValid();
-    }
-
-    @Override
-    public void setGreedyToLeft(boolean greedy) {
-      getOrCreateDelegate().setGreedyToLeft(greedy);
-    }
-
-    @Override
-    public void setGreedyToRight(boolean greedy) {
-      getOrCreateDelegate().setGreedyToRight(greedy);
-    }
-
-    @Override
-    public boolean isGreedyToRight() {
-      return getOrCreateDelegate().isGreedyToRight();
-    }
-
-    @Override
-    public boolean isGreedyToLeft() {
-      return getOrCreateDelegate().isGreedyToLeft();
-    }
-
-    @Override
-    public void dispose() {
-      RangeMarker delegate = getOrCreateDelegate();
-      if (delegate != null) {
-        delegate.dispose();
-      }
-    }
-  }
-
-  private static class OffsetLazyMarker extends LazyMarker {
-    private OffsetLazyMarker(@NotNull VirtualFile file, int offset) {
-      super(file, offset);
-    }
-
-    @Override
-    @NotNull
-    public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
-      final int offset = Math.min(myInitialOffset, document.getTextLength());
-      return document.createRangeMarker(offset, offset);
-    }
-  }
-
-  private class LineColumnLazyMarker extends LazyMarker {
-    private final int myLine;
-    private final int myColumn;
-
-    private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) {
-      super(file, -1);
-      myLine = line;
-      myColumn = column;
-    }
-
-    @Override
-    @Nullable
-    public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
-      if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
-        return null;
-      }
-
-      int offset = calculateOffset(myProject, file, document, myLine, myColumn);
-      return document.createRangeMarker(offset, offset);
-    }
-
-    @Override
-    public int getStartOffset() {
-      getOrCreateDelegate();
-      return super.getStartOffset();
-    }
-
-    @Override
-    public int getEndOffset() {
-      getOrCreateDelegate();
-      return super.getEndOffset();
-    }
-  }
-
-  private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
-    int offset;
-    if (line < document.getLineCount()) {
-      final int lineStart = document.getLineStartOffset(line);
-      final int lineEnd = document.getLineEndOffset(line);
-      final CharSequence docText = document.getCharsSequence();
-      final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType());
-
-      offset = lineStart;
-      int col = 0;
-      while (offset < lineEnd && col < column) {
-        col += docText.charAt(offset) == '\t' ? tabSize : 1;
-        offset++;
-      }
-    }
-    else {
-      offset = document.getTextLength();
-    }
-    return offset;
-  }
-
+  public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent);
 }
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java
new file mode 100644
index 0000000..c496452
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor.actionSystem;
+
+import com.intellij.ide.DataManager;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.DataKey;
+import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.NonNls;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.intellij.openapi.actionSystem.CommonDataKeys.*;
+import static com.intellij.openapi.actionSystem.PlatformDataKeys.PROJECT_FILE_DIRECTORY;
+
+/**
+* @author Konstantin Bulenkov
+*/
+final class DialogAwareDataContext implements DataContext {
+  private static final DataKey[] keys = {PROJECT, PROJECT_FILE_DIRECTORY, EDITOR, VIRTUAL_FILE, PSI_FILE};
+  private final Map<String, Object> values = new HashMap<String, Object>();
+
+  DialogAwareDataContext(DataContext context) {
+    for (DataKey key : keys) {
+      values.put(key.getName(), key.getData(context));
+    }
+  }
+
+  @Override
+  public Object getData(@NonNls String dataId) {
+    if (values.keySet().contains(dataId)) {
+      return values.get(dataId);
+    }
+    final Editor editor = (Editor)values.get(EDITOR.getName());
+    if (editor != null) {
+      return DataManager.getInstance().getDataContext(editor.getContentComponent()).getData(dataId);
+    }
+    return null;
+  }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
index 217ff70..945c520 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
@@ -26,6 +26,8 @@
 
 import java.awt.event.KeyEvent;
 
+import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT;
+
 public abstract class EditorAction extends AnAction implements DumbAware {
   private EditorActionHandler myHandler;
   private boolean myHandlersLoaded;
@@ -126,14 +128,14 @@
   }
 
   private static DataContext getProjectAwareDataContext(final Editor editor, @NotNull final DataContext original) {
-    if (CommonDataKeys.PROJECT.getData(original) == editor.getProject()) {
-      return original;
+    if (PROJECT.getData(original) == editor.getProject()) {
+      return new DialogAwareDataContext(original);
     }
 
     return new DataContext() {
       @Override
       public Object getData(String dataId) {
-        if (CommonDataKeys.PROJECT.is(dataId)) {
+        if (PROJECT.is(dataId)) {
           return editor.getProject();
         }
         return original.getData(dataId);
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
index 9cd9ab2..db13823 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
@@ -71,31 +71,17 @@
       if (range.getEndOffset() >= iterator.getStart()) {
         int relativeStart = Math.max(iterator.getStart() - range.getStartOffset(), 0);
         int relativeEnd = Math.min(iterator.getEnd() - range.getStartOffset(), range.getLength() + 1);
-        boolean merged = false;
-        if (myMergeByTextAttributes && !myPieces.isEmpty()) {
-          Element element = myPieces.get(myPieces.size() - 1);
-          if (element.getEnd() >= offset + relativeStart &&
-              Comparing.equal(element.getAttributes(), iterator.getTextAttributes()) &&
-              Comparing.equal(element.getElementType(), iterator.getTokenType())) {
-            merged = true;
-            myPieces.add(new Element(element.getStart(),
-                                     offset + relativeEnd,
-                                     iterator.getTokenType(),
-                                     iterator.getTextAttributes()));
-          }
-        }
-        if (!merged) {
-          myPieces.add(new Element(offset + relativeStart,
-                                   offset + relativeEnd,
-                                   iterator.getTokenType(),
-                                   iterator.getTextAttributes()));
-        }
+
+        addElement(new Element(offset + relativeStart,
+                               offset + relativeEnd,
+                               iterator.getTokenType(),
+                               iterator.getTextAttributes()));
       }
 
       if (range.getEndOffset() < iterator.getEnd()) {
         offset += range.getLength() + 1 + myAdditionalOffset;  // myAdditionalOffset because of extra line - for shoene separators
         int lastEnd = myPieces.isEmpty() ? -1 : myPieces.get(myPieces.size() - 1).getEnd();
-        myPieces.add(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER));
+        addElement(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER));
         index++;
         continue;
       }
@@ -104,6 +90,26 @@
     }
   }
 
+  private void addElement(@NotNull Element element) {
+    boolean merged = false;
+    if (myMergeByTextAttributes && !myPieces.isEmpty()) {
+      Element oldElement = myPieces.get(myPieces.size() - 1);
+      if (oldElement.getEnd() >= element.getStart() &&
+          Comparing.equal(oldElement.getAttributes(), element.getAttributes()) &&
+          Comparing.equal(oldElement.getElementType(), element.getElementType())) {
+        merged = true;
+        myPieces.remove(myPieces.size() - 1);
+        myPieces.add(new Element(oldElement.getStart(),
+                                 element.getEnd(),
+                                 element.getElementType(),
+                                 element.getAttributes()));
+      }
+    }
+    if (!merged) {
+      myPieces.add(element);
+    }
+  }
+
   @NotNull
   @Override
   public HighlighterIterator createIterator(int startOffset) {
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
index 1e43287..c958dbc 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
@@ -19,9 +19,11 @@
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.UIBundle;
+import org.jetbrains.annotations.NotNull;
 
 public class FileChooserDescriptorFactory {
-  private FileChooserDescriptorFactory() { }
+  private FileChooserDescriptorFactory() {
+  }
 
   public static FileChooserDescriptor createAllButJarContentsDescriptor() {
     return new FileChooserDescriptor(true, true, true, true, false, true);
@@ -83,7 +85,18 @@
   }
 
   public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType) {
-    return new FileChooserDescriptor(true, false, false, false, false, false) {
+    return createSingleFileDescriptor(fileType, false);
+  }
+
+  /**
+   * Creates file descriptor with certain type and (possible) folders.
+   * @param fileType supported type
+   * @param supportDirectories support directories or not
+   * @return descriptor
+   */
+  @NotNull
+  public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType, final boolean supportDirectories) {
+    return new FileChooserDescriptor(true, supportDirectories, false, false, false, false) {
       @Override
       public boolean isFileVisible(final VirtualFile file, final boolean showHiddenFiles) {
         return file.isDirectory() || file.getFileType() == fileType;
@@ -91,18 +104,22 @@
 
       @Override
       public boolean isFileSelectable(final VirtualFile file) {
-        return super.isFileSelectable(file) && file.getFileType() == fileType;
+        return super.isFileSelectable(file) && (file.getFileType() == fileType || ((file.isDirectory() && supportDirectories)));
       }
     };
   }
 
-  /** @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) */
+  /**
+   * @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15)
+   */
   @SuppressWarnings({"UnusedDeclaration", "deprecation"})
   public static FileChooserDescriptorBuilder onlyFiles() {
     return FileChooserDescriptorBuilder.onlyFiles();
   }
 
-  /** @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) */
+  /**
+   * @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15)
+   */
   @SuppressWarnings({"UnusedDeclaration", "deprecation"})
   public static FileChooserDescriptorBuilder filesAndFolders() {
     return FileChooserDescriptorBuilder.filesAndFolders();
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
index 366f69d..b958957 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
@@ -30,7 +30,7 @@
 
   public static final Key<Boolean> USE_CURRENT_WINDOW = Key.create("OpenFile.searchForOpen");
 
-  public static FileEditorManager getInstance(Project project) {
+  public static FileEditorManager getInstance(@NotNull Project project) {
     return project.getComponent(FileEditorManager.class);
   }
 
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
index 9ec804d..fdf32b9 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
@@ -55,34 +55,31 @@
   private boolean myUseCurrentWindow = false;
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int offset) {
-    this(project, file, -1, -1, offset, null, false);
+    this(project, file, -1, -1, offset, false);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int logicalLine, int logicalColumn) {
-    this(project, file, logicalLine, logicalColumn, -1, null, false);
+    this(project, file, logicalLine, logicalColumn, -1, false);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
                             int logicalLine, int logicalColumn, boolean persistent) {
-    this(project, file, logicalLine, logicalColumn, -1, null, persistent);
+    this(project, file, logicalLine, logicalColumn, -1, persistent);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file) {
-    this(project, file, -1, -1, -1, null, false);
+    this(project, file, -1, -1, -1, false);
   }
 
   private OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
-                             int logicalLine, int logicalColumn, int offset, @Nullable RangeMarker rangeMarker, boolean persistent) {
+                             int logicalLine, int logicalColumn, int offset, boolean persistent) {
     myProject = project;
 
     myFile = file;
     myLogicalLine = logicalLine;
     myLogicalColumn = logicalColumn;
     myOffset = offset;
-    if (rangeMarker != null) {
-      myRangeMarker = rangeMarker;
-    }
-    else if (offset >= 0) {
+    if (offset >= 0) {
       myRangeMarker = LazyRangeMarkerFactory.getInstance(project).createRangeMarker(file, offset);
     }
     else if (logicalLine >= 0 ){
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
index 3f4a92a..8dbe022 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
@@ -16,6 +16,8 @@
 package com.intellij.openapi.ui;
 
 import com.intellij.icons.AllIcons;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.project.Project;
 import com.intellij.ui.components.labels.LinkLabel;
 import com.intellij.ui.components.labels.LinkListener;
 import com.intellij.ui.components.panels.NonOpaquePanel;
@@ -35,7 +37,7 @@
 class Banner extends NonOpaquePanel implements PropertyChangeListener{
   private int myBannerMinHeight;
   private final JComponent myText = new MyText();
-
+  private final JLabel myProjectIcon = new JLabel(AllIcons.General.ProjectConfigurableBanner, SwingConstants.LEFT);
   private final NonOpaquePanel myActionsPanel = new NonOpaquePanel(new FlowLayout(FlowLayout.RIGHT, 2, 2));
 
   private final Map<Action, LinkLabel> myActions = new HashMap<Action, LinkLabel>();
@@ -45,7 +47,10 @@
 
     setBorder(new EmptyBorder(2, 6, 2, 4));
 
-    add(myText, BorderLayout.CENTER);
+    myProjectIcon.setVisible(false);
+    myProjectIcon.setBorder(new EmptyBorder(0, 12, 0, 4));
+    add(myText, BorderLayout.WEST);
+    add(myProjectIcon, BorderLayout.CENTER);
     add(myActionsPanel, BorderLayout.EAST);
   }
 
@@ -112,6 +117,17 @@
     repaint();
   }
 
+  public void forProject(Project project) {
+    if (project != null) {
+      myProjectIcon.setVisible(true);
+      myProjectIcon.setText(OptionsBundle.message(project.isDefault()
+                                                  ? "configurable.default.project.tooltip"
+                                                  : "configurable.current.project.tooltip"));
+    } else {
+      myProjectIcon.setVisible(false);
+    }
+  }
+
   public void setText(@NotNull final String... text) {
     myText.removeAll();
     for (int i = 0; i < text.length; i++) {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
index 5d2ecaf..c02f27a 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
@@ -46,6 +46,7 @@
   private WeakReference<ListPopup> myPopupRef;
   private ChangeEvent myChangeEvent = null;
   private T myValue;
+  private boolean myPaintArrow = true;
 
   protected EventListenerList myListenerList = new EventListenerList();
 
@@ -80,6 +81,10 @@
     return null;
   }
 
+  public void setPaintArrow(final boolean paintArrow) {
+    myPaintArrow = paintArrow;
+  }
+
   protected Runnable onChosen(@NotNull final T value) {
     stopCellEditing(value);
 
@@ -94,7 +99,7 @@
   protected void paintComponent(Graphics g) {
     super.paintComponent(g);
 
-    if (!StringUtil.isEmpty(getText())) {
+    if (!StringUtil.isEmpty(getText()) && myPaintArrow) {
       final Rectangle r = getBounds();
       final Insets i = getInsets();
       final int x = r.width - i.right - AllIcons.General.ArrowDown.getIconWidth();
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
index 34aaa93..463d950 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
@@ -16,7 +16,7 @@
 
 package com.intellij.openapi.ui;
 
-import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.project.Project;
 import com.intellij.ui.components.panels.NonOpaquePanel;
 import com.intellij.ui.components.panels.Wrapper;
 import com.intellij.util.ArrayUtil;
@@ -45,15 +45,21 @@
   private final NonOpaquePanel myBanner;
 
   private String[] myBannerText;
-  private boolean myDetailsEnabled = !Registry.is("ide.new.project.settings");
+  private boolean myDetailsEnabled;
   private String[] myPrefix;
   private String[] myText;
 
   private final Wrapper myContentGutter = new Wrapper();
 
-  private boolean myPaintBorder = !Registry.is("ide.new.project.settings");
+  private boolean myPaintBorder;
 
   public DetailsComponent() {
+    this(true, true);
+  }
+
+  public DetailsComponent(boolean detailsEnabled, boolean paintBorder) {
+    myDetailsEnabled = detailsEnabled;
+    myPaintBorder = paintBorder;
     myComponent = new JPanel(new BorderLayout()) {
       @Override
       protected void paintComponent(final Graphics g) {
@@ -110,7 +116,7 @@
     myBanner = new NonOpaquePanel(new BorderLayout());
     myBannerLabel = new Banner();
 
-    if (!Registry.is("ide.new.project.settings")) {
+    if (myDetailsEnabled) {
       myBanner.add(myBannerLabel, BorderLayout.CENTER);
     }
 
@@ -174,6 +180,9 @@
     }
   }
 
+  public void forProject(Project project) {
+    myBannerLabel.forProject(project);
+  }
 
   public void setPrefix(@Nullable String... prefix) {
     myPrefix = prefix;
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
index 25c52c7..6ef25dd 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.ui.Gray;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.ui.MacUIUtil;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.Nullable;
@@ -34,7 +35,6 @@
 import java.awt.event.FocusListener;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
-import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 
 /**
@@ -118,17 +118,7 @@
     final ComboBoxUI ui = comboBox.getUI();
     ComboPopup popup = null;
     if (ui instanceof BasicComboBoxUI) {
-      try {
-        final Field popupField = BasicComboBoxUI.class.getDeclaredField("popup");
-        popupField.setAccessible(true);
-        popup = (ComboPopup)popupField.get(ui);
-      }
-      catch (NoSuchFieldException e1) {
-        popup = null;
-      }
-      catch (IllegalAccessException e1) {
-        popup = null;
-      }
+      popup = ReflectionUtil.getField(BasicComboBoxUI.class, ui, ComboPopup.class, "popup");
     }
 
     return popup;
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
index 816349e..6c13964 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
@@ -111,7 +111,7 @@
   protected MyNode myRoot = new MyRootNode();
   protected Tree myTree = new Tree();
 
-  private final DetailsComponent myDetails = new DetailsComponent();
+  private final DetailsComponent myDetails = new DetailsComponent(!Registry.is("ide.new.project.settings"), !Registry.is("ide.new.project.settings"));
   protected JPanel myWholePanel;
   public JPanel myNorthPanel = new JPanel(new BorderLayout());
 
@@ -131,12 +131,9 @@
   protected MasterDetailsComponent(MasterDetailsState state) {
     myState = state;
 
-    mySplitter = new JBSplitter(false, .2f);
+    mySplitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f);
     mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements");
     mySplitter.setHonorComponentsMinimumSize(true);
-    if (Registry.is("ide.new.project.settings")) {
-      mySplitter.setOnePixelMode();
-    }
 
     installAutoScroll();
     reInitWholePanelIfNeeded();
@@ -300,6 +297,7 @@
 
   @NotNull 
   public JComponent createComponent() {
+    myTree.updateUI();
     reInitWholePanelIfNeeded();
 
     updateSelectionFromTree();
@@ -962,7 +960,11 @@
                                                                 myPreselection != null ? myPreselection.getDefaultIndex() : 0, true);
       final ListPopup listPopup = popupFactory.createListPopup(step);
       listPopup.setHandleAutoSelectionBeforeShow(true);
-      listPopup.showUnderneathOf(myNorthPanel);
+      if (e instanceof AnActionButton.AnActionEventWrapper) {
+        ((AnActionButton.AnActionEventWrapper)e).showPopup(listPopup);
+      } else {
+        listPopup.showUnderneathOf(myNorthPanel);
+      }
     }
   }
 
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
index 12b84f8..e619473 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,10 +18,12 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.ui.DocumentAdapter;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.border.EmptyBorder;
 import javax.swing.event.DocumentEvent;
 import java.awt.*;
 
@@ -55,6 +57,11 @@
         }
       });
     }
+    if (Registry.is("ide.new.project.settings")) {
+      myNamePanel.setBorder(new EmptyBorder(10, 10, 6, 10));
+    } else {
+      myNamePanel.setBorder(new EmptyBorder(0,0,0,0));
+    }
   }
 
   public boolean isNameEditable() {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java
new file mode 100644
index 0000000..2b00970
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.ui;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.Weighted;
+import com.intellij.openapi.wm.IdeGlassPane;
+import com.intellij.openapi.wm.IdeGlassPaneUtil;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class OnePixelDivider extends Divider {
+  private boolean myVertical;
+  private Splitter mySplitter;
+  private boolean myResizeEnabled;
+  private boolean mySwitchOrientationEnabled;
+  protected Point myPoint;
+  private IdeGlassPane myGlassPane;
+  private final MouseAdapter myListener = new MyMouseAdapter();
+  private Disposable myDisposable;
+
+  public OnePixelDivider(boolean vertical, Splitter splitter) {
+    super(new GridBagLayout());
+    mySplitter = splitter;
+    myResizeEnabled = true;
+    mySwitchOrientationEnabled = false;
+    setFocusable(false);
+    enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+    //setOpaque(false);
+    setOrientation(vertical);
+    setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)));
+  }
+
+  @Override
+  public void addNotify() {
+    super.addNotify();
+    init();
+  }
+
+  @Override
+  public void removeNotify() {
+    super.removeNotify();
+    if (myDisposable != null && !Disposer.isDisposed(myDisposable)) {
+      Disposer.dispose(myDisposable);
+    }
+  }
+
+  private boolean dragging = false;
+  private class MyMouseAdapter extends MouseAdapter implements Weighted {
+    @Override
+    public void mousePressed(MouseEvent e) {
+      dragging = isInDragZone(e);
+      _processMouseEvent(e);
+    }
+
+    boolean isInDragZone(MouseEvent e) {
+      final MouseEvent event = getTargetEvent(e);
+      final Point p = event.getPoint();
+      final int r = Math.abs(isVertical() ? p.y : p.x);
+      return r < 6;
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+      _processMouseEvent(e);
+      dragging = false;
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent e) {
+      final OnePixelDivider divider = OnePixelDivider.this;
+      if (isInDragZone(e)) {
+        myGlassPane.setCursor(divider.getCursor(), divider);
+      } else {
+        myGlassPane.setCursor(null, divider);
+      }
+      _processMouseMotionEvent(e);
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+      _processMouseMotionEvent(e);
+    }
+    @Override
+    public double getWeight() {
+      return 1;
+    }
+    private void _processMouseMotionEvent(MouseEvent e) {
+      MouseEvent event = getTargetEvent(e);
+      if (event == null) {
+        myGlassPane.setCursor(null, myListener);
+        return;
+      }
+
+      processMouseMotionEvent(event);
+      if (event.isConsumed()) {
+        e.consume();
+      }
+    }
+
+    private void _processMouseEvent(MouseEvent e) {
+      MouseEvent event = getTargetEvent(e);
+      if (event == null) {
+        myGlassPane.setCursor(null, myListener);
+        return;
+      }
+
+      processMouseEvent(event);
+      if (event.isConsumed()) {
+        e.consume();
+      }
+    }
+  }
+
+  private MouseEvent getTargetEvent(MouseEvent e) {
+    return SwingUtilities.convertMouseEvent(e.getComponent(), e, this);
+  }
+
+  private void init() {
+    myGlassPane = IdeGlassPaneUtil.find(this);
+    myDisposable = Disposer.newDisposable();
+    myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable);
+    myGlassPane.addMousePreprocessor(myListener, myDisposable);
+  }
+
+  public void setOrientation(boolean vertical) {
+    removeAll();
+    myVertical = vertical;
+    final int cursorType = isVertical() ? Cursor.N_RESIZE_CURSOR : Cursor.W_RESIZE_CURSOR;
+    setCursor(Cursor.getPredefinedCursor(cursorType));
+  }
+
+  @Override
+  protected void processMouseMotionEvent(MouseEvent e) {
+    super.processMouseMotionEvent(e);
+    if (!myResizeEnabled) return;
+    if (MouseEvent.MOUSE_DRAGGED == e.getID() && dragging) {
+      myPoint = SwingUtilities.convertPoint(this, e.getPoint(), mySplitter);
+      float proportion;
+      final float firstMinProportion = getMinProportion(mySplitter.getFirstComponent());
+      final float secondMinProportion = getMinProportion(mySplitter.getSecondComponent());
+      if (isVertical()) {
+        if (getHeight() > 0) {
+          proportion = Math.min(1.0f, Math
+            .max(.0f, Math.min(Math.max(firstMinProportion, (float)myPoint.y / (float)mySplitter.getHeight()), 1 - secondMinProportion)));
+          mySplitter.setProportion(proportion);
+        }
+      }
+      else {
+        if (getWidth() > 0) {
+          proportion = Math.min(1.0f, Math.max(.0f, Math.min(
+            Math.max(firstMinProportion, (float)myPoint.x / (float)mySplitter.getWidth()), 1 - secondMinProportion)));
+          mySplitter.setProportion(proportion);
+        }
+      }
+    }
+  }
+
+  private float getMinProportion(JComponent component) {
+    if (component != null &&
+        mySplitter.getFirstComponent() != null &&
+        mySplitter.getFirstComponent().isVisible() &&
+        mySplitter.getSecondComponent() != null &&
+        mySplitter.getSecondComponent().isVisible()) {
+      if (isVertical()) {
+        return (float)component.getMinimumSize().height / (float)(mySplitter.getHeight() - 1);
+      } else {
+        return (float)component.getMinimumSize().width / (float)(mySplitter.getWidth() - 1);
+      }
+    }
+
+    return 0.0f;
+  }
+
+  @Override
+  protected void processMouseEvent(MouseEvent e) {
+    super.processMouseEvent(e);
+    if (e.getID() == MouseEvent.MOUSE_CLICKED) {
+      if (mySwitchOrientationEnabled
+          && e.getClickCount() == 1
+          && SwingUtilities.isLeftMouseButton(e) && (SystemInfo.isMac ? e.isMetaDown() : e.isControlDown())) {
+        mySplitter.setOrientation(!mySplitter.getOrientation());
+      }
+      if (myResizeEnabled && e.getClickCount() == 2) {
+        mySplitter.setProportion(.5f);
+      }
+    }
+  }
+
+  public void setResizeEnabled(boolean resizeEnabled) {
+    myResizeEnabled = resizeEnabled;
+    if (!myResizeEnabled) {
+      setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+    }
+    else {
+      setCursor(isVertical() ?
+                Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) :
+                Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
+    }
+  }
+
+  public void setSwitchOrientationEnabled(boolean switchOrientationEnabled) {
+    mySwitchOrientationEnabled = switchOrientationEnabled;
+  }
+
+
+  public boolean isVertical() {
+    return myVertical;
+  }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
index fc9eec2..6c40a04 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
@@ -43,7 +43,7 @@
   private boolean myInvalidatesPendingFurtherRequestors = true;
   private Expirable myExpirable;
 
-  public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand");
+  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand");
 
   public boolean isForced() {
     return myForced;
diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButton.java b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
index 7c539b1..d1c19df 100644
--- a/platform/platform-api/src/com/intellij/ui/AnActionButton.java
+++ b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
@@ -17,6 +17,7 @@
 
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.util.containers.SmartHashSet;
 import com.intellij.util.ui.UIUtil;
@@ -187,7 +188,7 @@
 
     @Override
     public void actionPerformed(AnActionEvent e) {
-      myAction.actionPerformed(e);
+      myAction.actionPerformed(new AnActionEventWrapper(e, this));
     }
 
     @Override
@@ -205,4 +206,20 @@
       return myAction.isDumbAware();
     }
   }
+
+  public static class AnActionEventWrapper extends AnActionEvent {
+    private final AnActionButton myPeer;
+
+    private AnActionEventWrapper(AnActionEvent e, AnActionButton peer) {
+      super(e.getInputEvent(), e.getDataContext(), e.getPlace(), e.getPresentation(), e.getActionManager(), e.getModifiers());
+      myPeer = peer;
+    }
+
+    public void showPopup(JBPopup popup) {
+      popup.show(myPeer.getPreferredPopupPoint());
+    }
+
+
+
+  }
 }
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java
new file mode 100644
index 0000000..186904a
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package com.intellij.ui;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public abstract class CheckboxTreeAdapter implements CheckboxTreeListener {
+  @Override
+  public void mouseDoubleClicked(@NotNull CheckedTreeNode node) {
+  }
+
+  @Override
+  public void nodeStateChanged(@NotNull CheckedTreeNode node) {
+  }
+
+  @Override
+  public void beforeNodeStateChanged(@NotNull CheckedTreeNode node) {
+  }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
index d9755f3..88f433f 100644
--- a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
@@ -16,67 +16,49 @@
 package com.intellij.ui;
 
 import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.EventDispatcher;
 import com.intellij.util.ui.UIUtil;
-import com.intellij.util.ui.tree.TreeUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.tree.*;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreeNode;
 import java.awt.*;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Enumeration;
 
 public class CheckboxTreeBase extends Tree {
-  private final CheckPolicy myCheckPolicy;
-  private static final CheckPolicy DEFAULT_POLICY = new CheckPolicy(true, true, false, true);
+  private final CheckboxTreeHelper myHelper;
+  private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
 
   public CheckboxTreeBase() {
     this(new CheckboxTreeCellRendererBase(), null);
   }
 
   public CheckboxTreeBase(final CheckboxTreeCellRendererBase cellRenderer, CheckedTreeNode root) {
-    this(cellRenderer, root, DEFAULT_POLICY);
+    this(cellRenderer, root, CheckboxTreeHelper.DEFAULT_POLICY);
   }
 
   public CheckboxTreeBase(CheckboxTreeCellRendererBase cellRenderer, @Nullable CheckedTreeNode root, CheckPolicy checkPolicy) {
-    myCheckPolicy = checkPolicy;
+    myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
+    myEventDispatcher.addListener(new CheckboxTreeListener() {
+      @Override
+      public void mouseDoubleClicked(@NotNull CheckedTreeNode node) {
+        onDoubleClick(node);
+      }
 
-    setRootVisible(false);
-    setShowsRootHandles(true);
-    setLineStyleAngled();
-    TreeUtil.installActions(this);
+      @Override
+      public void nodeStateChanged(@NotNull CheckedTreeNode node) {
+        CheckboxTreeBase.this.onNodeStateChanged(node);
+      }
 
-    installRenderer(cellRenderer);
-
-    addKeyListener(new KeyAdapter() {
-      public void keyPressed(KeyEvent e) {
-        if (isToggleEvent(e)) {
-          TreePath treePath = getLeadSelectionPath();
-          if (treePath == null) return;
-          final Object o = treePath.getLastPathComponent();
-          if (!(o instanceof CheckedTreeNode)) return;
-          CheckedTreeNode firstNode = (CheckedTreeNode)o;
-          boolean checked = toggleNode(firstNode);
-
-          TreePath[] selectionPaths = getSelectionPaths();
-          for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
-            final TreePath selectionPath = selectionPaths[i];
-            final Object o1 = selectionPath.getLastPathComponent();
-            if (!(o1 instanceof CheckedTreeNode)) continue;
-            CheckedTreeNode node = (CheckedTreeNode)o1;
-            checkNode(node, checked);
-            ((DefaultTreeModel)getModel()).nodeChanged(node);
-          }
-
-          e.consume();
-        }
+      @Override
+      public void beforeNodeStateChanged(@NotNull CheckedTreeNode node) {
+        CheckboxTreeBase.this.nodeStateWillChange(node);
       }
     });
+    myHelper = new CheckboxTreeHelper(checkPolicy, myEventDispatcher);
+    myHelper.initTree(this, this, cellRenderer);
 
     setSelectionRow(0);
     if (root != null) {
@@ -84,57 +66,39 @@
     }
   }
 
+  @Deprecated
   public void installRenderer(final CheckboxTreeCellRendererBase cellRenderer) {
     setCellRenderer(cellRenderer);
-    new ClickListener() {
-      @Override
-      public boolean onClick(@NotNull MouseEvent e, int clickCount) {
-        int row = getRowForLocation(e.getX(), e.getY());
-        if (row < 0) return false;
-        final Object o = getPathForRow(row).getLastPathComponent();
-        if (!(o instanceof CheckedTreeNode)) return false;
-        Rectangle rowBounds = getRowBounds(row);
-        cellRenderer.setBounds(rowBounds);
-        Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
-        checkBounds.setLocation(rowBounds.getLocation());
+  }
 
-        if (checkBounds.height == 0) checkBounds.height = checkBounds.width = rowBounds.height;
+  /**
+   * @deprecated use {@link #setNodeState} to change node state or subscribe to {@link #addCheckboxTreeListener} to get notifications about state changes
+   */
+  @Deprecated
+  protected boolean toggleNode(CheckedTreeNode node) {
+    setNodeState(node, !node.isChecked());
+    return node.isChecked();
+  }
 
-        final CheckedTreeNode node = (CheckedTreeNode)o;
-        if (checkBounds.contains(e.getPoint())) {
-          if (node.isEnabled()) {
-            toggleNode(node);
-            setSelectionRow(row);
-            return true;
-          }
-        }
-        else if (clickCount > 1) {
-          onDoubleClick(node);
-          return true;
-        }
-        return false;
-      }
-    }.installOn(this);
+  /**
+   * @deprecated use {@link #setNodeState} to change node state or subscribe to {@link #addCheckboxTreeListener} to get notifications about state changes
+   */
+  @Deprecated
+  protected void checkNode(CheckedTreeNode node, boolean checked) {
+    setNodeState(node, checked);
+  }
+
+  public void setNodeState(@NotNull CheckedTreeNode node, boolean checked) {
+    myHelper.setNodeState(this, node, checked);
+  }
+
+  public void addCheckboxTreeListener(@NotNull CheckboxTreeListener listener) {
+    myEventDispatcher.addListener(listener);
   }
 
   protected void onDoubleClick(final CheckedTreeNode node) {
   }
 
-  protected boolean isToggleEvent(KeyEvent e) {
-    return e.getKeyCode() == KeyEvent.VK_SPACE;
-  }
-
-  protected boolean toggleNode(CheckedTreeNode node) {
-    boolean checked = !node.isChecked();
-    checkNode(node, checked);
-
-    // notify model listeners about model change
-    final TreeModel model = getModel();
-    model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
-
-    return checked;
-  }
-
   /**
    * Collect checked leaf nodes of the type {@code nodeType} and that are accepted by
    * {@code filter}
@@ -144,38 +108,8 @@
    * @param <T>      the type of the node
    * @return an array of collected nodes
    */
-  @SuppressWarnings("unchecked")
   public <T> T[] getCheckedNodes(final Class<T> nodeType, @Nullable final NodeFilter<T> filter) {
-    final ArrayList<T> nodes = new ArrayList<T>();
-    final Object root = getModel().getRoot();
-    if (!(root instanceof CheckedTreeNode)) {
-      throw new IllegalStateException(
-        "The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
-    }
-    new Object() {
-      @SuppressWarnings("unchecked")
-      public void collect(CheckedTreeNode node) {
-        if (node.isLeaf()) {
-          Object userObject = node.getUserObject();
-          if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
-            final T value = (T)userObject;
-            if (filter != null && !filter.accept(value)) return;
-            nodes.add(value);
-          }
-        }
-        else {
-          for (int i = 0; i < node.getChildCount(); i++) {
-            final TreeNode child = node.getChildAt(i);
-            if (child instanceof CheckedTreeNode) {
-              collect((CheckedTreeNode)child);
-            }
-          }
-        }
-      }
-    }.collect((CheckedTreeNode)root);
-    T[] result = (T[])Array.newInstance(nodeType, nodes.size());
-    nodes.toArray(result);
-    return result;
+    return CheckboxTreeHelper.getCheckedNodes(nodeType, filter, getModel());
   }
 
 
@@ -184,118 +118,14 @@
     return -1;
   }
 
-  protected void checkNode(CheckedTreeNode node, boolean checked) {
-    adjustParentsAndChildren(node, checked);
-    repaint();
-  }
-
   protected void onNodeStateChanged(CheckedTreeNode node) {
-
   }
 
   protected void nodeStateWillChange(CheckedTreeNode node) {
-
   }
 
-  protected void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
-    changeNodeState(node, checked);
-    if (!checked) {
-      if (myCheckPolicy.uncheckParentWithUncheckedChild) {
-        TreeNode parent = node.getParent();
-        while (parent != null) {
-          if (parent instanceof CheckedTreeNode) {
-            changeNodeState((CheckedTreeNode)parent, false);
-          }
-          parent = parent.getParent();
-        }
-      }
-      if (myCheckPolicy.uncheckChildrenWithUncheckedParent) {
-        uncheckChildren(node);
-      }
-
-    }
-    else {
-      if (myCheckPolicy.checkChildrenWithCheckedParent) {
-        checkChildren(node);
-      }
-
-      if (myCheckPolicy.checkParentWithCheckedChild) {
-        TreeNode parent = node.getParent();
-        while (parent != null) {
-          if (parent instanceof CheckedTreeNode) {
-            changeNodeState((CheckedTreeNode)parent, true);
-          }
-          parent = parent.getParent();
-        }
-      }
-
-    }
-    repaint();
-  }
-
-  private void changeNodeState(final CheckedTreeNode node, final boolean checked) {
-    if (node.isChecked() != checked) {
-      nodeStateWillChange(node);
-      node.setChecked(checked);
-      onNodeStateChanged(node);
-    }
-  }
-
-  private void uncheckChildren(final CheckedTreeNode node) {
-    final Enumeration children = node.children();
-    while (children.hasMoreElements()) {
-      final Object o = children.nextElement();
-      if (!(o instanceof CheckedTreeNode)) continue;
-      CheckedTreeNode child = (CheckedTreeNode)o;
-      changeNodeState(child, false);
-      uncheckChildren(child);
-    }
-  }
-
-  private void checkChildren(final CheckedTreeNode node) {
-    final Enumeration children = node.children();
-    while (children.hasMoreElements()) {
-      final Object o = children.nextElement();
-      if (!(o instanceof CheckedTreeNode)) continue;
-      CheckedTreeNode child = (CheckedTreeNode)o;
-      changeNodeState(child, true);
-      checkChildren(child);
-    }
-  }
-
+  @Deprecated
   protected void adjustParents(final CheckedTreeNode node, final boolean checked) {
-    TreeNode parentNode = node.getParent();
-    if (!(parentNode instanceof CheckedTreeNode)) return;
-    CheckedTreeNode parent = (CheckedTreeNode)parentNode;
-
-    if (!checked && isAllChildrenUnchecked(parent)) {
-      changeNodeState(parent, false);
-      adjustParents(parent, false);
-    }
-    else if (checked && isAllChildrenChecked(parent)) {
-      changeNodeState(parent, true);
-      adjustParents(parent, true);
-    }
-  }
-
-  private static boolean isAllChildrenUnchecked(final CheckedTreeNode node) {
-    for (int i = 0; i < node.getChildCount(); i++) {
-      final TreeNode o = node.getChildAt(i);
-      if ((o instanceof CheckedTreeNode) && ((CheckedTreeNode)o).isChecked()) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private static boolean isAllChildrenChecked(final CheckedTreeNode node) {
-    for (int i = 0; i < node.getChildCount(); i++) {
-      final TreeNode o = node.getChildAt(i);
-      if ((o instanceof CheckedTreeNode) && !((CheckedTreeNode)o).isChecked()) {
-        return false;
-      }
-    }
-    return true;
   }
 
   public static class CheckboxTreeCellRendererBase extends JPanel implements TreeCellRenderer {
@@ -395,8 +225,8 @@
     }
 
     /**
-     * @deprecated
      * @see CheckboxTreeCellRendererBase#customizeRenderer(javax.swing.JTree, Object, boolean, boolean, boolean, int, boolean)
+     * @deprecated
      */
     @Deprecated
     public void customizeCellRenderer(JTree tree,
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java
new file mode 100644
index 0000000..3048d13
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+package com.intellij.ui;
+
+import com.intellij.ui.speedSearch.SpeedSearchSupply;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.EventDispatcher;
+import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * @author nik
+ */
+class CheckboxTreeHelper {
+  static final CheckboxTreeBase.CheckPolicy DEFAULT_POLICY = new CheckboxTreeBase.CheckPolicy(true, true, false, true);
+  private final CheckboxTreeBase.CheckPolicy myCheckPolicy;
+  private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
+
+  CheckboxTreeHelper(CheckboxTreeBase.CheckPolicy checkPolicy, EventDispatcher<CheckboxTreeListener> dispatcher) {
+    myCheckPolicy = checkPolicy;
+    myEventDispatcher = dispatcher;
+  }
+
+  public void initTree(@NotNull final Tree tree, JComponent mainComponent, CheckboxTreeBase.CheckboxTreeCellRendererBase cellRenderer) {
+    tree.setCellRenderer(cellRenderer);
+    tree.setRootVisible(false);
+    tree.setShowsRootHandles(true);
+    tree.setLineStyleAngled();
+    TreeUtil.installActions(tree);
+
+    setupKeyListener(tree, mainComponent);
+    setupMouseListener(tree, mainComponent, cellRenderer);
+  }
+
+  public void setNodeState(Tree tree, CheckedTreeNode node, boolean checked) {
+    changeNodeState(node, checked);
+    adjustParentsAndChildren(node, checked);
+    tree.repaint();
+
+    // notify model listeners about model change
+    final TreeModel model = tree.getModel();
+    model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
+  }
+
+  private void toggleNode(Tree tree, CheckedTreeNode node) {
+    setNodeState(tree, node, !node.isChecked());
+  }
+
+  private void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
+    if (!checked) {
+      if (myCheckPolicy.uncheckParentWithUncheckedChild) {
+        TreeNode parent = node.getParent();
+        while (parent != null) {
+          if (parent instanceof CheckedTreeNode) {
+            changeNodeState((CheckedTreeNode)parent, false);
+          }
+          parent = parent.getParent();
+        }
+      }
+      if (myCheckPolicy.uncheckChildrenWithUncheckedParent) {
+        uncheckChildren(node);
+      }
+    }
+    else {
+      if (myCheckPolicy.checkChildrenWithCheckedParent) {
+        checkChildren(node);
+      }
+
+      if (myCheckPolicy.checkParentWithCheckedChild) {
+        TreeNode parent = node.getParent();
+        while (parent != null) {
+          if (parent instanceof CheckedTreeNode) {
+            changeNodeState((CheckedTreeNode)parent, true);
+          }
+          parent = parent.getParent();
+        }
+      }
+    }
+  }
+
+  private void changeNodeState(final CheckedTreeNode node, final boolean checked) {
+    if (node.isChecked() != checked) {
+      myEventDispatcher.getMulticaster().beforeNodeStateChanged(node);
+      node.setChecked(checked);
+      myEventDispatcher.getMulticaster().nodeStateChanged(node);
+    }
+  }
+
+  private void uncheckChildren(final CheckedTreeNode node) {
+    final Enumeration children = node.children();
+    while (children.hasMoreElements()) {
+      final Object o = children.nextElement();
+      if (!(o instanceof CheckedTreeNode)) continue;
+      CheckedTreeNode child = (CheckedTreeNode)o;
+      changeNodeState(child, false);
+      uncheckChildren(child);
+    }
+  }
+
+  private void checkChildren(final CheckedTreeNode node) {
+    final Enumeration children = node.children();
+    while (children.hasMoreElements()) {
+      final Object o = children.nextElement();
+      if (!(o instanceof CheckedTreeNode)) continue;
+      CheckedTreeNode child = (CheckedTreeNode)o;
+      changeNodeState(child, true);
+      checkChildren(child);
+    }
+  }
+
+  private void setupKeyListener(final Tree tree, final JComponent mainComponent) {
+    mainComponent.addKeyListener(new KeyAdapter() {
+      public void keyPressed(@NotNull KeyEvent e) {
+        if (isToggleEvent(e, mainComponent)) {
+          TreePath treePath = tree.getLeadSelectionPath();
+          if (treePath == null) return;
+          final Object o = treePath.getLastPathComponent();
+          if (!(o instanceof CheckedTreeNode)) return;
+          CheckedTreeNode firstNode = (CheckedTreeNode)o;
+          toggleNode(tree, firstNode);
+          boolean checked = firstNode.isChecked();
+
+          TreePath[] selectionPaths = tree.getSelectionPaths();
+          for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
+            final TreePath selectionPath = selectionPaths[i];
+            final Object o1 = selectionPath.getLastPathComponent();
+            if (!(o1 instanceof CheckedTreeNode)) continue;
+            CheckedTreeNode node = (CheckedTreeNode)o1;
+            setNodeState(tree, node, checked);
+          }
+
+          e.consume();
+        }
+      }
+    });
+  }
+
+  private static boolean isToggleEvent(KeyEvent e, JComponent mainComponent) {
+    return e.getKeyCode() == KeyEvent.VK_SPACE && SpeedSearchSupply.getSupply(mainComponent) == null;
+  }
+
+  private void setupMouseListener(final Tree tree, JComponent mainComponent, final CheckboxTreeBase.CheckboxTreeCellRendererBase cellRenderer) {
+    new ClickListener() {
+      @Override
+      public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+        int row = tree.getRowForLocation(e.getX(), e.getY());
+        if (row < 0) return false;
+        final Object o = tree.getPathForRow(row).getLastPathComponent();
+        if (!(o instanceof CheckedTreeNode)) return false;
+        Rectangle rowBounds = tree.getRowBounds(row);
+        cellRenderer.setBounds(rowBounds);
+        Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
+        checkBounds.setLocation(rowBounds.getLocation());
+
+        if (checkBounds.height == 0) checkBounds.height = checkBounds.width = rowBounds.height;
+
+        final CheckedTreeNode node = (CheckedTreeNode)o;
+        if (checkBounds.contains(e.getPoint())) {
+          if (node.isEnabled()) {
+            toggleNode(tree, node);
+            tree.setSelectionRow(row);
+            return true;
+          }
+        }
+        else if (clickCount > 1) {
+          myEventDispatcher.getMulticaster().mouseDoubleClicked(node);
+          return true;
+        }
+
+        return false;
+      }
+    }.installOn(mainComponent);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T[] getCheckedNodes(final Class<T> nodeType, @Nullable final Tree.NodeFilter<T> filter, final TreeModel model) {
+    final ArrayList<T> nodes = new ArrayList<T>();
+    final Object root = model.getRoot();
+    if (!(root instanceof CheckedTreeNode)) {
+      throw new IllegalStateException(
+        "The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
+    }
+    new Object() {
+      @SuppressWarnings("unchecked")
+      public void collect(CheckedTreeNode node) {
+        if (node.isLeaf()) {
+          Object userObject = node.getUserObject();
+          if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
+            final T value = (T)userObject;
+            if (filter != null && !filter.accept(value)) return;
+            nodes.add(value);
+          }
+        }
+        else {
+          for (int i = 0; i < node.getChildCount(); i++) {
+            final TreeNode child = node.getChildAt(i);
+            if (child instanceof CheckedTreeNode) {
+              collect((CheckedTreeNode)child);
+            }
+          }
+        }
+      }
+    }.collect((CheckedTreeNode)root);
+    T[] result = (T[])Array.newInstance(nodeType, nodes.size());
+    nodes.toArray(result);
+    return result;
+  }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java
new file mode 100644
index 0000000..792c458
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package com.intellij.ui;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface CheckboxTreeListener extends EventListener {
+  void mouseDoubleClicked(@NotNull CheckedTreeNode node);
+
+  void nodeStateChanged(@NotNull CheckedTreeNode node);
+
+  void beforeNodeStateChanged(@NotNull CheckedTreeNode node);
+}
diff --git a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
index 846378c..2d4213d 100644
--- a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -165,6 +165,9 @@
 
   @Override
   public void addNotify() {
+    if (getBackground() != null && !getBackground().equals(UIUtil.getPanelBackground())) {
+      SwingUtilities.updateComponentTreeUI(this.getParent());
+    }
     final JRootPane pane = getRootPane();
     for (AnActionButton button : myActions) {
       final ShortcutSet shortcut = button.getShortcut();
diff --git a/platform/platform-api/src/com/intellij/ui/JBSplitter.java b/platform/platform-api/src/com/intellij/ui/JBSplitter.java
index b4000db..5f01602 100644
--- a/platform/platform-api/src/com/intellij/ui/JBSplitter.java
+++ b/platform/platform-api/src/com/intellij/ui/JBSplitter.java
@@ -94,14 +94,6 @@
     saveProportion();
   }
 
-  public void setOnePixelMode() {
-    setDividerWidth(1);
-    setShowDividerIcon(false);
-    getDivider().setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)));
-    setShowDividerControls(false);
-    setOrientation(getOrientation());
-  }
-
   protected void loadProportion() {
     if (! StringUtil.isEmpty(mySplitterProportionKey)) {
       setProportion(PropertiesComponent.getInstance().getFloat(mySplitterProportionKey, myProportion));
diff --git a/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java b/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java
new file mode 100644
index 0000000..15dd5fd
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package com.intellij.ui;
+
+import com.intellij.openapi.ui.Divider;
+import com.intellij.openapi.ui.OnePixelDivider;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class OnePixelSplitter extends JBSplitter {
+
+  public OnePixelSplitter() {
+    super();
+    init();
+  }
+
+  public OnePixelSplitter(boolean vertical) {
+    super(vertical);
+    init();
+  }
+
+  public OnePixelSplitter(boolean vertical, float proportion) {
+    super(vertical, proportion);
+    init();
+  }
+
+  public OnePixelSplitter(float proportion) {
+    super(proportion);
+    init();
+  }
+
+  public OnePixelSplitter(boolean vertical, float proportion, float minProp, float maxProp) {
+    super(vertical, proportion, minProp, maxProp);
+    init();
+  }
+
+  protected void init() {
+    setDividerWidth(1);
+  }
+
+  @Override
+  protected Divider createDivider() {
+    return new OnePixelDivider(isVertical(), this);
+  }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java b/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
index ee68a3f..2f5bf03 100644
--- a/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
+++ b/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
 
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.border.Border;
 import java.awt.*;
@@ -28,17 +29,17 @@
   private final Color myColor;
   private final Insets myInsets;
 
-  public CustomLineBorder(@NotNull Color color, @NotNull Insets insets) {
+  public CustomLineBorder(@Nullable Color color, @NotNull Insets insets) {
     myColor = color;
     myInsets = insets;
   }
 
-  public CustomLineBorder(@NotNull Color color, int top, int left, int bottom, int right) {
+  public CustomLineBorder(@Nullable Color color, int top, int left, int bottom, int right) {
     this(color, new Insets(top, left, bottom, right));
   }
 
   public CustomLineBorder(@NotNull Insets insets) {
-    this(UIUtil.getBorderColor(), insets);
+    this(null, insets);
   }
 
   public CustomLineBorder(int top, int left, int bottom, int right) {
@@ -59,7 +60,7 @@
   }
 
   protected Color getColor() {
-    return myColor;
+    return myColor == null ? UIUtil.getBorderColor() : myColor;
   }
 
   @Override
diff --git a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
index a79349b..46bce6b 100644
--- a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
+++ b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
@@ -17,12 +17,12 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.util.config.Storage;
-import com.intellij.util.ui.ListTableModel;
 import org.jetbrains.annotations.NonNls;
 
 import javax.swing.*;
 import javax.swing.table.TableColumn;
 import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -33,10 +33,14 @@
 public class BaseTableView extends JBTable {
   private static final Logger LOG = Logger.getInstance("#com.intellij.ui.table.BaseTableView");
 
-  public BaseTableView(final ListTableModel model) {
+  public BaseTableView(final TableModel model) {
     super(model);
   }
 
+  public BaseTableView(TableModel model, TableColumnModel columnModel) {
+    super(model, columnModel);
+  }
+
   @NonNls
   private static String orderPropertyName(final int index) {
     return "Order"+index;
diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
index e7ff935..435c435 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -62,8 +62,12 @@
     this(new DefaultTableModel());
   }
 
-  public JBTable(final TableModel model) {
-    super(model);
+  public JBTable(TableModel model) {
+    this(model, null);
+  }
+
+  public JBTable(final TableModel model, final TableColumnModel columnModel) {
+    super(model, columnModel);
 
     myEmptyText = new StatusText(this) {
       @Override
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
index d1dfa97..c8c944c 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
@@ -92,6 +92,7 @@
    * out of its container. (IDEA-61536)
    */
   private WeakReference<TabInfo> myPreviousSelection = new WeakReference<TabInfo>(null);
+  private boolean myTitleShortened;
 
   public TabInfo(final JComponent component) {
     myComponent = component;
@@ -392,6 +393,14 @@
     return myPreviousSelection.get();
   }
 
+  public boolean isTitleShortened() {
+    return myTitleShortened;
+  }
+
+  public void setTitleIsShortened(boolean titleIsShortened) {
+    myTitleShortened = titleIsShortened;
+  }
+
   public interface DragOutDelegate {
 
     void dragOutStarted(MouseEvent mouseEvent, TabInfo info);
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
index 655854a..b0df091 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
@@ -240,7 +240,7 @@
 
     final JBTabsPosition position = myTabs.getTabsPosition();
 
-    if (!willDragOutStart && JBEditorTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) {
+    if (!willDragOutStart && myTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) {
       Point p = new Point(event.getPoint());
       p = SwingUtilities.convertPoint(event.getComponent(), p, myTabs);
       if (myTabs.getVisibleRect().contains(p) && myPressedOnScreenPoint.distance(new RelativePoint(event).getScreenPoint()) > 15) {
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
index 761d3ea..a842f62 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
@@ -43,7 +43,8 @@
  * @author pegov
  */
 public class JBEditorTabs extends JBTabsImpl {
-  private static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical";
+  public static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical";
+  static final String TABS_SHORTEN_TITLE_IF_NEED = "tabs.shorten.title.if.need";
   private JBEditorTabsPainter myDarkPainter = new DarculaEditorTabsPainter();
   private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter();
 
@@ -61,6 +62,13 @@
   }
 
   @Override
+  protected TabLabel createTabLabel(TabInfo info) {
+    TabLabel label = super.createTabLabel(info);
+    label.putClientProperty(TABS_SHORTEN_TITLE_IF_NEED, Boolean.TRUE);
+    return label;
+  }
+
+  @Override
   public boolean isEditorTabs() {
     return true;
   }
@@ -130,7 +138,7 @@
     return UIUtil.isUnderDarcula() ? myDarkPainter : myDefaultPainter;
   }
 
-  public static boolean isAlphabeticalMode() {
+  public boolean isAlphabeticalMode() {
     return Registry.is(TABS_ALPHABETICAL_KEY);
   }
 
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
index a058bad..60898a6 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
@@ -1262,6 +1262,10 @@
     return null;
   }
 
+  public boolean isAlphabeticalMode() {
+    return false;
+  }
+
   @Nullable
   private TabInfo findEnabledBackward(int from, boolean cycle) {
     if (from < 0) return null;
@@ -1653,19 +1657,13 @@
 
     config.setAntialiasing(false);
 
-    if (isSideComponentVertical()) {
-      Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
-      if (toolbarComp != null && !toolbarComp.isEmpty()) {
-        Rectangle toolBounds = toolbarComp.getBounds();
-        g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+    Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
+    if (toolbarComp != null && !toolbarComp.isEmpty()) {
+      Rectangle toolBounds = toolbarComp.getBounds();
+      g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+      if (isSideComponentVertical()) {
         g2d.drawLine((int)toolBounds.getMaxX(), toolBounds.y, (int)toolBounds.getMaxX(), (int)toolBounds.getMaxY() - 1);
-      }
-    }
-    else if (!isSideComponentOnTabs()) {
-      Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
-      if (toolbarComp != null && !toolbarComp.isEmpty()) {
-        Rectangle toolBounds = toolbarComp.getBounds();
-        g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+      } else if (!isSideComponentOnTabs()) {
         g2d.drawLine(toolBounds.x, (int)toolBounds.getMaxY(), (int)toolBounds.getMaxX() - 1, (int)toolBounds.getMaxY());
       }
     }
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
index 21c36d5..a360c4e 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.util.Pass;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.*;
 import com.intellij.ui.components.panels.Wrapper;
 import com.intellij.ui.tabs.JBTabsPosition;
@@ -317,6 +318,16 @@
 
 
   public void setText(final SimpleColoredText text) {
+    myInfo.setTitleIsShortened(false);
+    if (text != null && text.getTexts().size() == 1 && Boolean.TRUE == getClientProperty(JBEditorTabs.TABS_SHORTEN_TITLE_IF_NEED)) {
+      String title = text.getTexts().get(0);
+      if (title.length() > UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT) {
+        SimpleTextAttributes attributes = text.getAttributes().get(0);
+        text.clear();
+        text.append(StringUtil.getShortened(title, UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT), attributes);
+        myInfo.setTitleIsShortened(true);
+      }
+    }
     myLabel.change(new Runnable() {
       public void run() {
         myLabel.clear();
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
index 653420a..4e5925d 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -147,7 +147,7 @@
   }
 
   public LayoutPassInfo layoutSingleRow(List<TabInfo> visibleInfos)  {
-    if (JBEditorTabs.isAlphabeticalMode()) {
+    if (myTabs.isAlphabeticalMode()) {
       Collections.sort(visibleInfos, new Comparator<TabInfo>() {
         @Override
         public int compare(TabInfo o1, TabInfo o2) {
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
index 169b5d5..0975876 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -828,4 +828,35 @@
   public void setHorizontalAutoScrollingEnabled(boolean enabled) {
     myHorizontalAutoScrolling = enabled;
   }
+
+  /**
+   * Returns the deepest visible component
+   * that will be rendered at the specified location.
+   *
+   * @param x horizontal location in the tree
+   * @param y vertical location in the tree
+   * @return the deepest visible component of the renderer
+   */
+  @Nullable
+  protected Component getDeepestRendererComponentAt(int x, int y) {
+    int row = getRowForLocation(x, y);
+    if (row >= 0) {
+      TreeCellRenderer renderer = getCellRenderer();
+      if (renderer != null) {
+        TreePath path = getPathForRow(row);
+        Object node = path.getLastPathComponent();
+        Component component = renderer.getTreeCellRendererComponent(this, node,
+                                                                    isRowSelected(row),
+                                                                    isExpanded(row),
+                                                                    getModel().isLeaf(node),
+                                                                    row, true);
+        Rectangle bounds = getPathBounds(path);
+        if (bounds != null) {
+          component.setBounds(bounds); // initialize size to layout complex renderer
+          return SwingUtilities.getDeepestComponentAt(component, x - bounds.x, y - bounds.y);
+        }
+      }
+    }
+    return null;
+  }
 }
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
index dac3354..b574926 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
@@ -98,7 +98,9 @@
 
   public void setVisibleRow(int row) {
     myVisibleRow  = row;
-    setPreferredSize(new Dimension(getRowBounds(myVisibleRow).width, getPreferredSize().height));
+    final Rectangle rowBounds = getRowBounds(myVisibleRow);
+    final int indent = rowBounds.x - getVisibleRect().x;
+    setPreferredSize(new Dimension(getRowBounds(myVisibleRow).width + indent, getPreferredSize().height));
   }
 
   public void _processKeyEvent(KeyEvent e){
diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
index 94eaa4d..0bcb416 100644
--- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
+++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
@@ -29,6 +29,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.openapi.wm.IdeFrame;
+import com.intellij.util.SystemProperties;
 import com.intellij.util.WaitForProgressToShow;
 import com.intellij.util.proxy.CommonProxy;
 import com.intellij.util.proxy.JavaProxyProperty;
@@ -64,6 +65,7 @@
 )
 public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent,
                                          ExportableApplicationComponent {
+  public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("connection.timeout", 10000);
   private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable");
   public boolean PROXY_TYPE_IS_SOCKS = false;
   public boolean USE_HTTP_PROXY = false;
@@ -348,8 +350,8 @@
 
     final URLConnection connection = openConnection(url);
     try {
-      connection.setConnectTimeout(3 * 1000);
-      connection.setReadTimeout(3 * 1000);
+      connection.setConnectTimeout(CONNECTION_TIMEOUT);
+      connection.setReadTimeout(CONNECTION_TIMEOUT);
       connection.connect();
       connection.getInputStream();
     }
diff --git a/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java b/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
index c2d3d82..89d5a23 100644
--- a/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
+++ b/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
@@ -108,6 +108,11 @@
   }
 
   public FormBuilder addVerticalGap(final int height) {
+    if (height == -1) {
+      myPanel.add(new JLabel(), new GridBagConstraints(0, myLineCount++, 2, 1, 0, 1, CENTER, NONE, new Insets(0, 0, 0, 0), 0, 0));
+      return this;
+    }
+
     return addLabeledComponent((JLabel)null,
                                new Box.Filler(new Dimension(0, height), new Dimension(0, height), new Dimension(Short.MAX_VALUE, height)));
   }
diff --git a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
index 669766e..3000b49 100644
--- a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
+++ b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
@@ -29,7 +29,7 @@
   public static final ExtensionPointName<HttpRequestHandler> EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler");
 
   public boolean isSupported(@NotNull FullHttpRequest request) {
-    return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD;
+    return request.method() == HttpMethod.GET || request.method() == HttpMethod.HEAD;
   }
 
   public abstract boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context)
diff --git a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
similarity index 100%
rename from platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
rename to platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
diff --git a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
similarity index 100%
rename from platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
rename to platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
diff --git a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
index 64aefa4..b8e17ea 100644
--- a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
+++ b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -115,7 +115,7 @@
     public void documentChanged(DocumentEvent event) {
       if (myDocumentSavingInProgress) {
         /** When {@link FileDocumentManager#saveAllDocuments} is called,
-         *  {@link com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper} can change a document.
+         *  {@link com.intellij.openapi.editor.impl.TrailingSpacesStripper} can change a document.
          *  These needless 'documentChanged' events should be filtered out.
          */
         return;
diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
index 90d633f..a73295c 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
@@ -41,7 +41,7 @@
   }
 
   static boolean isApplicable() {
-    return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils
+    return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils
       .isIdeaCommunity();
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
index 1bbd749..c8699c0 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -952,25 +952,18 @@
   }
 
   private static class WindowsAltSupressor implements EventDispatcher {
-
-    private boolean myPureAltWasPressed;
     private boolean myWaitingForAltRelease;
-    private boolean myWaiterScheduled;
-
     private Robot myRobot;
 
     @Override
     public boolean dispatch(AWTEvent e) {
       boolean dispatch = true;
-      if (!Registry.is("actionSystem.win.suppressAlt.new") && e instanceof KeyEvent) {
+      if (e instanceof KeyEvent) {
         KeyEvent ke = (KeyEvent)e;
         final Component component = ke.getComponent();
-        final Window window = component == null ? null : SwingUtilities.windowForComponent(component);
         boolean pureAlt = ke.getKeyCode() == KeyEvent.VK_ALT && (ke.getModifiers() | InputEvent.ALT_MASK) == InputEvent.ALT_MASK;
         if (!pureAlt) {
-          myPureAltWasPressed = false;
           myWaitingForAltRelease = false;
-          myWaiterScheduled = false;
         }
         else {
           if (ApplicationManager.getApplication() == null ||
@@ -978,28 +971,25 @@
               !SystemInfo.isWindows ||
               !Registry.is("actionSystem.win.suppressAlt") ||
               !(UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE)) {
-            return !dispatch;
+            return true;
           }
 
           if (ke.getID() == KeyEvent.KEY_PRESSED) {
-            myPureAltWasPressed = true;
             dispatch = !myWaitingForAltRelease;
           }
           else if (ke.getID() == KeyEvent.KEY_RELEASED) {
             if (myWaitingForAltRelease) {
-              myPureAltWasPressed = false;
               myWaitingForAltRelease = false;
-              myWaiterScheduled = false;
               dispatch = false;
             }
-            else {
-              myWaiterScheduled = true;
+            else if (component != null) {
               //noinspection SSBasedInspection
               SwingUtilities.invokeLater(new Runnable() {
                 @Override
                 public void run() {
                   try {
-                    if (SystemInfo.isWindows || window == null || !window.isActive()) {
+                    final Window window = component instanceof Window ? (Window)component : SwingUtilities.windowForComponent(component);
+                    if (window == null || !window.isActive()) {
                       return;
                     }
                     myWaitingForAltRelease = true;
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
index 8aa0e38..d711894 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -24,13 +24,12 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.reference.SoftReference;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.image.VolatileImage;
 import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
 import java.util.Map;
 
 /**
@@ -40,7 +39,6 @@
   private static final Logger LOG = Logger.getInstance("#com.intellij.ide.HackyRepaintManager");
 
   private Map<GraphicsConfiguration, VolatileImage> myImagesMap;
-  @NonNls private static final String FAULTY_FIELD_NAME = "volatileMap";
 
   WeakReference<JComponent> myLastComponent;
 
@@ -53,14 +51,7 @@
   // sync here is to avoid data race when two(!) AWT threads on startup try to compete for the single myImagesMap
   private synchronized void clearLeakyImages(boolean force) {
     if (myImagesMap == null) {
-      try {
-        Field volMapField = RepaintManager.class.getDeclaredField(FAULTY_FIELD_NAME);
-        volMapField.setAccessible(true);
-        myImagesMap = (Map<GraphicsConfiguration, VolatileImage>)volMapField.get(this);
-      }
-      catch (Exception e) {
-        LOG.error(e);
-      }
+      myImagesMap = ReflectionUtil.getField(RepaintManager.class, this, Map.class, "volatileMap");
     }
 
     if (force ||
@@ -90,12 +81,12 @@
 
   // We must keep a strong reference to the DisplayChangedListener,
   //  since SunDisplayChanger keeps only a WeakReference to it.
-  private Object displayChangeHack;
+  private DisplayChangeHandler displayChangeHack;
   
   {
     try {
       GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
-      GraphicsDevice[] devices = env.getScreenDevices();    // init
+      env.getScreenDevices();    // init
       Class<?> aClass = Class.forName("sun.awt.DisplayChangedListener"); // might be absent
       displayChangeHack = new DisplayChangeHandler();
       
@@ -104,7 +95,8 @@
           .getMethod("addDisplayChangedListener", new Class[]{aClass})
           .invoke(env, displayChangeHack);
       }
-    } catch (Throwable t) {
+    }
+    catch (Throwable t) {
       if (!(t instanceof HeadlessException)) LOG.error("Cannot setup display change listener", t);
     }
   }
diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
index e3e1945..3b8bace 100644
--- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
@@ -59,7 +59,7 @@
   static final class XmlRpcRequestHandler extends HttpRequestHandler {
     @Override
     public boolean isSupported(@NotNull FullHttpRequest request) {
-      return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS;
+      return request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS;
     }
 
     @Override
@@ -89,7 +89,7 @@
       return false;
     }
 
-    if (request.getMethod() == HttpMethod.POST) {
+    if (request.method() == HttpMethod.POST) {
       ByteBuf result;
       ByteBufInputStream in = new ByteBufInputStream(request.content());
       try {
@@ -116,7 +116,7 @@
       return true;
     }
     else if (HttpMethod.POST.name().equals(request.headers().get("Access-Control-Request-Method"))) {
-      LOG.assertTrue(request.getMethod() == HttpMethod.OPTIONS);
+      LOG.assertTrue(request.method() == HttpMethod.OPTIONS);
       Responses.sendOptionsResponse("POST, OPTIONS", request, context);
       return true;
     }
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
index 7bbc3e0..0068304 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
@@ -33,6 +33,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.FieldPanel;
 import com.intellij.util.Consumer;
+import com.intellij.util.containers.MultiMap;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -55,15 +56,14 @@
   private final boolean myShowFilePath;
   private final String myDescription;
 
-  public ChooseComponentsToExportDialog(List<ExportableComponent> components,
-                                        Map<File, Set<ExportableComponent>> fileToComponents,
+  public ChooseComponentsToExportDialog(MultiMap<File, ExportableComponent> fileToComponents,
                                         boolean showFilePath, final String title, String description) {
     super(false);
     myDescription = description;
     myShowFilePath = showFilePath;
     Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement = new LinkedHashMap<ExportableComponent, ComponentElementProperties>();
 
-    for (ExportableComponent component : components) {
+    for (ExportableComponent component : fileToComponents.values()) {
       if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) {
         ComponentElementProperties componentElementProperties = new ComponentElementProperties();
         componentElementProperties.addComponent(component);
@@ -149,14 +149,14 @@
   }
 
   private static boolean addToExistingListElement(ExportableComponent component,
-                                           Map<ExportableComponent,ComponentElementProperties> componentToContainingListElement,
-                                           Map<File, Set<ExportableComponent>> fileToComponents) {
+                                                  Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement,
+                                                  MultiMap<File, ExportableComponent> fileToComponents) {
     final File[] exportFiles = component.getExportFiles();
     File file = null;
     for (File exportFile : exportFiles) {
-      final Set<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
+      Collection<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
 
-      for (final ExportableComponent tiedComponent : tiedComponents) {
+      for (ExportableComponent tiedComponent : tiedComponents) {
         if (tiedComponent == component) continue;
         final ComponentElementProperties elementProperties = componentToContainingListElement.get(tiedComponent);
         if (elementProperties != null && !FileUtil.filesEqual(exportFile, file)) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
index e82e22d..19a6502 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
@@ -35,7 +35,9 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
 import com.intellij.util.io.ZipUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.BufferedOutputStream;
 import java.io.File;
@@ -47,10 +49,18 @@
 public class ExportSettingsAction extends AnAction implements DumbAware {
   public void actionPerformed(AnActionEvent e) {
     Project project = getEventProject(e);
-    List<ExportableComponent> exportableComponents = new ArrayList<ExportableComponent>();
-    Map<File,Set<ExportableComponent>> fileToComponents = getRegisteredComponentsAndFiles(exportableComponents);
 
-    final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(exportableComponents, fileToComponents, true,
+    ApplicationManager.getApplication().saveSettings();
+
+    MultiMap<File, ExportableComponent> fileToComponents = getExportableComponentsMap();
+    for (Iterator<File> it = fileToComponents.keySet().iterator(); it.hasNext(); ) {
+      File file = it.next();
+      if (!file.exists()) {
+        it.remove();
+      }
+    }
+
+    final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(fileToComponents, true,
                                                                                      IdeBundle.message("title.select.components.to.export"),
                                                                                      IdeBundle.message(
                                                                                        "prompt.please.check.all.components.to.export"));
@@ -65,8 +75,6 @@
       ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
     }
 
-    ApplicationManager.getApplication().saveSettings();
-
     final File saveFile = dialog.getExportFile();
     try {
       if (saveFile.exists()) {
@@ -121,24 +129,18 @@
     }
   }
 
-  public static Map<File, Set<ExportableComponent>> getRegisteredComponentsAndFiles(List<ExportableComponent> exportableComponents) {
-    Map<File,Set<ExportableComponent>> fileToComponents = new HashMap<File, Set<ExportableComponent>>();
+  @NotNull
+  public static MultiMap<File, ExportableComponent> getExportableComponentsMap() {
+    MultiMap<File, ExportableComponent> result = MultiMap.createSet();
 
-    final List<ExportableComponent> components = new ArrayList<ExportableComponent>(Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
+    ExportableApplicationComponent[] components1 = ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class);
+    List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
 
-    components.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
-
-    for (ExportableComponent component : components) {
-      exportableComponents.add(component);
+    for (ExportableComponent component : ContainerUtil.concat(Arrays.asList(components1), components2)) {
       for (File exportFile : component.getExportFiles()) {
-        Set<ExportableComponent> componentsTied = fileToComponents.get(exportFile);
-        if (componentsTied == null) {
-          componentsTied = new HashSet<ExportableComponent>();
-          fileToComponents.put(exportFile, componentsTied);
-        }
-        componentsTied.add(component);
+        result.putValue(exportFile, component);
       }
     }
-    return fileToComponents;
+    return result;
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
index 1e98994..f06c45e 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
@@ -36,13 +36,17 @@
 import com.intellij.openapi.updateSettings.impl.UpdateSettings;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
 import com.intellij.util.io.ZipUtil;
 
 import java.awt.*;
 import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
@@ -77,10 +81,10 @@
         return;
       }
 
-      final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>();
-      final Map<File, Set<ExportableComponent>> filesToComponents = ExportSettingsAction.getRegisteredComponentsAndFiles(registeredComponents);
-      List<ExportableComponent> components = getComponentsStored(saveFile, registeredComponents);
-      final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(components, filesToComponents, false,
+      MultiMap<File, ExportableComponent> filesToComponents = ExportSettingsAction.getExportableComponentsMap();
+      List<ExportableComponent> components = getComponentsStored(saveFile, ContainerUtil.newArrayList(filesToComponents.values()));
+      filesToComponents.values().retainAll(components);
+      final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(filesToComponents, false,
                                                                                        IdeBundle.message("title.select.components.to.import"),
                                                                                        IdeBundle.message("prompt.check.components.to.import"));
       dialog.show();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index 7244977..fce491b 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -27,17 +27,20 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.application.ex.ApplicationInfoEx;
 import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
 import com.intellij.ui.LicensingFacade;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 
 public class SendFeedbackAction extends AnAction implements DumbAware {
+  @Override
   public void actionPerformed(AnActionEvent e) {
-    launchBrowser();
+    launchBrowser(e.getProject());
   }
 
-  public static void launchBrowser() {
+  public static void launchBrowser(@Nullable Project project) {
     final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
     boolean eap = appInfo.isEAP();
     String urlTemplate = eap ? appInfo.getEAPFeedbackUrl() : appInfo.getReleaseFeedbackUrl();
@@ -46,7 +49,7 @@
       .replace("$TIMEZONE", System.getProperty("user.timezone"))
       .replace("$EVAL", isEvaluationLicense() ? "true" : "false")
       .replace("$DESCR", getDescription());
-    BrowserUtil.browse(urlTemplate);
+    BrowserUtil.browse(urlTemplate, project);
   }
 
   private static String getDescription() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
index 851c909..dde5a5c 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -27,14 +27,9 @@
   public void update(final AnActionEvent event) {
     final Project project = CommonDataKeys.PROJECT.getData(event.getDataContext());
     final Presentation presentation = event.getPresentation();
-    boolean enabled;
-    if (project == null) {
-      enabled = false;
-    }
-    else {
-      enabled = isActionEnabled(project);
-    }
-    if (ActionPlaces.isPopupPlace(event.getPlace())) {
+    boolean inContextMenu = ActionPlaces.isPopupPlace(event.getPlace());
+    boolean enabled = project != null && isActionEnabled(project, inContextMenu);
+    if (inContextMenu) {
       presentation.setVisible(enabled);
     }
     else {
@@ -42,7 +37,17 @@
     }
   }
 
-  protected boolean isActionEnabled(Project project) {
+  /**
+   * This method determines whether the action is enabled for {@code project}
+   * if {@code inContextMenu} is set to {@code false}.  Otherwise,
+   * it determines whether the action is visible in the context menu.
+   *
+   * @param project       the specified project
+   * @param inContextMenu whether the action is used in context menu
+   * @return              {@code true} if the action is enabled,
+   *                      {@code false} otherwise
+   */
+  protected boolean isActionEnabled(Project project, boolean inContextMenu) {
     final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
     return fileEditorManager.isInSplitter();
   }
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 4541f46..cb35b5a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -1071,7 +1071,7 @@
       public void layoutContainer(Container target) {
         final JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, files);
         JComponent filesPane = scrollPane != null ? scrollPane : files;
-        if (sBounds == null) {
+        if (sBounds == null || !target.isShowing()) {
           super.layoutContainer(target);
           sBounds = separator.getBounds();
           tBounds = toolWindows.getBounds();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
index 8431364..7b000f5 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
 import com.intellij.ide.ui.UISettings;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.ui.tabs.impl.JBEditorTabs;
 
 import javax.swing.*;
@@ -28,7 +29,7 @@
 public class TabsAlphabeticalModeSwitcher extends ToggleAction {
   @Override
   public boolean isSelected(AnActionEvent e) {
-    return JBEditorTabs.isAlphabeticalMode();
+    return Registry.is(JBEditorTabs.TABS_ALPHABETICAL_KEY);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
index 12df75e..ec72488 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -32,8 +32,8 @@
   }
 
   @Override
-  protected boolean isActionEnabled(Project project) {
+  protected boolean isActionEnabled(Project project, boolean inContextMenu) {
     final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
-    return fileEditorManager.getWindowSplitCount() > 2;
+    return inContextMenu ? fileEditorManager.getWindowSplitCount() > 2 : fileEditorManager.isInSplitter();
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
index d450cf4..1af2fb8 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
@@ -25,7 +25,6 @@
 import com.intellij.openapi.util.IconLoader;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.util.IconUtil;
-import com.intellij.util.PlatformUtils;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.Nullable;
 
@@ -55,12 +54,12 @@
       myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/OSXDarcula.png"));
     }
     else if (SystemInfo.isWindows) {
-      if (PlatformUtils.isIdeaCommunity()) {
+      //if (PlatformUtils.isIdeaCommunity()) {
         myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/WindowsIntelliJ.png"));
-      }
-      else {
-        myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
-      }
+      //}
+      //else {
+      //  myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
+      //}
       myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/WindowsDarcula.png"));
     }
     else {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
index e5b9f15..b1ea133 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
@@ -25,21 +25,15 @@
  * The interface defines basic password management operations
  */
 public interface PasswordStorage {
-
   /**
-   * @deprecated To remove in IDEA 15. Use {@link #getPassword(Project, Class, String, ModalityState)}
-   */
-  @Deprecated
-  @Nullable
-  String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
-  /**
-   * Get password stored in a password safe.
-   * <p/>
-   * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
-   * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
-   * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
-   * windows.
+   * <p>Get password stored in a password safe.</p>
+   *
+   * <p><b>NB: </b>
+   *    This method may be called from the background,
+   *    and it may need to ask user to enter the master password to access the database by calling
+   *    {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()} to show a modal dialog.
+   *    So make sure not to call it from the read action.
+   *    Calling this method from the dispatch thread is allowed.</p>
    *
    * @param project   the project, that is used to ask for the master password if this is the first access to password safe
    * @param requestor the requestor class
@@ -49,45 +43,9 @@
    * @throws IllegalStateException if the method is called from the read action.
    */
   @Nullable
-  String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
-                     @Nullable ModalityState state) throws PasswordSafeException;
-
-  /**
-   * Store password in password safe
-   * <p/>
-   * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
-   * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
-   * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
-   * windows.
-   *
-   * @param project   the project, that is used to ask for the master password if this is the first access to password safe
-   * @param requestor the requestor class
-   * @param key       the key for the password
-   * @param value     the value to store
-   * @throws PasswordSafeException if password safe cannot be accessed
-   */
-  void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
-                     @Nullable ModalityState modalityState) throws PasswordSafeException;
-
-  /**
-   * @deprecated To remove in IDEA 15. Use {@link #storePassword(Project, Class, String, String, ModalityState)}
-   */
-  @Deprecated
-  void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
-
-  /**
-   * @deprecated To remove in IDEA 15. Use {@link #removePassword(Project, Class, String, ModalityState)}
-   */
-  @Deprecated
-  void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
+  String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
   /**
    * Remove password stored in a password safe
-   * <p/>
-   * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
-   * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
-   * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
-   * windows.
    *
    * @param project   the project, that is used to ask for the master password if this is the first access to password safe
    * @param requestor the requestor class
@@ -95,7 +53,15 @@
    * @return the plugin key
    * @throws PasswordSafeException if password safe cannot be accessed
    */
-  void removePassword(@Nullable Project project, @NotNull Class requestor, String key,
-                      @Nullable ModalityState modalityState) throws PasswordSafeException;
-
+  void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
+  /**
+   * Store password in password safe
+   *
+   * @param project   the project, that is used to ask for the master password if this is the first access to password safe
+   * @param requestor the requestor class
+   * @param key       the key for the password
+   * @param value     the value to store
+   * @throws PasswordSafeException if password safe cannot be accessed
+   */
+  void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
index 34aee7a..6d5127b 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
@@ -22,7 +22,6 @@
 import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase;
 import com.intellij.ide.passwordSafe.impl.providers.memory.MemoryPasswordSafe;
 import com.intellij.ide.passwordSafe.impl.providers.nil.NilProvider;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.NotNull;
@@ -71,19 +70,11 @@
   }
 
   @Nullable
-  @Override
   public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
-    return getPassword(project, requester, key, null);
-  }
-
-  @Nullable
-  @Override
-  public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
     if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
-      String password = getMemoryProvider().getPassword(project, requester, key, modalityState);
+      String password = getMemoryProvider().getPassword(project, requester, key);
       if (password == null) {
-        password = provider().getPassword(project, requester, key, modalityState);
+        password = provider().getPassword(project, requester, key);
         if (password != null) {
           // cache the password in memory as well for easier access during the session
           getMemoryProvider().storePassword(project, requester, key, password);
@@ -91,35 +82,21 @@
       }
       return password;
     }
-    return provider().getPassword(project, requester, key, modalityState);
+    return provider().getPassword(project, requester, key);
   }
 
-  @Override
-  public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
-    removePassword(project, requestor, key, null);
-  }
-
-  @Override
-  public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
-                             @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
     if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
       getMemoryProvider().removePassword(project, requester, key);
     }
-    provider().removePassword(project, requester, key, modalityState);
+    provider().removePassword(project, requester, key);
   }
 
-  @Override
-  public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
-    storePassword(project, requestor, key, value, null);
-  }
-
-  @Override
-  public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
     if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
       getMemoryProvider().storePassword(project, requester, key, value);
     }
-    provider().storePassword(project, requester, key, value, modalityState);
+    provider().storePassword(project, requester, key, value);
   }
 
   /**
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
index 3a40d61..18dee7c 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
@@ -15,11 +15,7 @@
  */
 package com.intellij.ide.passwordSafe.impl;
 
-import com.intellij.ide.passwordSafe.PasswordSafeException;
 import com.intellij.ide.passwordSafe.PasswordStorage;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * The provider for password safe component
@@ -38,21 +34,4 @@
    * @return the name of provider
    */
   public abstract String getName();
-
-  @Nullable
-  @Override
-  public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
-    return getPassword(project, requestor, key, null);
-  }
-
-  @Override
-  public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
-    storePassword(project, requestor, key, value, null);
-  }
-
-  @Override
-  public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
-    removePassword(project, requestor, key, null);
-  }
-
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
index 8c8f921..a0b0018 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
@@ -43,15 +43,13 @@
    * @throws PasswordSafeException in case of problems with access to the password database.
    * @throws IllegalStateException if the method is called from the read action.
    */
-  protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor,
-                                @Nullable ModalityState modalityState) throws PasswordSafeException;
+  protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException;
 
   @Nullable
-  public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
-    byte[] k = dbKey(project, requestor, key, modalityState);
+  public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
+    byte[] k = dbKey(project, requestor, key);
     byte[] ct = getEncryptedPassword(k);
-    return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor, modalityState), ct);
+    return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor), ct);
   }
 
   /**
@@ -68,17 +66,14 @@
    * @param project
    * @param requestor the requestor class
    * @param key       the key to use
-   * @param modalityState
    * @return the key to use for map
    */
-  private byte[] dbKey(@Nullable Project project, @NotNull Class requestor, String key,
-                       @Nullable ModalityState modalityState) throws PasswordSafeException {
-    return EncryptionUtil.dbKey(key(project, requestor, modalityState), requestor, key);
+  private byte[] dbKey(@Nullable Project project, Class requestor, String key) throws PasswordSafeException {
+    return EncryptionUtil.dbKey(key(project, requestor), requestor, key);
   }
 
-  public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
-                             @Nullable ModalityState modalityState) throws PasswordSafeException {
-    byte[] k = dbKey(project, requester, key, modalityState);
+  public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
+    byte[] k = dbKey(project, requester, key);
     removeEncryptedPassword(k);
   }
 
@@ -89,10 +84,9 @@
    */
   protected abstract void removeEncryptedPassword(byte[] key);
 
-  public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
-    byte[] k = dbKey(project, requestor, key, modalityState);
-    byte[] ct = EncryptionUtil.encryptText(key(project, requestor, modalityState), value);
+  public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
+    byte[] k = dbKey(project, requestor, key);
+    byte[] ct = EncryptionUtil.encryptText(key(project, requestor), value);
     storeEncryptedPassword(k, ct);
   }
 
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
index b74e513..8401592 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
@@ -154,8 +154,7 @@
   }
 
   @Override
-  protected byte[] key(@Nullable final Project project, @NotNull final Class requestor,
-                       @Nullable ModalityState modalityState) throws PasswordSafeException {
+  protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException {
     Application application = ApplicationManager.getApplication();
     if (!isTestMode() && application.isHeadlessEnvironment()) {
       throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
@@ -200,7 +199,7 @@
               }
             }
           }
-        }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+        }, ModalityState.any());
         //noinspection ThrowableResultOfMethodCallIgnored
         if (ex.get() != null) {
           throw ex.get();
@@ -211,12 +210,11 @@
   }
 
   @Override
-  public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
     if (database.isEmpty()) {
       return null;
     }
-    return super.getPassword(project, requestor, key, modalityState);
+    return super.getPassword(project, requestor, key);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
index da82bb9..4989789 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
@@ -19,12 +19,10 @@
 import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider;
 import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
 import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.security.SecureRandom;
 import java.util.Collections;
@@ -60,7 +58,7 @@
   }
 
   @Override
-  protected byte[] key(Project project, @NotNull Class requestor, @Nullable ModalityState modalityState) {
+  protected byte[] key(Project project, @NotNull Class requestor) {
     if (key.get() == null) {
       byte[] rnd = new byte[EncryptionUtil.SECRET_KEY_SIZE_BYTES * 16];
       new SecureRandom().nextBytes(rnd);
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
index e3a7732..4bf024d 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
@@ -17,7 +17,6 @@
 
 import com.intellij.ide.passwordSafe.PasswordSafeException;
 import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -42,22 +41,16 @@
     return "Do not Store";
   }
 
-  @Nullable
-  public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
     // nothing is stored
     return null;
   }
 
-  @Override
-  public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
-                             @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
     // do nothing
   }
 
-  @Override
-  public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
-                            @Nullable ModalityState modalityState) throws PasswordSafeException {
+  public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
     // just forget about password
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
index 353e836..8aa0099 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
@@ -73,10 +73,7 @@
   /**
    * Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
    * the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
-   *
    * @param project       the context project
-   * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
-   *                      If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
    * @param title         the dialog title
    * @param message       the message describing a resource for which password is asked
    * @param requestor     the password requestor
@@ -86,13 +83,12 @@
    */
   @Nullable
   public static String askPassword(final Project project,
-                                   @Nullable ModalityState modalityState,
                                    final String title,
                                    final String message,
                                    @NotNull final Class<?> requestor,
                                    final String key,
                                    boolean resetPassword, String error) {
-    return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error, null, null);
+    return askPassword(project, title, message, requestor, key, resetPassword, error, null, null);
   }
 
   /**
@@ -112,17 +108,14 @@
                                    @NotNull final Class<?> requestor,
                                    final String key,
                                    boolean resetPassword) {
-    return askPassword(null, null, title, message, requestor, key, resetPassword, null);
+    return askPassword(null, title, message, requestor, key, resetPassword, null);
   }
 
 
   /**
    * Ask passphrase possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
    * the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
-   *
    * @param project       the context project (might be null)
-   * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
-   *                      If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
    * @param title         the dialog title
    * @param message       the message describing a resource for which password is asked
    * @param requestor     the password requestor
@@ -132,13 +125,13 @@
    */
   @Nullable
   public static String askPassphrase(final Project project,
-                                     @Nullable ModalityState modalityState, final String title,
+                                     final String title,
                                      final String message,
                                      @NotNull final Class<?> requestor,
                                      final String key,
                                      boolean resetPassword,
                                      String error) {
-    return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error,
+    return askPassword(project, title, message, requestor, key, resetPassword, error,
                        "Passphrase:", "Remember the passphrase");
   }
 
@@ -146,10 +139,7 @@
   /**
    * Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
    * the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
-   *
    * @param project       the context project
-   * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
-   *                      If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
    * @param title         the dialog title
    * @param message       the message describing a resource for which password is asked
    * @param requestor     the password requestor
@@ -161,7 +151,6 @@
    */
   @Nullable
   private static String askPassword(final Project project,
-                                    @Nullable ModalityState modalityState,
                                     final String title,
                                     final String message,
                                     @NotNull final Class<?> requestor,
@@ -176,7 +165,7 @@
         ps.removePassword(project, requestor, key);
       }
       else {
-        String pw = ps.getPassword(project, requestor, key, modalityState);
+        String pw = ps.getPassword(project, requestor, key);
         if (pw != null) {
           return pw;
         }
@@ -214,7 +203,7 @@
           }
         }
       }
-    }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+    }, ModalityState.any());
     return ref.get();
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
index 20a41e3..931458f 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
@@ -161,7 +161,7 @@
         g.fillRect(0,0, getWidth(), getHeight());
       }
     };
-    header.setBorder(new CustomLineBorder(UIUtil.getBorderColor(), 1, 1, 0, 1));
+    header.setBorder(new CustomLineBorder(1, 1, 0, 1));
     final JLabel mySortLabel = new JLabel();
     mySortLabel.setForeground(UIUtil.getLabelDisabledForeground());
     mySortLabel.setBorder(new EmptyBorder(1, 1, 1, 5));
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
index be7aa3c..ec763a8 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
@@ -68,6 +68,8 @@
                                    HttpConfigurable.getInstance().openHttpConnection(url) :
                                    (HttpURLConnection)new URL(url).openConnection();
     connection.setRequestProperty("Accept-Encoding", "gzip");
+    connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+    connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
 
     if (indicator != null) {
       indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
index 19d924d..1036307 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
@@ -46,6 +46,7 @@
 import com.intellij.ui.ScreenUtil;
 import com.intellij.ui.content.Content;
 import com.intellij.ui.mac.MacPopupMenuUI;
+import com.intellij.ui.popup.OurHeavyWeightPopup;
 import com.intellij.util.IJSwingUtilities;
 import com.intellij.util.ObjectUtils;
 import com.intellij.util.PlatformUtils;
@@ -853,6 +854,9 @@
       final Point point = fixPopupLocation(contents, x, y);
 
       final int popupType = UIUtil.isUnderGTKLookAndFeel() ? WEIGHT_HEAVY : PopupUtil.getPopupType(this);
+      if (popupType == WEIGHT_HEAVY && OurHeavyWeightPopup.isEnabled()) {
+        return new OurHeavyWeightPopup(owner, contents, point.x, point.y);
+      }
       if (popupType >= 0) {
         PopupUtil.setPopupType(myDelegate, popupType);
       }
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
index a86a28a..b06cd21 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
@@ -79,7 +79,7 @@
   @SuppressWarnings("UnusedParameters")
   private static void log(Exception e) {
 //    everything is gonna be alright
-    e.printStackTrace();
+//    e.printStackTrace();
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index 255d356..5ddd245 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -48,6 +48,13 @@
 MenuBar.darcula.borderColor=555555
 MenuBar.darcula.borderShadowColor=282828
 
+CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI
+CheckBoxMenuItem.borderPainted=false
+
+RadioButtonMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonMenuItemUI
+RadioButtonMenuItem.borderPainted=false
+
+
 TabbedPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI
 TabbedPane.tabInsets=0,4,0,4
 TabbedPane.highlight=292b2d
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java
new file mode 100644
index 0000000..d9c4ac7
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.Gray;
+import com.intellij.util.ui.UIUtil;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaCheckBoxMenuItemUI extends DarculaMenuItemUIBase {
+
+  @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+  public static ComponentUI createUI(JComponent c) {
+    return new DarculaCheckBoxMenuItemUI();
+  }
+
+  protected String getPropertyPrefix() {
+      return "CheckBoxMenuItem";
+  }
+
+  @Override
+  public Dimension getPreferredSize(JComponent c) {
+    return super.getPreferredSize(c);
+  }
+
+  @Override
+  protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+    Graphics2D g = (Graphics2D) g2;
+    final GraphicsConfig config = new GraphicsConfig(g);
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+    g.translate(lr.getCheckRect().x-2, lr.getCheckRect().y);
+
+    final int sz = 13;
+    g.setPaint(new GradientPaint(sz / 2, 1, Gray._110, sz / 2, sz, Gray._95));
+    g.fillRoundRect(0, 0, sz, sz - 1 , 4, 4);
+
+    g.setPaint(new GradientPaint(sz / 2, 1, Gray._120.withAlpha(0x5a), sz / 2, sz, Gray._105.withAlpha(90)));
+    g.drawRoundRect(0, (UIUtil.isUnderDarcula() ? 1 : 0), sz, sz - 1, 4, 4);
+
+    g.setPaint(Gray._40.withAlpha(180));
+    g.drawRoundRect(0, 0, sz, sz - 1, 4, 4);
+
+
+    if (lh.getMenuItem().isSelected()) {
+      g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+      g.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+      g.setPaint(Gray._30);
+      g.drawLine(4, 7, 7, 10);
+      g.drawLine(7, 10, sz, 2);
+      g.setPaint(Gray._170);
+      g.drawLine(4, 5, 7, 8);
+      g.drawLine(7, 8, sz, 0);
+    }
+
+    g.translate(-lr.getCheckRect().x+2, -lr.getCheckRect().y);
+    config.restore();
+    g.setColor(foreground);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
new file mode 100644
index 0000000..cc69d24
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import sun.swing.MenuItemLayoutHelper;
+import sun.swing.SwingUtilities2;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicMenuItemUI;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaMenuItemUIBase extends BasicMenuItemUI {
+  @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+  public static ComponentUI createUI(JComponent c) {
+      return new DarculaMenuItemUIBase();
+  }
+
+  public void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement path[], MenuSelectionManager manager) {
+    Point p = e.getPoint();
+    if (p.x >= 0 && p.x < item.getWidth() &&
+        p.y >= 0 && p.y < item.getHeight()) {
+      if (e.getID() == MouseEvent.MOUSE_RELEASED) {
+        manager.clearSelectedPath();
+        item.doClick(0);
+        item.setArmed(false);
+      } else
+        manager.setSelectedPath(path);
+    } else if (item.getModel().isArmed()) {
+      MenuElement newPath[] = new MenuElement[path.length - 1];
+      int i, c;
+      for (i = 0, c = path.length - 1; i < c; i++)
+        newPath[i] = path[i];
+      manager.setSelectedPath(newPath);
+    }
+  }
+
+  protected void paintMenuItem(Graphics g, JComponent c,
+                                   Icon checkIcon, Icon arrowIcon,
+                                   Color background, Color foreground,
+                                   int defaultTextIconGap) {
+    // Save original graphics font and color
+    Font holdf = g.getFont();
+    Color holdc = g.getColor();
+
+    JMenuItem mi = (JMenuItem) c;
+    g.setFont(mi.getFont());
+
+    Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
+    applyInsets(viewRect, mi.getInsets());
+
+    MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
+        arrowIcon, viewRect, defaultTextIconGap, "-", //todo[kb] use protected field BasicMenuItemUI.acceleratorDelimiter when we move to java 1.7
+        mi.getComponentOrientation().isLeftToRight(), mi.getFont(),
+        acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
+        getPropertyPrefix());
+    MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
+
+    paintBackground(g, mi, background);
+    paintCheckIcon(g, lh, lr, holdc, foreground);
+    paintIcon(g, lh, lr, holdc);
+    g.setColor(foreground);
+    paintText(g, lh, lr);
+    paintAccText(g, lh, lr);
+    paintArrowIcon(g, lh, lr, foreground);
+
+    // Restore original graphics font and color
+    g.setColor(holdc);
+    g.setFont(holdf);
+  }
+
+  protected void paintIcon(Graphics g, MenuItemLayoutHelper lh,
+                         MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
+      if (lh.getIcon() != null) {
+          Icon icon;
+          ButtonModel model = lh.getMenuItem().getModel();
+          if (!model.isEnabled()) {
+              icon = lh.getMenuItem().getDisabledIcon();
+          } else if (model.isPressed() && model.isArmed()) {
+              icon = lh.getMenuItem().getPressedIcon();
+              if (icon == null) {
+                  // Use default icon
+                  icon = lh.getMenuItem().getIcon();
+              }
+          } else {
+              icon = lh.getMenuItem().getIcon();
+          }
+
+          if (icon != null) {
+              icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
+                      lr.getIconRect().y);
+              g.setColor(holdc);
+          }
+      }
+  }
+
+  protected void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
+                              MenuItemLayoutHelper.LayoutResult lr,
+                              Color holdc, Color foreground) {
+      if (lh.getCheckIcon() != null) {
+          ButtonModel model = lh.getMenuItem().getModel();
+          if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+                  && model.isSelected())) {
+              g.setColor(foreground);
+          } else {
+              g.setColor(holdc);
+          }
+          if (lh.useCheckAndArrow()) {
+              lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
+                      lr.getCheckRect().x, lr.getCheckRect().y);
+          }
+          g.setColor(holdc);
+      }
+  }
+
+  protected void paintAccText(Graphics g, MenuItemLayoutHelper lh,
+                              MenuItemLayoutHelper.LayoutResult lr) {
+    if (!lh.getAccText().equals("")) {
+      ButtonModel model = lh.getMenuItem().getModel();
+      g.setFont(lh.getAccFontMetrics().getFont());
+      if (!model.isEnabled()) {
+        // *** paint the accText disabled
+        if (disabledForeground != null) {
+          g.setColor(disabledForeground);
+          SwingUtilities2.drawString(lh.getMenuItem(), g,
+              lh.getAccText(), lr.getAccRect().x,
+              lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+        } else {
+          g.setColor(lh.getMenuItem().getBackground().brighter());
+          SwingUtilities2.drawString(lh.getMenuItem(), g,
+              lh.getAccText(), lr.getAccRect().x,
+              lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+          g.setColor(lh.getMenuItem().getBackground().darker());
+          SwingUtilities2.drawString(lh.getMenuItem(), g,
+              lh.getAccText(), lr.getAccRect().x - 1,
+              lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
+        }
+      } else {
+        // *** paint the accText normally
+        if (model.isArmed()
+            || (lh.getMenuItem() instanceof JMenu
+            && model.isSelected())) {
+          g.setColor(acceleratorSelectionForeground);
+        } else {
+          g.setColor(acceleratorForeground);
+        }
+        SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
+                                   lr.getAccRect().x, lr.getAccRect().y +
+                                                      lh.getAccFontMetrics().getAscent());
+      }
+    }
+  }
+
+  protected void paintText(Graphics g, MenuItemLayoutHelper lh,
+                         MenuItemLayoutHelper.LayoutResult lr) {
+      if (!lh.getText().equals("")) {
+          if (lh.getHtmlView() != null) {
+              // Text is HTML
+              lh.getHtmlView().paint(g, lr.getTextRect());
+          } else {
+              // Text isn't HTML
+              paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText());
+          }
+      }
+  }
+
+  protected void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
+                              MenuItemLayoutHelper.LayoutResult lr,
+                              Color foreground) {
+      if (lh.getArrowIcon() != null) {
+          ButtonModel model = lh.getMenuItem().getModel();
+          if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+                              && model.isSelected())) {
+              g.setColor(foreground);
+          }
+          if (lh.useCheckAndArrow()) {
+              lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
+                      lr.getArrowRect().x, lr.getArrowRect().y);
+          }
+      }
+  }
+
+  protected void applyInsets(Rectangle rect, Insets insets) {
+      if(insets != null) {
+          rect.x += insets.left;
+          rect.y += insets.top;
+          rect.width -= (insets.right + rect.x);
+          rect.height -= (insets.bottom + rect.y);
+      }
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
new file mode 100644
index 0000000..1048e5d
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.ColorUtil;
+import com.intellij.ui.Gray;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaRadioButtonMenuItemUI extends DarculaMenuItemUIBase {
+  @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+  public static ComponentUI createUI(JComponent c) {
+    return new DarculaRadioButtonMenuItemUI();
+  }
+
+  protected String getPropertyPrefix() {
+      return "RadioButtonMenuItem";
+  }
+
+  @Override
+  protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+    Graphics2D g = (Graphics2D) g2;
+    final GraphicsConfig config = new GraphicsConfig(g);
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+    g.translate(lr.getCheckRect().x-1, lr.getCheckRect().y-1);
+
+    int rad = 5;
+
+    final int x = 0;
+    final int y = 0;
+    final int w = 13;
+    final int h = 13;
+
+    g.translate(x, y);
+
+    //setup AA for lines
+    Color bg = lh.getMenuItem().getBackground();
+    g.setPaint(new GradientPaint(0, 0, ColorUtil.shift(bg, 1.5),
+        0, 16, ColorUtil.shift(bg, 1.2)));
+
+    g.fillOval(0, 1, w - 1, h - 1);
+
+        g.setPaint(new GradientPaint(w / 2, 1, Gray._160.withAlpha(90), w / 2, h, Gray._100.withAlpha(90)));
+        g.drawOval(0, 2, w - 1, h - 1);
+
+        g.setPaint(Gray._40.withAlpha(200));
+    g.drawOval(0, 1, w - 1, h - 1);
+
+    if (lh.getMenuItem().isSelected()) {
+      final boolean enabled = lh.getMenuItem().isEnabled();
+      g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));
+      g.fillOval((w - rad)/2 , h/2 , rad, rad);
+      g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor"));
+      g.fillOval((w - rad)/2 , h/2 - 1, rad, rad);
+    }
+    config.restore();
+    g.translate(-x, -y);
+
+
+    g.translate(-lr.getCheckRect().x+1, -lr.getCheckRect().y+1);
+    config.restore();
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
index 2b8a8a4..fcbe27f 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
@@ -15,383 +15,89 @@
  */
 package com.intellij.ide.util;
 
-import com.intellij.ui.*;
-import com.intellij.ui.table.JBTable;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.ComponentWithEmptyText;
-import com.intellij.util.ui.StatusText;
-import com.intellij.util.ui.Table;
-import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import javax.swing.*;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.*;
+import javax.swing.table.TableCellRenderer;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @see ChooseElementsDialog
  */
-public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
-  private JBTable myTable = null;
-  private MyTableModel myTableModel = null;
-  private boolean myColorUnmarkedElements = true;
-  private final List<ElementsMarkListener<T>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
-  private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
-  private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+public class ElementsChooser<T> extends MultiStateElementsChooser<T, Boolean> {
+  private static final BooleanMarkStateDescriptor MARK_STATE_DESCRIPTOR = new BooleanMarkStateDescriptor();
 
   public interface ElementsMarkListener<T> {
     void elementMarkChanged(T element, boolean isMarked);
   }
 
   public ElementsChooser(final boolean elementsCanBeMarked) {
-    this(null, false, elementsCanBeMarked);
+    super(elementsCanBeMarked, ElementsChooser.<T>getMarkStateDescriptor());
   }
 
   public ElementsChooser(List<T> elements, boolean marked) {
-    this(elements, marked, true);
-  }
-
-  private ElementsChooser(@Nullable List<T> elements, boolean marked, boolean elementsCanBeMarked) {
-    super(new BorderLayout());
-
-    myTableModel = new MyTableModel(elementsCanBeMarked);
-    myTable = new Table(myTableModel);
-    myTable.setShowGrid(false);
-    myTable.setIntercellSpacing(new Dimension(0, 0));
-    myTable.setTableHeader(null);
-    myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
-    myTable.setColumnSelectionAllowed(false);
-    JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
-    pane.setPreferredSize(new Dimension(100, 155));
-    TableColumnModel columnModel = myTable.getColumnModel();
-
-    if (elementsCanBeMarked) {
-      TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
-      TableUtil.setupCheckboxColumn(checkMarkColumn);
-      checkMarkColumn.setCellRenderer(new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
-    }
-    columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
-
-    add(pane, BorderLayout.CENTER);
-    myTable.registerKeyboardAction(
-      new ActionListener() {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          final int[] selectedRows = myTable.getSelectedRows();
-          boolean currentlyMarked = true;
-          for (int selectedRow : selectedRows) {
-            currentlyMarked = myTableModel.isElementMarked(selectedRow);
-            if (!currentlyMarked) {
-              break;
-            }
-          }
-          myTableModel.setMarked(selectedRows, !currentlyMarked);
-        }
-      },
-      KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
-      JComponent.WHEN_FOCUSED
-    );
-
-    final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
-      @Override
-      public int getSelectedIndex() {
-        return myTable.getSelectedRow();
-      }
-
-      @Override
-      protected int convertIndexToModel(int viewIndex) {
-        return myTable.convertRowIndexToModel(viewIndex);
-      }
-
-      @Override
-      public Object[] getAllElements() {
-        final int count = myTableModel.getRowCount();
-        Object[] elements = new Object[count];
-        for (int idx = 0; idx < count; idx++) {
-          elements[idx] = myTableModel.getElementAt(idx);
-        }
-        return elements;
-      }
-
-      @Override
-      public String getElementText(Object element) {
-        return getItemText((T)element);
-      }
-
-      @Override
-      public void selectElement(Object element, String selectedText) {
-        final int count = myTableModel.getRowCount();
-        for (int row = 0; row < count; row++) {
-          if (element.equals(myTableModel.getElementAt(row))) {
-            final int viewRow = myTable.convertRowIndexToView(row);
-            myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
-            TableUtil.scrollSelectionToVisible(myTable);
-            break;
-          }
-        }
-      }
-    };
-    speedSearch.setComparator(new SpeedSearchComparator(false));
-    setElements(elements, marked);
-    installActions(myTable);
-  }
-
-  private static void installActions(JTable table) {
-    InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
-    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
-    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
-    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
-    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
-  }
-
-  @NotNull
-  @Override
-  public StatusText getEmptyText() {
-    return myTable.getEmptyText();
-  }
-
-  @NotNull
-  @Override
-  public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
-    return myTable.getExpandableItemsHandler();
-  }
-
-  @Override
-  public void setExpandableItemsEnabled(boolean enabled) {
-    myTable.setExpandableItemsEnabled(enabled);
-  }
-
-  public void setSingleSelectionMode() {
-    myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-  }
-
-  public void refresh() {
-    myTableModel.fireTableDataChanged();
-  }
-
-  public void refresh(T element) {
-    final int row = myTableModel.getElementRow(element);
-    if (row >= 0) {
-      myTableModel.fireTableRowsUpdated(row, row);
-    }
-  }
-
-  private int[] mySavedSelection = null;
-  public void saveSelection() {
-    mySavedSelection = myTable.getSelectedRows();
-  }
-
-  public void restoreSelection() {
-    if (mySavedSelection != null) {
-      TableUtil.selectRows(myTable, mySavedSelection);
-      mySavedSelection = null;
-    }
-  }
-
-  public boolean isColorUnmarkedElements() {
-    return myColorUnmarkedElements;
-  }
-
-  public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
-    myColorUnmarkedElements = colorUnmarkedElements;
+    super(elements, marked, ElementsChooser.<T>getMarkStateDescriptor());
   }
 
   public void addElementsMarkListener(ElementsMarkListener<T> listener) {
-    myListeners.add(listener);
+    addElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
   }
 
   public void removeElementsMarkListener(ElementsMarkListener<T> listener) {
-    myListeners.remove(listener);
-  }
-
-  public void addListSelectionListener(ListSelectionListener listener) {
-    myTable.getSelectionModel().addListSelectionListener(listener);
-  }
-  public void removeListSelectionListener(ListSelectionListener listener) {
-    myTable.getSelectionModel().removeListSelectionListener(listener);
+    removeElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
   }
 
   public void addElement(T element, final boolean isMarked) {
-    addElement(element, isMarked, element instanceof ElementProperties ? (ElementProperties)element : null);
+    addElement(element, getMarkState(isMarked));
   }
 
   /**
    * Check if element is marked
+   *
    * @param element an element to test
    * @return true if element is marked
    */
   public boolean isElementMarked(T element) {
-    final int elementRow = myTableModel.getElementRow(element);
-    return myTableModel.isElementMarked(elementRow);
+    return getElementMarkState(element);
   }
 
   /**
-   * Check if element is marked
+   * Update element mark
+   *
    * @param element an element to test
-   * @param marked a new value of mark.
+   * @param marked  a new value of mark.
    */
   public void setElementMarked(T element, boolean marked) {
-    final int elementRow = myTableModel.getElementRow(element);
-    myTableModel.setMarked(elementRow, marked);
+    setElementMarkState(element, getMarkState(marked));
   }
 
-
-  public void removeElement(T element) {
-    final int elementRow = myTableModel.getElementRow(element);
-    if (elementRow < 0) {
-      return; // no such element
-    }
-    final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
-
-    myTableModel.removeElement(element);
-    myElementToPropertiesMap.remove(element);
-
-    if (wasSelected) {
-      final int rowCount = myTableModel.getRowCount();
-      if (rowCount > 0) {
-        selectRow(elementRow % rowCount);
-      }
-      else {
-        myTable.getSelectionModel().clearSelection();
-      }
-    }
-    myTable.requestFocus();
-  }
-
-  public void removeAllElements() {
-    myTableModel.removeAllElements();
-    myTable.getSelectionModel().clearSelection();
-  }
-
-  private void selectRow(final int row) {
-    myTable.getSelectionModel().setSelectionInterval(row, row);
-    myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
-  }
-
-  public void moveElement(T element, int newRow) {
-    final int elementRow = myTableModel.getElementRow(element);
-    if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
-      return;
-    }
-    final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
-    myTableModel.changeElementRow(element, newRow);
-    if (wasSelected) {
-      selectRow(newRow);
-    }
-  }
-
-  public interface ElementProperties {
-    @Nullable
-    Icon getIcon();
-    @Nullable
-    Color getColor();
-  }
   public void addElement(T element, final boolean isMarked, ElementProperties elementProperties) {
-    myTableModel.addElement(element, isMarked);
-    myElementToPropertiesMap.put(element, elementProperties);
-    selectRow(myTableModel.getRowCount() - 1);
-    myTable.requestFocus();
-  }
-
-  public void setElementProperties(T element, ElementProperties properties) {
-    myElementToPropertiesMap.put(element, properties);
+    addElement(element, getMarkState(isMarked), elementProperties);
   }
 
   public void setElements(List<T> elements, boolean marked) {
-    myTableModel.clear();
-    myTableModel.addElements(elements, marked);
-  }
-
-  @Nullable
-  public T getSelectedElement() {
-    final int selectedRow = getSelectedElementRow();
-    return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
-  }
-
-  public int getSelectedElementRow() {
-    return myTable.getSelectedRow();
-  }
-
-  @NotNull
-  public List<T> getSelectedElements() {
-    final List<T> elements = new ArrayList<T>();
-    final int[] selectedRows = myTable.getSelectedRows();
-    for (int selectedRow : selectedRows) {
-      if (selectedRow < 0) {
-        continue;
-      }
-      elements.add(myTableModel.getElementAt(selectedRow));
-    }
-    return elements;
-  }
-
-  public void selectElements(Collection<? extends T> elements) {
-    if (elements.isEmpty()) {
-      myTable.clearSelection();
-      return;
-    }
-    final int[] rows = getElementsRows(elements);
-    TableUtil.selectRows(myTable, rows);
-    TableUtil.scrollSelectionToVisible(myTable);
-    myTable.requestFocus();
-  }
-
-  private int[] getElementsRows(final Collection<? extends T> elements) {
-    final int[] rows = new int[elements.size()];
-    int index = 0;
-    for (final T element : elements) {
-      rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
-    }
-    return rows;
+    setElements(elements, getMarkState(marked));
   }
 
   public void markElements(Collection<T> elements) {
-    myTableModel.setMarked(getElementsRows(elements), true);
+    markElements(elements, Boolean.TRUE);
   }
 
   @NotNull
   public List<T> getMarkedElements() {
-    final int count = myTableModel.getRowCount();
+    Map<T, Boolean> elementMarkStates = getElementMarkStates();
     List<T> elements = new ArrayList<T>();
-    for (int idx = 0; idx < count; idx++) {
-      final T element = myTableModel.getElementAt(idx);
-      if (myTableModel.isElementMarked(idx)) {
-        elements.add(element);
+    for (Map.Entry<T, Boolean> entry : elementMarkStates.entrySet()) {
+      if (entry.getValue()) {
+        elements.add(entry.getKey());
       }
     }
     return elements;
   }
 
-  public void sort(Comparator<T> comparator) {
-    myTableModel.sort(comparator);
-  }
-  
-  @Override
-  public void setEnabled(boolean enabled) {
-    super.setEnabled(enabled);
-    myTable.setRowSelectionAllowed(enabled);
-    myTableModel.fireTableDataChanged();
-  }
-
-  public void stopEditing() {
-    TableCellEditor editor = myTable.getCellEditor();
-    if (editor != null) {
-      editor.stopCellEditing();
-    }
-  }
-
-  public JComponent getComponent() {
-    return myTable;
-  }
-
   public void invertSelection() {
     final int count = getElementCount();
     for (int i = 0; i < count; i++) {
@@ -401,264 +107,89 @@
   }
 
   public void setAllElementsMarked(boolean marked) {
-    final int[] rows = new int[myTableModel.getRowCount()];
-    for (int idx = 0; idx < rows.length; idx++) {
-      rows[idx] = idx;
-    }
-    myTableModel.setMarked(rows, marked);
+    setAllElementsMarked(getMarkState(marked));
   }
 
-  private void notifyElementMarked(T element, boolean isMarked) {
-    for (ElementsMarkListener<T> listener : myListeners) {
-      listener.elementMarkChanged(element, isMarked);
-    }
+  private static Boolean getMarkState(boolean marked) {
+    return marked;
   }
 
-  public void clear() {
-    myTableModel.clear();
-    myElementToPropertiesMap.clear();
+  @SuppressWarnings("unchecked")
+  private static <T> MarkStateDescriptor<T, Boolean> getMarkStateDescriptor() {
+    return MARK_STATE_DESCRIPTOR;
   }
 
-  public int getElementCount() {
-    return myTableModel.getRowCount();
-  }
-
-  public T getElementAt(int row) {
-    return myTableModel.getElementAt(row);
-  }
-
-  public void disableElement(T element) {
-    myDisabledMap.put(element, Boolean.TRUE);
-  }
-  
-  private final class MyTableModel extends AbstractTableModel {
-    private final List<T> myElements = new ArrayList<T>();
-    private final Map<T, Boolean> myMarkedMap = new HashMap<T, Boolean>();
-    public final int CHECK_MARK_COLUM_INDEX;
-    public final int ELEMENT_COLUMN_INDEX;
-    private final boolean myElementsCanBeMarked;
-
-    public MyTableModel(final boolean elementsCanBeMarked) {
-      myElementsCanBeMarked = elementsCanBeMarked;
-      if (elementsCanBeMarked) {
-        CHECK_MARK_COLUM_INDEX = 0;
-        ELEMENT_COLUMN_INDEX = 1;
-      }
-      else {
-        CHECK_MARK_COLUM_INDEX = -1;
-        ELEMENT_COLUMN_INDEX = 0;
-      }
-    }
-    
-    public void sort(Comparator<T> comparator) {
-      Collections.sort(myElements, comparator);
-      fireTableDataChanged();
-    }
-    
-    public T getElementAt(int index) {
-      return myElements.get(index);
-    }
-
-    public boolean isElementMarked(int index) {
-      final T element = myElements.get(index);
-      final Boolean isMarked = myMarkedMap.get(element);
-      return isMarked.booleanValue();
-    }
-
-    private void addElement(T element, boolean isMarked) {
-      myElements.add(element);
-      myMarkedMap.put(element, isMarked? Boolean.TRUE : Boolean.FALSE);
-      int row = myElements.size() - 1;
-      fireTableRowsInserted(row, row);
-    }
-
-    private void addElements(@Nullable List<T> elements, boolean isMarked) {
-      if (elements == null || elements.isEmpty()) {
-        return;
-      }
-      for (final T element : elements) {
-        myElements.add(element);
-        myMarkedMap.put(element, isMarked ? Boolean.TRUE : Boolean.FALSE);
-      }
-      fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
-    }
-
-    public void removeElement(T element) {
-      final boolean reallyRemoved = myElements.remove(element);
-      if (reallyRemoved) {
-        myMarkedMap.remove(element);
-        fireTableDataChanged();
-      }
-    }
-
-    public void changeElementRow(T element, int row) {
-      final boolean reallyRemoved = myElements.remove(element);
-      if (reallyRemoved) {
-        myElements.add(row, element);
-        fireTableDataChanged();
-      }
-    }
-
-    public int getElementRow(T element) {
-      return myElements.indexOf(element);
-    }
-
-    public void removeAllElements() {
-      myElements.clear();
-      fireTableDataChanged();
-    }
-
-    public void removeRows(int[] rows) {
-      final List<T> toRemove = new ArrayList<T>();
-      for (int row : rows) {
-        final T element = myElements.get(row);
-        toRemove.add(element);
-        myMarkedMap.remove(element);
-      }
-      myElements.removeAll(toRemove);
-      fireTableDataChanged();
-    }
-
+  private static class BooleanMarkStateDescriptor<T> implements MarkStateDescriptor<T, Boolean> {
+    @NotNull
     @Override
-    public int getRowCount() {
-      return myElements.size();
+    public Boolean getDefaultState(@NotNull T element) {
+      return Boolean.FALSE;
     }
 
+    @NotNull
     @Override
-    public int getColumnCount() {
-      return myElementsCanBeMarked? 2 : 1;
+    public Boolean getNextState(@NotNull T element, @NotNull Boolean state) {
+      return !state;
     }
 
-    @Override
     @Nullable
-    public Object getValueAt(int rowIndex, int columnIndex) {
-      T element = myElements.get(rowIndex);
-      if (columnIndex == ELEMENT_COLUMN_INDEX) {
-        return element;
+    @Override
+    public Boolean getNextState(@NotNull Map<T, Boolean> elementsWithStates) {
+      boolean currentlyMarked = true;
+      for (Boolean state : elementsWithStates.values()) {
+        currentlyMarked = state;
+        if (!currentlyMarked) {
+          break;
+        }
       }
-      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
-        return myMarkedMap.get(element);
-      }
+      return !currentlyMarked;
+    }
+
+    @Override
+    public boolean isMarked(@NotNull Boolean state) {
+      return state;
+    }
+
+    @Nullable
+    @Override
+    public Boolean getMarkState(@Nullable Object value) {
+      return value instanceof Boolean ? ((Boolean)value) : null;
+    }
+
+    @Nullable
+    @Override
+    public TableCellRenderer getMarkRenderer() {
       return null;
     }
-
-    @Override
-    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
-      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
-        setMarked(rowIndex, ((Boolean)aValue).booleanValue());
-      }
-    }
-
-    private void setMarked(int rowIndex, final boolean marked) {
-      final T element = myElements.get(rowIndex);
-      final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
-      final Boolean prevValue = myMarkedMap.put(element, newValue);
-      fireTableRowsUpdated(rowIndex, rowIndex);
-      if (!newValue.equals(prevValue)) {
-        notifyElementMarked(element, marked);
-      }
-    }
-
-    private void setMarked(int[] rows, final boolean marked) {
-      if (rows == null || rows.length == 0) {
-        return;
-      }
-      int firstRow = Integer.MAX_VALUE;
-      int lastRow = Integer.MIN_VALUE;
-      final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
-      for (final int row : rows) {
-        final T element = myElements.get(row);
-        final Boolean prevValue = myMarkedMap.put(element, newValue);
-        if (!newValue.equals(prevValue)) {
-          notifyElementMarked(element, newValue.booleanValue());
-        }
-        firstRow = Math.min(firstRow, row);
-        lastRow = Math.max(lastRow, row);
-      }
-      fireTableRowsUpdated(firstRow, lastRow);
-    }
-
-    @Override
-    public Class getColumnClass(int columnIndex) {
-      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
-        return Boolean.class;
-      }
-      return super.getColumnClass(columnIndex);
-    }
-
-    @Override
-    public boolean isCellEditable(int rowIndex, int columnIndex) {
-      if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
-        return false;
-      }
-      final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
-      return myDisabledMap.get(o) == null; 
-    }
-
-    public void clear() {
-      myElements.clear();
-      myMarkedMap.clear();
-      fireTableDataChanged();
-    }
   }
 
-  protected String getItemText(@NotNull T value) {
-    return value.toString();
-  }
+  private static class ElementsMarkStateListenerAdapter<T> implements ElementsMarkStateListener<T, Boolean> {
+    private final ElementsMarkListener<T> myListener;
 
-  @Nullable
-  protected Icon getItemIcon(@NotNull T value) {
-    return null;
-  }
-
-  private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
-    @Override
-    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-      final Color color = UIUtil.getTableFocusCellBackground();
-      Component component;
-      T t = (T)value;
-      try {
-        UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
-        component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-        setText(t != null ? getItemText(t) : "");
-        if (component instanceof JLabel) {
-          ((JLabel)component).setBorder(noFocusBorder);
-        }
-      }
-      finally {
-        UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
-      }
-      final MyTableModel model = (MyTableModel)table.getModel();
-      component.setEnabled(ElementsChooser.this.isEnabled() && (!myColorUnmarkedElements || model.isElementMarked(row)));
-      final ElementProperties properties = myElementToPropertiesMap.get(t);
-      if (component instanceof JLabel) {
-        final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
-        JLabel label = (JLabel)component;
-        label.setIcon(icon);
-        label.setDisabledIcon(icon);
-      }
-      component.setForeground(properties != null && properties.getColor() != null ?
-                              properties.getColor() :
-                              isSelected ? table.getSelectionForeground() : table.getForeground());
-      return component;
-    }
-  }
-
-  private class CheckMarkColumnCellRenderer implements TableCellRenderer {
-    private final TableCellRenderer myDelegate;
-
-    public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
-      myDelegate = delegate;
+    public ElementsMarkStateListenerAdapter(ElementsMarkListener<T> listener) {
+      myListener = listener;
     }
 
     @Override
-    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-      Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-      component.setEnabled(isEnabled());
-      if (component instanceof JComponent) {
-        ((JComponent)component).setBorder(null);
-      }
-      return component;
+    public void elementMarkChanged(T element, Boolean markState) {
+      myListener.elementMarkChanged(element, markState);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      ElementsMarkStateListenerAdapter that = (ElementsMarkStateListenerAdapter)o;
+
+      if (!myListener.equals(that.myListener)) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return myListener.hashCode();
     }
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
new file mode 100644
index 0000000..bccbd7b
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
@@ -0,0 +1,692 @@
+/*
+ * 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.
+ */
+package com.intellij.ide.util;
+
+import com.intellij.ui.*;
+import com.intellij.ui.table.JBTable;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ComponentWithEmptyText;
+import com.intellij.util.ui.StatusText;
+import com.intellij.util.ui.Table;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.*;
+import java.util.List;
+
+public class MultiStateElementsChooser<T, S> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
+  private MarkStateDescriptor<T, S> myMarkStateDescriptor;
+  private JBTable myTable = null;
+  private MyTableModel myTableModel = null;
+  private boolean myColorUnmarkedElements = true;
+  private final List<ElementsMarkStateListener<T, S>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+  private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
+  private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+
+  public interface ElementsMarkStateListener<T, S> {
+    void elementMarkChanged(T element, S markState);
+  }
+
+  public interface MarkStateDescriptor<T, S> {
+    @NotNull
+    S getDefaultState(@NotNull T element);
+
+    @NotNull
+    S getNextState(@NotNull T element, @NotNull S state);
+
+    @Nullable
+    S getNextState(@NotNull Map<T, S> elementsWithStates);
+
+    boolean isMarked(@NotNull S state);
+
+    @Nullable
+    S getMarkState(@Nullable Object value);
+
+    @Nullable
+    TableCellRenderer getMarkRenderer();
+  }
+
+  public MultiStateElementsChooser(final boolean elementsCanBeMarked, MarkStateDescriptor<T, S> markStateDescriptor) {
+    this(null, null, elementsCanBeMarked, markStateDescriptor);
+  }
+
+  public MultiStateElementsChooser(List<T> elements, S markState, MarkStateDescriptor<T, S> markStateDescriptor) {
+    this(elements, markState, true, markStateDescriptor);
+  }
+
+  private MultiStateElementsChooser(@Nullable List<T> elements,
+                                    S markState,
+                                    boolean elementsCanBeMarked,
+                                    MarkStateDescriptor<T, S> markStateDescriptor) {
+    super(new BorderLayout());
+
+    myMarkStateDescriptor = markStateDescriptor;
+
+    myTableModel = new MyTableModel(elementsCanBeMarked);
+    myTable = new Table(myTableModel);
+    myTable.setShowGrid(false);
+    myTable.setIntercellSpacing(new Dimension(0, 0));
+    myTable.setTableHeader(null);
+    myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+    myTable.setColumnSelectionAllowed(false);
+    JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
+    pane.setPreferredSize(new Dimension(100, 155));
+    TableColumnModel columnModel = myTable.getColumnModel();
+
+    if (elementsCanBeMarked) {
+      TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
+      TableUtil.setupCheckboxColumn(checkMarkColumn);
+      TableCellRenderer checkMarkRenderer = myMarkStateDescriptor.getMarkRenderer();
+      if (checkMarkRenderer == null) {
+        checkMarkRenderer = new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class));
+      }
+      checkMarkColumn.setCellRenderer(checkMarkRenderer);
+    }
+    columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
+
+    add(pane, BorderLayout.CENTER);
+    myTable.registerKeyboardAction(
+      new ActionListener() {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+          final int[] selectedRows = myTable.getSelectedRows();
+          Map<T, S> selectedElements = new LinkedHashMap<T, S>(selectedRows.length);
+          for (int selectedRow : selectedRows) {
+            selectedElements.put(myTableModel.getElementAt(selectedRow), myTableModel.getElementMarkState(selectedRow));
+          }
+          S nextState = myMarkStateDescriptor.getNextState(selectedElements);
+          if (nextState != null) {
+            myTableModel.setMarkState(selectedRows, nextState);
+          }
+        }
+      },
+      KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
+      JComponent.WHEN_FOCUSED
+    );
+
+    final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
+      @Override
+      public int getSelectedIndex() {
+        return myTable.getSelectedRow();
+      }
+
+      @Override
+      protected int convertIndexToModel(int viewIndex) {
+        return myTable.convertRowIndexToModel(viewIndex);
+      }
+
+      @Override
+      public Object[] getAllElements() {
+        final int count = myTableModel.getRowCount();
+        Object[] elements = new Object[count];
+        for (int idx = 0; idx < count; idx++) {
+          elements[idx] = myTableModel.getElementAt(idx);
+        }
+        return elements;
+      }
+
+      @Override
+      public String getElementText(Object element) {
+        return getItemText((T)element);
+      }
+
+      @Override
+      public void selectElement(Object element, String selectedText) {
+        final int count = myTableModel.getRowCount();
+        for (int row = 0; row < count; row++) {
+          if (element.equals(myTableModel.getElementAt(row))) {
+            final int viewRow = myTable.convertRowIndexToView(row);
+            myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
+            TableUtil.scrollSelectionToVisible(myTable);
+            break;
+          }
+        }
+      }
+    };
+    speedSearch.setComparator(new SpeedSearchComparator(false));
+    setElements(elements, markState);
+    installActions(myTable);
+  }
+
+  private static void installActions(JTable table) {
+    InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
+    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
+    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
+    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
+    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
+  }
+
+  @NotNull
+  @Override
+  public StatusText getEmptyText() {
+    return myTable.getEmptyText();
+  }
+
+  @NotNull
+  @Override
+  public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
+    return myTable.getExpandableItemsHandler();
+  }
+
+  @Override
+  public void setExpandableItemsEnabled(boolean enabled) {
+    myTable.setExpandableItemsEnabled(enabled);
+  }
+
+  public void setSingleSelectionMode() {
+    myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+  }
+
+  public void refresh() {
+    myTableModel.fireTableDataChanged();
+  }
+
+  public void refresh(T element) {
+    final int row = myTableModel.getElementRow(element);
+    if (row >= 0) {
+      myTableModel.fireTableRowsUpdated(row, row);
+    }
+  }
+
+  private int[] mySavedSelection = null;
+  public void saveSelection() {
+    mySavedSelection = myTable.getSelectedRows();
+  }
+
+  public void restoreSelection() {
+    if (mySavedSelection != null) {
+      TableUtil.selectRows(myTable, mySavedSelection);
+      mySavedSelection = null;
+    }
+  }
+
+  public boolean isColorUnmarkedElements() {
+    return myColorUnmarkedElements;
+  }
+
+  public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
+    myColorUnmarkedElements = colorUnmarkedElements;
+  }
+
+  public void addElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+    myListeners.add(listener);
+  }
+
+  public void removeElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+    myListeners.remove(listener);
+  }
+
+  public void addListSelectionListener(ListSelectionListener listener) {
+    myTable.getSelectionModel().addListSelectionListener(listener);
+  }
+  public void removeListSelectionListener(ListSelectionListener listener) {
+    myTable.getSelectionModel().removeListSelectionListener(listener);
+  }
+
+  public void addElement(T element, final S markState) {
+    addElement(element, markState, element instanceof ElementProperties ? (ElementProperties)element : null);
+  }
+
+  /**
+   * Gets element mark state
+   * @param element an element to test
+   * @return state of element
+   */
+  public S getElementMarkState(T element) {
+    final int elementRow = myTableModel.getElementRow(element);
+    return myTableModel.getElementMarkState(elementRow);
+  }
+
+  /**
+   * Update element mark state
+   * @param element an element to test
+   * @param markState a new value of mark state
+   */
+  public void setElementMarkState(T element, S markState) {
+    final int elementRow = myTableModel.getElementRow(element);
+    myTableModel.setMarkState(elementRow, markState);
+  }
+
+
+  public void removeElement(T element) {
+    final int elementRow = myTableModel.getElementRow(element);
+    if (elementRow < 0) {
+      return; // no such element
+    }
+    final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+
+    myTableModel.removeElement(element);
+    myElementToPropertiesMap.remove(element);
+
+    if (wasSelected) {
+      final int rowCount = myTableModel.getRowCount();
+      if (rowCount > 0) {
+        selectRow(elementRow % rowCount);
+      }
+      else {
+        myTable.getSelectionModel().clearSelection();
+      }
+    }
+    myTable.requestFocus();
+  }
+
+  public void removeAllElements() {
+    myTableModel.removeAllElements();
+    myTable.getSelectionModel().clearSelection();
+  }
+
+  private void selectRow(final int row) {
+    myTable.getSelectionModel().setSelectionInterval(row, row);
+    myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
+  }
+
+  public void moveElement(T element, int newRow) {
+    final int elementRow = myTableModel.getElementRow(element);
+    if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
+      return;
+    }
+    final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+    myTableModel.changeElementRow(element, newRow);
+    if (wasSelected) {
+      selectRow(newRow);
+    }
+  }
+
+  public interface ElementProperties {
+    @Nullable
+    Icon getIcon();
+    @Nullable
+    Color getColor();
+  }
+
+  public void addElement(T element, final S markState, ElementProperties elementProperties) {
+    myTableModel.addElement(element, markState);
+    myElementToPropertiesMap.put(element, elementProperties);
+    selectRow(myTableModel.getRowCount() - 1);
+    myTable.requestFocus();
+  }
+
+  public void setElementProperties(T element, ElementProperties properties) {
+    myElementToPropertiesMap.put(element, properties);
+  }
+
+  public void setElements(List<T> elements, S markState) {
+    myTableModel.clear();
+    myTableModel.addElements(elements, markState);
+  }
+
+  @Nullable
+  public T getSelectedElement() {
+    final int selectedRow = getSelectedElementRow();
+    return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
+  }
+
+  public int getSelectedElementRow() {
+    return myTable.getSelectedRow();
+  }
+
+  @NotNull
+  public List<T> getSelectedElements() {
+    final List<T> elements = new ArrayList<T>();
+    final int[] selectedRows = myTable.getSelectedRows();
+    for (int selectedRow : selectedRows) {
+      if (selectedRow < 0) {
+        continue;
+      }
+      elements.add(myTableModel.getElementAt(selectedRow));
+    }
+    return elements;
+  }
+
+  public void selectElements(Collection<? extends T> elements) {
+    if (elements.isEmpty()) {
+      myTable.clearSelection();
+      return;
+    }
+    final int[] rows = getElementsRows(elements);
+    TableUtil.selectRows(myTable, rows);
+    TableUtil.scrollSelectionToVisible(myTable);
+    myTable.requestFocus();
+  }
+
+  private int[] getElementsRows(final Collection<? extends T> elements) {
+    final int[] rows = new int[elements.size()];
+    int index = 0;
+    for (final T element : elements) {
+      rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
+    }
+    return rows;
+  }
+
+  public void markElements(Collection<T> elements, S markState) {
+    myTableModel.setMarkState(getElementsRows(elements), markState);
+  }
+
+  @NotNull
+  public Map<T, S> getElementMarkStates() {
+    final int count = myTableModel.getRowCount();
+    Map<T, S> elements = new LinkedHashMap<T, S>();
+    for (int idx = 0; idx < count; idx++) {
+      final T element = myTableModel.getElementAt(idx);
+      elements.put(element, myTableModel.getElementMarkState(idx));
+    }
+    return elements;
+  }
+
+  public void sort(Comparator<T> comparator) {
+    myTableModel.sort(comparator);
+  }
+
+  @Override
+  public void setEnabled(boolean enabled) {
+    super.setEnabled(enabled);
+    myTable.setRowSelectionAllowed(enabled);
+    myTableModel.fireTableDataChanged();
+  }
+
+  public void stopEditing() {
+    TableCellEditor editor = myTable.getCellEditor();
+    if (editor != null) {
+      editor.stopCellEditing();
+    }
+  }
+
+  public JComponent getComponent() {
+    return myTable;
+  }
+
+  public void setAllElementsMarked(S markState) {
+    final int[] rows = new int[myTableModel.getRowCount()];
+    for (int idx = 0; idx < rows.length; idx++) {
+      rows[idx] = idx;
+    }
+    myTableModel.setMarkState(rows, markState);
+  }
+
+  private void notifyElementMarked(T element, S markState) {
+    for (ElementsMarkStateListener<T, S> listener : myListeners) {
+      listener.elementMarkChanged(element, markState);
+    }
+  }
+
+  public void clear() {
+    myTableModel.clear();
+    myElementToPropertiesMap.clear();
+  }
+
+  public int getElementCount() {
+    return myTableModel.getRowCount();
+  }
+
+  public T getElementAt(int row) {
+    return myTableModel.getElementAt(row);
+  }
+
+  public void disableElement(T element) {
+    myDisabledMap.put(element, Boolean.TRUE);
+  }
+
+  private final class MyTableModel extends AbstractTableModel {
+    private final List<T> myElements = new ArrayList<T>();
+    private final Map<T, S> myMarkedMap = new HashMap<T, S>();
+    public final int CHECK_MARK_COLUM_INDEX;
+    public final int ELEMENT_COLUMN_INDEX;
+    private final boolean myElementsCanBeMarked;
+
+    public MyTableModel(final boolean elementsCanBeMarked) {
+      myElementsCanBeMarked = elementsCanBeMarked;
+      if (elementsCanBeMarked) {
+        CHECK_MARK_COLUM_INDEX = 0;
+        ELEMENT_COLUMN_INDEX = 1;
+      }
+      else {
+        CHECK_MARK_COLUM_INDEX = -1;
+        ELEMENT_COLUMN_INDEX = 0;
+      }
+    }
+
+    public void sort(Comparator<T> comparator) {
+      Collections.sort(myElements, comparator);
+      fireTableDataChanged();
+    }
+
+    public T getElementAt(int index) {
+      return myElements.get(index);
+    }
+
+    public S getElementMarkState(int index) {
+      final T element = myElements.get(index);
+      return myMarkedMap.get(element);
+    }
+
+    private void addElement(T element, S markState) {
+      myElements.add(element);
+      myMarkedMap.put(element, notNullMarkState(element, markState));
+      int row = myElements.size() - 1;
+      fireTableRowsInserted(row, row);
+    }
+
+    private void addElements(@Nullable List<T> elements, S markState) {
+      if (elements == null || elements.isEmpty()) {
+        return;
+      }
+      for (final T element : elements) {
+        myElements.add(element);
+        myMarkedMap.put(element, notNullMarkState(element, markState));
+      }
+      fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
+    }
+
+    public void removeElement(T element) {
+      final boolean reallyRemoved = myElements.remove(element);
+      if (reallyRemoved) {
+        myMarkedMap.remove(element);
+        fireTableDataChanged();
+      }
+    }
+
+    public void changeElementRow(T element, int row) {
+      final boolean reallyRemoved = myElements.remove(element);
+      if (reallyRemoved) {
+        myElements.add(row, element);
+        fireTableDataChanged();
+      }
+    }
+
+    public int getElementRow(T element) {
+      return myElements.indexOf(element);
+    }
+
+    public void removeAllElements() {
+      myElements.clear();
+      fireTableDataChanged();
+    }
+
+    public void removeRows(int[] rows) {
+      final List<T> toRemove = new ArrayList<T>();
+      for (int row : rows) {
+        final T element = myElements.get(row);
+        toRemove.add(element);
+        myMarkedMap.remove(element);
+      }
+      myElements.removeAll(toRemove);
+      fireTableDataChanged();
+    }
+
+    @Override
+    public int getRowCount() {
+      return myElements.size();
+    }
+
+    @Override
+    public int getColumnCount() {
+      return myElementsCanBeMarked? 2 : 1;
+    }
+
+    @Override
+    @Nullable
+    public Object getValueAt(int rowIndex, int columnIndex) {
+      T element = myElements.get(rowIndex);
+      if (columnIndex == ELEMENT_COLUMN_INDEX) {
+        return element;
+      }
+      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+        return myMarkedMap.get(element);
+      }
+      return null;
+    }
+
+    @Override
+    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+        S nextState = myMarkStateDescriptor.getMarkState(aValue);
+        if (nextState == null) {
+          T element = myTableModel.getElementAt(rowIndex);
+          S currentState = myTableModel.getElementMarkState(rowIndex);
+          nextState = myMarkStateDescriptor.getNextState(element, currentState);
+        }
+        setMarkState(rowIndex, nextState);
+      }
+    }
+
+    private void setMarkState(int rowIndex, final S markState) {
+      final T element = myElements.get(rowIndex);
+      final S newValue = notNullMarkState(element, markState);
+      final S prevValue = myMarkedMap.put(element, newValue);
+      fireTableRowsUpdated(rowIndex, rowIndex);
+      if (!newValue.equals(prevValue)) {
+        notifyElementMarked(element, newValue);
+      }
+    }
+
+    private void setMarkState(int[] rows, final S markState) {
+      if (rows == null || rows.length == 0) {
+        return;
+      }
+      int firstRow = Integer.MAX_VALUE;
+      int lastRow = Integer.MIN_VALUE;
+      for (final int row : rows) {
+        final T element = myElements.get(row);
+        final S newValue = notNullMarkState(element, markState);
+        final S prevValue = myMarkedMap.put(element, newValue);
+        if (!newValue.equals(prevValue)) {
+          notifyElementMarked(element, newValue);
+        }
+        firstRow = Math.min(firstRow, row);
+        lastRow = Math.max(lastRow, row);
+      }
+      fireTableRowsUpdated(firstRow, lastRow);
+    }
+
+    @NotNull
+    private S notNullMarkState(T element, S markState) {
+      return markState != null ? markState : myMarkStateDescriptor.getDefaultState(element);
+    }
+
+    @Override
+    public Class getColumnClass(int columnIndex) {
+      if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+        return Boolean.class;
+      }
+      return super.getColumnClass(columnIndex);
+    }
+
+    @Override
+    public boolean isCellEditable(int rowIndex, int columnIndex) {
+      if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
+        return false;
+      }
+      final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
+      return myDisabledMap.get(o) == null;
+    }
+
+    public void clear() {
+      myElements.clear();
+      myMarkedMap.clear();
+      fireTableDataChanged();
+    }
+  }
+
+  protected String getItemText(@NotNull T value) {
+    return value.toString();
+  }
+
+  @Nullable
+  protected Icon getItemIcon(@NotNull T value) {
+    return null;
+  }
+
+  private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
+    @Override
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+      final Color color = UIUtil.getTableFocusCellBackground();
+      Component component;
+      T t = (T)value;
+      try {
+        UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
+        component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+        setText(t != null ? getItemText(t) : "");
+        if (component instanceof JLabel) {
+          ((JLabel)component).setBorder(noFocusBorder);
+        }
+      }
+      finally {
+        UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
+      }
+      final MyTableModel model = (MyTableModel)table.getModel();
+      component.setEnabled(MultiStateElementsChooser.this.isEnabled() &&
+                           (!myColorUnmarkedElements || myMarkStateDescriptor.isMarked(model.getElementMarkState(row))));
+      final ElementProperties properties = myElementToPropertiesMap.get(t);
+      if (component instanceof JLabel) {
+        final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
+        JLabel label = (JLabel)component;
+        label.setIcon(icon);
+        label.setDisabledIcon(icon);
+      }
+      component.setForeground(properties != null && properties.getColor() != null ?
+                              properties.getColor() :
+                              isSelected ? table.getSelectionForeground() : table.getForeground());
+      return component;
+    }
+  }
+
+  private class CheckMarkColumnCellRenderer implements TableCellRenderer {
+    private final TableCellRenderer myDelegate;
+
+    public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
+      myDelegate = delegate;
+    }
+
+    @Override
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+      Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+      component.setEnabled(isEnabled());
+      if (component instanceof JComponent) {
+        ((JComponent)component).setBorder(null);
+      }
+      return component;
+    }
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
index 8974915..2873ed3 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -21,12 +21,11 @@
 import com.intellij.openapi.components.PersistentStateComponent;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Function;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.containers.hash.HashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.List;
 import java.util.Set;
@@ -60,19 +59,11 @@
   @Nullable
   private static Object getPropertyValue(Object componentInstance, String propertyName) {
     final Class<? extends Object> componentInstanceClass = componentInstance.getClass();
-    Object propertyValue = null;
-    try {
-      Field field = componentInstanceClass.getDeclaredField(propertyName);
-      propertyValue = field.get(componentInstance);
-    }
-    catch (NoSuchFieldException ignored) {
-    }
-    catch (IllegalAccessException ignored) {
-    }
+    Object propertyValue = ReflectionUtil.getField(componentInstanceClass, componentInstance, null, propertyName);
     if (propertyValue == null) {
-      Method method = getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
+      Method method = ReflectionUtil.getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
       if (method == null) {
-        method = getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
+        method = ReflectionUtil.getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
       }
       if (method != null) {
         try {
@@ -85,16 +76,6 @@
     return propertyValue;
   }
 
-  @Nullable
-  private static Method getMethod(@NotNull Class componentInstanceClass, @NotNull String name) {
-    try {
-      return componentInstanceClass.getMethod(name);
-    }
-    catch (NoSuchMethodException ignored) {
-    }
-    return null;
-  }
-
   private static String getUsageDescriptorKey(@NotNull String providerName, @NotNull String name, @NotNull String value) {
     final String shortName = StringUtil.getShortName(providerName);
     return shortName + "#" + name + "(" + value + ")";
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
index 73af2c3..2d6a768 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
 import com.intellij.openapi.ui.ComboBoxTableRenderer;
 import com.intellij.openapi.ui.StripeTable;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.ui.IdeBorderFactory;
 import com.intellij.ui.TableSpeedSearch;
 import com.intellij.ui.components.JBScrollPane;
 import com.intellij.util.ui.UIUtil;
@@ -30,6 +31,7 @@
 import javax.swing.*;
 import javax.swing.border.LineBorder;
 import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
 import javax.swing.table.TableColumn;
 import java.awt.*;
 import java.awt.event.ActionEvent;
@@ -126,6 +128,22 @@
 
       final TableColumn idColumn = getColumnModel().getColumn(ID_COLUMN);
       idColumn.setPreferredWidth(200);
+      idColumn.setCellRenderer(new DefaultTableCellRenderer() {
+        @NotNull
+        @Override
+        public Component getTableCellRendererComponent(@NotNull JTable table,
+                                                       Object value,
+                                                       boolean isSelected,
+                                                       boolean hasFocus,
+                                                       int row,
+                                                       int column) {
+          Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+          if (component instanceof JComponent) {
+            ((JComponent)component).setBorder(IdeBorderFactory.createEmptyBorder(0, 4, 0, 4));
+          }
+          return component;
+        }
+      });
 
       final TableColumn displayTypeColumn = getColumnModel().getColumn(DISPLAY_TYPE_COLUMN);
       displayTypeColumn.setMaxWidth(300);
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index 36bd876..51809ad 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.AppUIUtil;
 import com.intellij.util.PlatformUtils;
-import com.intellij.util.SystemProperties;
 import com.intellij.util.ThreeState;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -402,15 +401,12 @@
       dir = dir.substring(1, dir.length() - 1);
     }
     if (replaceUserHome) {
-      if (dir.startsWith("~\\") || dir.startsWith("~//") || StringUtil.startsWithConcatenation(dir, "~", File.separator)) {
-        dir = SystemProperties.getUserHome() + dir.substring(1);
-      }
+      dir = FileUtil.expandUserHome(dir);
     }
     return dir;
   }
 
-  public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, 
-                                                   @NotNull final ConfigImportSettings settings) {
+  public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, @NotNull final ConfigImportSettings settings) {
     if (new File(installationHome, OPTIONS_XML).exists()) return true;
     if (new File(installationHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) return true;
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
index b0d4d3f..005c006 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,8 +15,7 @@
  */
 package com.intellij.openapi.application;
 
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.util.SystemProperties;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.ThreeState;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -74,10 +73,7 @@
   }
 
   protected String getAutoImportLabel(File guessedOldConfig) {
-    String path = guessedOldConfig.getAbsolutePath();
-    if (SystemInfo.isUnix) {
-      path = path.replace(SystemProperties.getUserHome(), "~");
-    }
+    String path = FileUtil.getLocationRelativeToUserHome(guessedOldConfig.getAbsolutePath());
     return ApplicationBundle.message("radio.import.auto", path);
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
index bf7fe9c..9f43164 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
@@ -20,7 +20,6 @@
 import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.command.*;
@@ -96,11 +95,11 @@
   }
 
   public static int getGlobalUndoLimit() {
-    return Registry.intValue("undo.globalUndoLimit", 10);
+    return Registry.intValue("undo.globalUndoLimit");
   }
 
   public static int getDocumentUndoLimit() {
-    return Registry.intValue("undo.documentUndoLimit", 100);
+    return Registry.intValue("undo.documentUndoLimit");
   }
 
   public UndoManagerImpl(Application application, CommandProcessor commandProcessor) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
index a916d9e..372b14e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
@@ -73,8 +73,9 @@
       SelectionModel selectionModel = myEditor.getSelectionModel();
       if (selectionModel.hasSelection()) {
         TextRange range = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+        boolean forceReadOnly = myEditor.isViewer();
         myContents[1] = new FragmentContent(DiffContent.fromDocument(getProject(), getDocument()),
-                                            range, getProject(), getDocumentFile(getDocument()));
+                                            range, getProject(), getDocumentFile(getDocument()), forceReadOnly);
       }
       else {
         myContents [1] = DiffContent.fromDocument(getProject(), getDocument());
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
index 538058d..ec7a316 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
@@ -23,6 +23,8 @@
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.DialogWrapperDialog;
 import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 
@@ -56,25 +58,26 @@
     myShowSourcePolicy = showSourcePolicy;
   }
 
-  public void showSource(OpenFileDescriptor descriptor) {
+  public void showSource(@Nullable OpenFileDescriptor descriptor) {
+    if (descriptor == null || myDiffPanel.getProject() == null) return;
     myShowSourcePolicy.showSource(descriptor, myDiffPanel);
   }
 
   public interface ShowSourcePolicy {
-    void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel);
+    void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel);
 
     ShowSourcePolicy DONT_SHOW = new ShowSourcePolicy() {
-      public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {}
+      public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {}
     };
 
     ShowSourcePolicy OPEN_EDITOR = new ShowSourcePolicy() {
-      public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+      public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
         FileEditorManager.getInstance(diffPanel.getProject()).openTextEditor(descriptor, true);
       }
     };
 
     ShowSourcePolicy OPEN_EDITOR_AND_CLOSE_DIFF = new ShowSourcePolicy() {
-      public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+      public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
         OPEN_EDITOR.showSource(descriptor, diffPanel);
         if (diffPanel.getOwnerWindow() == null) return;
         Disposer.dispose(diffPanel);
@@ -97,7 +100,7 @@
     };
 
     ShowSourcePolicy DEFAULT = new ShowSourcePolicy() {
-      public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+      public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
         Window window = diffPanel.getOwnerWindow();
         if (window == null) return;
         else if (window instanceof Frame) OPEN_EDITOR.showSource(descriptor, diffPanel);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
index 5f16914..8ea3242 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
@@ -73,7 +73,6 @@
 import com.intellij.util.containers.CacheOneStepIterator;
 import com.intellij.util.diff.FilesTooBigForDiffException;
 import com.intellij.util.ui.PlatformColors;
-import com.intellij.util.ui.UIUtil;
 import gnu.trove.TIntFunction;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -160,8 +159,8 @@
     myOwnerWindow = owner;
     myIsSyncScroll = true;
     final boolean v = !horizontal;
-    myLeftSide =  new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, v ? 0 : 1, v ? 0 : 1));
-    myRightSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), v ? 0 : 1, v ? 0 : 1, 1, 0));
+    myLeftSide =  new DiffSideView(this, new CustomLineBorder(1, 0, v ? 0 : 1, v ? 0 : 1));
+    myRightSide = new DiffSideView(this, new CustomLineBorder(v ? 0 : 1, v ? 0 : 1, 1, 0));
     myLeftSide.becomeMaster();
     myDiffUpdater = new Rediffers(this);
 
@@ -298,13 +297,11 @@
     myData.setContents(content1, content2);
     Project project = myData.getProject();
     FileType[] types = DiffUtil.chooseContentTypes(new DiffContent[]{content1, content2});
-    VirtualFile baseFile = content1.getFile();
-    if (baseFile == null && myDiffRequest != null) {
-      String path = myDiffRequest.getWindowTitle();
-      if (path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
-    }
-    myLeftSide.setHighlighterFactory(createHighlighter(types[0], baseFile, project));
-    myRightSide.setHighlighterFactory(createHighlighter(types[1], baseFile, project));
+    VirtualFile beforeFile = content1.getFile();
+    VirtualFile afterFile = content2.getFile();
+    String path = myDiffRequest == null ? null : myDiffRequest.getWindowTitle();
+    myLeftSide.setHighlighterFactory(createHighlighter(types[0], beforeFile, afterFile, path, project));
+    myRightSide.setHighlighterFactory(createHighlighter(types[1], afterFile, beforeFile, path, project));
     setSplitterProportion(content1, content2);
     rediff();
     if (myIsRequestFocus) {
@@ -344,8 +341,16 @@
     }
   }
   // todo pay attention here
-  private static DiffHighlighterFactory createHighlighter(FileType contentType, VirtualFile file, Project project) {
-    return new DiffHighlighterFactoryImpl(contentType, file, project);
+  private static DiffHighlighterFactory createHighlighter(FileType contentType,
+                                                          VirtualFile file,
+                                                          VirtualFile otherFile,
+                                                          String path,
+                                                          Project project) {
+    VirtualFile baseFile = file;
+    if (baseFile == null) baseFile = otherFile;
+    if (baseFile == null && path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
+
+    return new DiffHighlighterFactoryImpl(contentType, baseFile, project);
   }
 
   void rediff() {
@@ -607,7 +612,7 @@
     return myData.getProject();
   }
 
-  public void showSource(OpenFileDescriptor descriptor) {
+  public void showSource(@Nullable OpenFileDescriptor descriptor) {
     myOptions.showSource(descriptor);
   }
 
@@ -1004,10 +1009,7 @@
 
     @Override
     public void navigate(boolean requestFocus) {
-      final OpenFileDescriptor descriptor = mySide.getCurrentOpenFileDescriptor();
-      if (descriptor != null) {
-        showSource(descriptor);
-      }
+      showSource(mySide.getCurrentOpenFileDescriptor());
     }
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
index 5f4507d..4b6a289 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
 import com.intellij.openapi.diff.impl.splitter.DiffDividerPaint;
 import com.intellij.openapi.editor.event.VisibleAreaEvent;
 import com.intellij.openapi.editor.event.VisibleAreaListener;
+import com.intellij.openapi.ui.Divider;
 import com.intellij.openapi.ui.Splitter;
 
 import javax.swing.*;
@@ -43,8 +44,8 @@
     setHonorComponentsMinimumSize(false);
   }
 
-  protected Splitter.Divider createDivider() {
-    return new Divider(){
+  protected Divider createDivider() {
+    return new DividerImpl(){
       public void paint(Graphics g) {
         super.paint(g);
         myPaint.paint(g, this);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
index 10362cc..cbad541 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
@@ -27,9 +27,7 @@
 import com.intellij.openapi.diff.actions.NextDiffAction;
 import com.intellij.openapi.diff.actions.PreviousDiffAction;
 import com.intellij.openapi.diff.actions.ToggleAutoScrollAction;
-import com.intellij.openapi.diff.impl.DiffUtil;
-import com.intellij.openapi.diff.impl.EditingSides;
-import com.intellij.openapi.diff.impl.GenericDataProvider;
+import com.intellij.openapi.diff.impl.*;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter;
 import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList;
@@ -49,16 +47,20 @@
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.ex.EditorMarkupModel;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
 import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.LabeledComponent;
+import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.EditorNotificationPanel;
-import com.intellij.util.diff.FilesTooBigForDiffException;
+import com.intellij.util.containers.Convertor;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -141,9 +143,6 @@
   private DiffRequest.ToolbarAddons createToolbar() {
     return new DiffRequest.ToolbarAddons() {
       public void customize(DiffToolbar toolbar) {
-        ActionManager actionManager = ActionManager.getInstance();
-        toolbar.addAction(actionManager.getAction(IdeActions.ACTION_COPY));
-        toolbar.addAction(actionManager.getAction(IdeActions.ACTION_FIND));
         toolbar.addAction(PreviousDiffAction.find());
         toolbar.addAction(NextDiffAction.find());
         toolbar.addSeparator();
@@ -235,6 +234,8 @@
     Editor base = getEditor(1);
     Editor right = getEditor(2);
 
+    setupHighlighterSettings(left, base, right);
+
     myMergeList.setMarkups(left, base, right);
     EditingSides[] sides = {getFirstEditingSide(), getSecondEditingSide()};
     myScrollSupport.install(sides);
@@ -271,6 +272,37 @@
     return myScrollSupport.isEnabled();
   }
 
+  private void setupHighlighterSettings(Editor left, Editor base, Editor right) {
+    Editor[] editors = new Editor[]{left, base, right};
+    DiffContent[] contents = myData.getContents();
+    FileType[] types = DiffUtil.chooseContentTypes(contents);
+
+    VirtualFile fallbackFile = contents[1].getFile();
+    FileType fallbackType = contents[1].getContentType();
+
+    for (int i = 0; i < 3; i++) {
+      Editor editor = editors[i];
+      DiffContent content = contents[i];
+
+      EditorHighlighter highlighter =
+        createHighlighter(types[i], content.getFile(), fallbackFile, fallbackType, myData.getProject()).createHighlighter();
+      if (highlighter != null) {
+        ((EditorEx)editor).setHighlighter(highlighter);
+      }
+    }
+  }
+
+  private static DiffHighlighterFactory createHighlighter(FileType contentType,
+                                                          VirtualFile file,
+                                                          VirtualFile otherFile,
+                                                          FileType otherType,
+                                                          Project project) {
+    if (file == null) file = otherFile;
+    if (contentType == null) contentType = otherType;
+
+    return new DiffHighlighterFactoryImpl(contentType, file, project);
+  }
+
   public void setHighlighterSettings(@Nullable EditorColorsScheme settings) {
     for (EditorPlace place : getEditorPlaces()) {
       setHighlighterSettings(settings, place);
@@ -337,7 +369,20 @@
       data.customizeToolbar(myPanel.resetToolbar());
       myPanel.registerToolbarActions();
       if ( data instanceof MergeRequestImpl && myBuilder != null){
-        ((MergeRequestImpl)data).setActions(myBuilder, this);
+        Convertor<DialogWrapper, Boolean> preOkHook = new Convertor<DialogWrapper, Boolean>() {
+          @Override
+          public Boolean convert(DialogWrapper dialog) {
+            ChangeCounter counter = ChangeCounter.getOrCreate(myMergeList);
+            int changes = counter.getChangeCounter();
+            int conflicts = counter.getConflictCounter();
+            if (changes == 0 && conflicts == 0) return true;
+            return Messages.showYesNoDialog(dialog.getRootPane(),
+                                            DiffBundle.message("merge.dialog.apply.partially.resolved.changes.confirmation.message", changes, conflicts),
+                                            DiffBundle.message("apply.partially.resolved.merge.dialog.title"),
+                                            Messages.getQuestionIcon()) == Messages.YES;
+          }
+        };
+        ((MergeRequestImpl)data).setActions(myBuilder, this, preOkHook);
       }
     }
     finally {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
index 3b13543..962a071 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
@@ -20,6 +20,7 @@
 import com.intellij.openapi.diff.MergeRequest;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
@@ -27,11 +28,11 @@
 
 public class DiffRequestFactoryImpl extends DiffRequestFactory {
 
-  public MergeRequest createMergeRequest(String leftText,
-                                         String rightText,
-                                         String originalContent,
+  public MergeRequest createMergeRequest(@NotNull String leftText,
+                                         @NotNull String rightText,
+                                         @NotNull String originalContent,
                                          @NotNull VirtualFile file,
-                                         Project project,
+                                         @Nullable Project project,
                                          @Nullable final ActionButtonPresentation okButtonPresentation,
                                          @Nullable final ActionButtonPresentation cancelButtonPresentation) {
     final Document document = FileDocumentManager.getInstance().getDocument(file);
@@ -41,16 +42,26 @@
                                   cancelButtonPresentation);
     }
     else {
-      return create3WayDiffRequest(leftText, rightText, originalContent, project, okButtonPresentation, cancelButtonPresentation);
+      return create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, okButtonPresentation, cancelButtonPresentation);
     }
   }
 
-  public MergeRequest create3WayDiffRequest(final String leftText,
-                                            final String rightText,
-                                            final String originalContent,
-                                            final Project project,
+  public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+                                            @NotNull String rightText,
+                                            @NotNull String originalContent,
+                                            @Nullable FileType type,
+                                            @Nullable Project project,
                                             @Nullable final ActionButtonPresentation okButtonPresentation,
                                             @Nullable final ActionButtonPresentation cancelButtonPresentation) {
-    return new MergeRequestImpl(leftText, originalContent, rightText, project, okButtonPresentation, cancelButtonPresentation);
+    return new MergeRequestImpl(leftText, originalContent, rightText, type, project, okButtonPresentation, cancelButtonPresentation);
+  }
+
+  public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+                                            @NotNull String rightText,
+                                            @NotNull String originalContent,
+                                            @Nullable Project project,
+                                            @Nullable final ActionButtonPresentation okButtonPresentation,
+                                            @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+    return create3WayDiffRequest(leftText, rightText, originalContent, null, project, okButtonPresentation, cancelButtonPresentation);
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
index 3b1385e..938c1ee 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
@@ -28,6 +28,7 @@
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.Convertor;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -46,39 +47,51 @@
   @Nullable private final ActionButtonPresentation myOkButtonPresentation;
   @Nullable private final ActionButtonPresentation myCancelButtonPresentation;
 
-  public MergeRequestImpl(String left,
-                          MergeVersion base,
-                          String right,
-                          Project project,
+  public MergeRequestImpl(@NotNull String left,
+                          @NotNull MergeVersion base,
+                          @NotNull String right,
+                          @Nullable Project project,
                           @Nullable final ActionButtonPresentation okButtonPresentation,
                           @Nullable final ActionButtonPresentation cancelButtonPresentation) {
     this(new SimpleContent(left), new MergeContent(base, project), new SimpleContent(right), project, okButtonPresentation,
          cancelButtonPresentation);
   }
 
-  public MergeRequestImpl(DiffContent left,
-                          MergeVersion base,
-                          DiffContent right,
-                          Project project,
+  public MergeRequestImpl(@NotNull DiffContent left,
+                          @NotNull MergeVersion base,
+                          @NotNull DiffContent right,
+                          @Nullable Project project,
                           @Nullable final ActionButtonPresentation okButtonPresentation,
                           @Nullable final ActionButtonPresentation cancelButtonPresentation) {
     this(left, new MergeContent(base, project), right, project, okButtonPresentation, cancelButtonPresentation);
   }
 
-  public MergeRequestImpl(String left,
-                          String base,
-                          String right,
-                          Project project,
+  public MergeRequestImpl(@NotNull String left,
+                          @NotNull String base,
+                          @NotNull String right,
+                          @Nullable Project project,
                           @Nullable final ActionButtonPresentation okButtonPresentation,
                           @Nullable final ActionButtonPresentation cancelButtonPresentation) {
-    this(new SimpleContent(left), new SimpleContent(base), new SimpleContent(right), project, okButtonPresentation,
-         cancelButtonPresentation);
+    this(left, base, right, null, project, okButtonPresentation, cancelButtonPresentation);
   }
 
-  private MergeRequestImpl(DiffContent left,
-                           DiffContent base,
-                           DiffContent right,
-                           Project project,
+  public MergeRequestImpl(@NotNull String left,
+                          @NotNull String base,
+                          @NotNull String right,
+                          @Nullable FileType type,
+                          @Nullable Project project,
+                          @Nullable final ActionButtonPresentation okButtonPresentation,
+                          @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+    this(new SimpleContent(left, type),
+         new SimpleContent(base, type),
+         new SimpleContent(right, type),
+         project, okButtonPresentation, cancelButtonPresentation);
+  }
+
+  private MergeRequestImpl(@NotNull DiffContent left,
+                           @NotNull DiffContent base,
+                           @NotNull DiffContent right,
+                           @Nullable Project project,
                            @Nullable final ActionButtonPresentation okButtonPresentation,
                            @Nullable final ActionButtonPresentation cancelButtonPresentation) {
     super(project);
@@ -176,6 +189,10 @@
   }
 
   public void setActions(final DialogBuilder builder, MergePanel2 mergePanel) {
+    setActions(builder, mergePanel, null);
+  }
+
+  public void setActions(final DialogBuilder builder, MergePanel2 mergePanel, final Convertor<DialogWrapper, Boolean> preOkHook) {
     builder.removeAllActions(); // otherwise dialog will get default actions (OK, Cancel)
 
     if (myOkButtonPresentation != null) {
@@ -187,6 +204,7 @@
       builder.setOkOperation(new Runnable() {
         @Override
         public void run() {
+          if (preOkHook != null && !preOkHook.convert(builder.getDialogWrapper())) return;
           myOkButtonPresentation.run(builder.getDialogWrapper());
         }
       });
@@ -221,11 +239,11 @@
   }
 
   public static class MergeContent extends DiffContent {
-    private final MergeVersion myTarget;
+    @NotNull private final MergeVersion myTarget;
     private final Document myWorkingDocument;
     private final Project myProject;
 
-    public MergeContent(MergeVersion target, Project project) {
+    public MergeContent(@NotNull MergeVersion target, Project project) {
       myTarget = target;
       myProject = project;
       myWorkingDocument = myTarget.createWorkingDocument(project);
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java b/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
similarity index 100%
rename from platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java
rename to platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java b/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
similarity index 100%
rename from platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
rename to platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
index f8b3cf7..c42cd65 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
@@ -15,31 +15,10 @@
  */
 package com.intellij.openapi.editor.actions;
 
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
 
 public class CloneCaretAbove extends EditorAction {
   public CloneCaretAbove() {
-    super(new Handler());
-  }
-
-  private static class Handler extends EditorActionHandler {
-    public Handler() {
-      super(true);
-    }
-
-    @Override
-    public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
-      caret.clone(true);
-    }
-
-    @Override
-    public boolean isEnabled(Editor editor, DataContext dataContext) {
-      return editor.getCaretModel().supportsMultipleCarets();
-    }
+    super(new CloneCaretActionHandler(true));
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
new file mode 100644
index 0000000..5c5528a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorLastActionTracker;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.util.Key;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+public class CloneCaretActionHandler extends EditorActionHandler {
+  private static final Key<Integer> LEVEL = Key.create("CloneCaretActionHandler.level");
+
+  private static final Set<String> OUR_ACTIONS = new HashSet<String>(Arrays.asList(
+    IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE,
+    IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW,
+    IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION,
+    IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION
+  ));
+
+  private final boolean myCloneAbove;
+
+  public CloneCaretActionHandler(boolean above) {
+    myCloneAbove = above;
+  }
+
+  @Override
+  public boolean isEnabled(Editor editor, DataContext dataContext) {
+    return editor.getCaretModel().supportsMultipleCarets();
+  }
+
+  @Override
+  protected void doExecute(Editor editor, @Nullable Caret targetCaret, DataContext dataContext) {
+    if (targetCaret != null) {
+      targetCaret.clone(myCloneAbove);
+      return;
+    }
+    int currentLevel = 0;
+    List<Caret> currentCarets = new ArrayList<Caret>();
+    for (Caret caret : editor.getCaretModel().getAllCarets()) {
+      int level = getLevel(caret);
+      if (Math.abs(level) > Math.abs(currentLevel)) {
+        currentLevel = level;
+        currentCarets.clear();
+      }
+      if (Math.abs(level) == Math.abs(currentLevel)) {
+        currentCarets.add(caret);
+      }
+    }
+    boolean removeCarets = currentLevel > 0 && myCloneAbove || currentLevel < 0 && !myCloneAbove;
+    Integer newLevel = myCloneAbove ? currentLevel - 1 : currentLevel + 1;
+    for (Caret caret : currentCarets) {
+      if (removeCarets) {
+        editor.getCaretModel().removeCaret(caret);
+      }
+      else {
+        Caret clone = caret;
+        do {
+          Caret original = clone;
+          clone = clone.clone(myCloneAbove);
+          if (original != caret) {
+            editor.getCaretModel().removeCaret(original);
+          }
+        } while (clone != null && caret.hasSelection() && !clone.hasSelection());
+        if (clone != null) {
+          clone.putUserData(LEVEL, newLevel);
+        }
+      }
+    }
+    if (removeCarets) {
+      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+    }
+  }
+
+  private static int getLevel(Caret caret) {
+    if (isRepeatedActionInvocation()) {
+      Integer value = caret.getUserData(LEVEL);
+      return value == null ? 0 : value;
+    }
+    else {
+      caret.putUserData(LEVEL, null);
+      return 0;
+    }
+  }
+
+  private static boolean isRepeatedActionInvocation() {
+    String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
+    return OUR_ACTIONS.contains(lastActionId);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
index 17d1770..9740877 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
@@ -15,35 +15,10 @@
  */
 package com.intellij.openapi.editor.actions;
 
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
 
 public class CloneCaretBelow extends EditorAction {
   public CloneCaretBelow() {
-    super(new Handler());
-  }
-
-  private static class Handler extends EditorActionHandler {
-    public Handler() {
-      super(true);
-    }
-
-    @Override
-    public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
-      CaretModel caretModel = editor.getCaretModel();
-      if (caretModel.supportsMultipleCarets()) {
-        caret.clone(false);
-      }
-    }
-
-    @Override
-    public boolean isEnabled(Editor editor, DataContext dataContext) {
-      return editor.getCaretModel().supportsMultipleCarets();
-    }
+    super(new CloneCaretActionHandler(false));
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
index cfd039a..c769f92 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
@@ -62,7 +62,13 @@
   private int myVisualLineEnd;
   private RangeMarker savedBeforeBulkCaretMarker;
   private boolean mySkipChangeRequests;
+  /**
+   * Initial horizontal caret position during vertical navigation.
+   * Similar to {@link #myDesiredX}, but represents logical caret position (<code>getLogicalPosition().column</code>) rather than visual.
+   */
   private int myLastColumnNumber = 0;
+  private int myDesiredSelectionStartColumn = -1;
+  private int myDesiredSelectionEndColumn = -1;
   /**
    * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
    * it's possible that the following situation occurs:
@@ -82,11 +88,10 @@
    */
   private boolean myReportCaretMoves;
   /**
-   * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
-   * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
-   * its initial visual position when possible.
+   * This field holds initial horizontal caret position during vertical navigation. It's used to determine target position when
+   * moving to the new line. It is stored in pixels, not in columns, to account for non-monospaced fonts as well.
    * <p/>
-   * This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
+   * Negative value means no coordinate should be preserved.
    */
   private int myDesiredX = -1;
 
@@ -255,10 +260,11 @@
         EditorSettings editorSettings = myEditor.getSettings();
         VisualPosition visualCaret = getVisualPosition();
 
+        int lastColumnNumber = myLastColumnNumber;
         int desiredX = myDesiredX;
         if (columnShift == 0) {
           if (myDesiredX < 0) {
-            desiredX = myEditor.visualPositionToXY(visualCaret).x;
+            desiredX = getCurrentX();
           }
         }
         else {
@@ -267,15 +273,12 @@
 
         int newLineNumber = visualCaret.line + lineShift;
         int newColumnNumber = visualCaret.column + columnShift;
-        if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
+        if (desiredX >= 0) {
           newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
         }
 
         Document document = myEditor.getDocument();
-        if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
-          newColumnNumber = supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber();
-        }
-        else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
+        if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
           int lastLine = document.getLineCount() - 1;
           if (lastLine < 0) lastLine = 0;
           if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
@@ -303,18 +306,21 @@
           // We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
           newColumnNumber = 0;
           desiredX = -1;
+          lastColumnNumber = -1;
         }
 
         VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
-        int lastColumnNumber = newColumnNumber;
         if (!myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
           LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
           int offset = myEditor.logicalPositionToOffset(log);
           if (offset >= document.getTextLength()) {
             int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
             // We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
-            newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
-            desiredX = -1;
+            if (lastOffsetColumn > newColumnNumber) {
+              newColumnNumber = lastOffsetColumn;
+              desiredX = -1;
+              lastColumnNumber = -1;
+            }
           }
           if (!editorSettings.isCaretInsideTabs()) {
             CharSequence text = document.getCharsSequence();
@@ -353,7 +359,7 @@
         }
         else {
           moveToVisualPosition(pos);
-          if (!editorSettings.isVirtualSpace() && columnShift == 0) {
+          if (!editorSettings.isVirtualSpace() && columnShift == 0 && lastColumnNumber >=0) {
             setLastColumnNumber(lastColumnNumber);
           }
         }
@@ -550,6 +556,7 @@
     }
 
     setLastColumnNumber(myLogicalCaret.column);
+    myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
     myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
 
     updateOffsetsFromLogicalPosition();
@@ -705,7 +712,8 @@
 
     myEditor.getFoldingModel().flushCaretPosition();
 
-    setLastColumnNumber(column);
+    setLastColumnNumber(myLogicalCaret.column);
+    myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
     myEditor.updateCaretCursor();
     requestRepaint(oldInfo);
 
@@ -962,6 +970,8 @@
     clone.myLastColumnNumber = this.myLastColumnNumber;
     clone.myReportCaretMoves = this.myReportCaretMoves;
     clone.myDesiredX = this.myDesiredX;
+    clone.myDesiredSelectionStartColumn = -1;
+    clone.myDesiredSelectionEndColumn = -1;
     return clone;
   }
 
@@ -971,10 +981,10 @@
     assertIsDispatchThread();
     int lineShift = above ? -1 : 1;
     final CaretImpl clone = cloneWithoutSelection();
-    final int newSelectionStartOffset, newSelectionEndOffset;
+    final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn;
     final VisualPosition newSelectionStartPosition, newSelectionEndPosition;
     final boolean hasNewSelection;
-    if (hasSelection()) {
+    if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) {
       VisualPosition startPosition = getSelectionStartPosition();
       VisualPosition endPosition = getSelectionEndPosition();
       VisualPosition leadPosition = getLeadSelectionPosition();
@@ -982,8 +992,10 @@
       boolean leadIsEnd = leadPosition.equals(endPosition);
       LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition);
       LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition);
-      LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column));
-      LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column));
+      newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn;
+      newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn;
+      LogicalPosition newSelectionStart = truncate(selectionStart.line + lineShift, newSelectionStartColumn);
+      LogicalPosition newSelectionEnd = truncate(selectionEnd.line + lineShift, newSelectionEndColumn);
       newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart);
       newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd);
       newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart);
@@ -996,6 +1008,8 @@
       newSelectionStartPosition = null;
       newSelectionEndPosition = null;
       hasNewSelection = false;
+      newSelectionStartColumn = -1;
+      newSelectionEndColumn = -1;
     }
     LogicalPosition oldPosition = getLogicalPosition();
     int newLine = oldPosition.line + lineShift;
@@ -1003,7 +1017,12 @@
       Disposer.dispose(clone);
       return null;
     }
-    clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
+    clone.moveToLogicalPosition(new LogicalPosition(newLine, myLastColumnNumber), false, null, false);
+    clone.myLastColumnNumber = myLastColumnNumber;
+    clone.myDesiredX = myDesiredX >= 0 ? myDesiredX : getCurrentX();
+    clone.myDesiredSelectionStartColumn = newSelectionStartColumn;
+    clone.myDesiredSelectionEndColumn = newSelectionEndColumn;
+
     if (myEditor.getCaretModel().addCaret(clone)) {
       if (hasNewSelection) {
         myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
@@ -1025,15 +1044,15 @@
     }
   }
 
-  private LogicalPosition truncate(LogicalPosition position) {
-    if (position.line < 0) {
+  private LogicalPosition truncate(int line, int column) {
+    if (line < 0) {
       return new LogicalPosition(0, 0);
     }
-    else if (position.line >= myEditor.getDocument().getLineCount()) {
+    else if (line >= myEditor.getDocument().getLineCount()) {
       return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength());
     }
     else {
-      return position;
+      return new LogicalPosition(line, column);
     }
   }
 
@@ -1396,9 +1415,8 @@
         }
 
         try {
-          EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
-            IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
-          handler.execute(myEditor, myEditor.getDataContext());
+          EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
+          handler.execute(myEditor, CaretImpl.this, myEditor.getDataContext());
         }
         finally {
           if (needOverrideSetting) {
@@ -1453,6 +1471,10 @@
     return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
   }
 
+  private int getCurrentX() {
+    return myEditor.visualPositionToXY(myVisibleCaret).x;
+  }
+
   @Override
   @NotNull
   public EditorImpl getEditor() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
new file mode 100644
index 0000000..c26c7e9
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor.impl;
+
+import com.intellij.codeInsight.editorActions.TextBlockTransferable;
+import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.LineTokenizer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public class EditorCopyPasteHelperImpl extends EditorCopyPasteHelper {
+  private static final Logger LOG = Logger.getInstance(EditorCopyPasteHelperImpl.class);
+
+  @Override
+  public void copySelectionToClipboard(@NotNull Editor editor) {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    List<TextBlockTransferableData> extraData = new ArrayList<TextBlockTransferableData>();
+    String s = editor.getCaretModel().supportsMultipleCarets() ? getSelectedTextForClipboard(editor, extraData)
+                                                               : editor.getSelectionModel().getSelectedText();
+    if (s == null) return;
+
+    s = TextBlockTransferable.convertLineSeparators(s, "\n", extraData);
+    Transferable contents = editor.getCaretModel().supportsMultipleCarets() ? new TextBlockTransferable(s, extraData, null) : new StringSelection(s);
+    CopyPasteManager.getInstance().setContents(contents);
+  }
+
+  public static String getSelectedTextForClipboard(@NotNull Editor editor, @NotNull Collection<TextBlockTransferableData> extraDataCollector) {
+    final StringBuilder buf = new StringBuilder();
+    String separator = "";
+    List<Caret> carets = editor.getCaretModel().getAllCarets();
+    int[] startOffsets = new int[carets.size()];
+    int[] endOffsets = new int[carets.size()];
+    for (int i = 0; i < carets.size(); i++) {
+      buf.append(separator);
+      String caretSelectedText = carets.get(i).getSelectedText();
+      startOffsets[i] = buf.length();
+      if (caretSelectedText != null) {
+        buf.append(caretSelectedText);
+      }
+      endOffsets[i] = buf.length();
+      separator = "\n";
+    }
+    extraDataCollector.add(new CaretStateTransferableData(startOffsets, endOffsets));
+    return buf.toString();
+  }
+
+  @Nullable
+  @Override
+  public TextRange[] pasteFromClipboard(@NotNull Editor editor) {
+    CopyPasteManager manager = CopyPasteManager.getInstance();
+    if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+      Transferable clipboardContents = manager.getContents();
+      if (clipboardContents != null) {
+        return pasteTransferable(editor, clipboardContents);
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  @Override
+  public TextRange[] pasteTransferable(final @NotNull Editor editor, @NotNull Transferable content) {
+    String text = getStringContent(content);
+    if (text == null) return null;
+
+    if (editor.getCaretModel().supportsMultipleCarets()) {
+      int caretCount = editor.getCaretModel().getCaretCount();
+      if (caretCount == 1 && editor.isColumnMode()) {
+        int pastedLineCount = LineTokenizer.calcLineCount(text, true);
+        EditorModificationUtil.deleteSelectedText(editor);
+        Caret caret = editor.getCaretModel().getPrimaryCaret();
+        for (int i = 0; i < pastedLineCount - 1; i++) {
+          caret = caret.clone(false);
+          if (caret == null) {
+            break;
+          }
+        }
+        caretCount = editor.getCaretModel().getCaretCount();
+      }
+      CaretStateTransferableData caretData = null;
+      try {
+        caretData = content.isDataFlavorSupported(CaretStateTransferableData.FLAVOR)
+                    ? (CaretStateTransferableData)content.getTransferData(CaretStateTransferableData.FLAVOR) : null;
+      }
+      catch (Exception e) {
+        LOG.error(e);
+      }
+      final TextRange[] ranges = new TextRange[caretCount];
+      final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretData, caretCount).iterator();
+      final int[] index = {0};
+      editor.getCaretModel().runForEachCaret(new CaretAction() {
+        @Override
+        public void perform(Caret caret) {
+          String segment = segments.next();
+          int caretOffset = caret.getOffset();
+          ranges[index[0]++] = new TextRange(caretOffset, caretOffset + segment.length());
+          EditorModificationUtil.insertStringAtCaret(editor, segment, false, true);
+        }
+      });
+      return ranges;
+    }
+    else {
+      int caretOffset = editor.getCaretModel().getOffset();
+      EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
+      return new TextRange[] { new TextRange(caretOffset, caretOffset + text.length())};
+    }
+  }
+
+  @Nullable
+  private static String getStringContent(@NotNull Transferable content) {
+    RawText raw = RawText.fromTransferable(content);
+    if (raw != null) return raw.rawText;
+
+    try {
+      return (String)content.getTransferData(DataFlavor.stringFlavor);
+    }
+    catch (UnsupportedFlavorException ignore) { }
+    catch (IOException ignore) { }
+
+    return null;
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index f600c60..39706f0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -992,7 +992,16 @@
   }
 
   public void setLineNumberAreaWidth(@NotNull TIntFunction calculator) {
-    final int lineNumberAreaWidth = calculator.execute(myLineNumberConvertor.execute(endLineNumber()));
+    int maxLineNumber = 0;
+    for (int i = endLineNumber(); i >= 0; i--) {
+      int number = myLineNumberConvertor.execute(i);
+      if (number >= 0) {
+        maxLineNumber = number;
+        break;
+      }
+    }
+
+    final int lineNumberAreaWidth = calculator.execute(maxLineNumber);
     if (myLineNumberAreaWidth != lineNumberAreaWidth) {
       myLineNumberAreaWidth = lineNumberAreaWidth;
       fireResized();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
index c1499a7..8be2284 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
@@ -15,10 +15,19 @@
  */
 package com.intellij.openapi.editor.impl;
 
+import com.intellij.lexer.Lexer;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
+import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
 import com.intellij.reference.SoftReference;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -55,4 +64,28 @@
     return null;
   }
 
+  @Nullable
+  public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
+    EditorHighlighter highlighter = null;
+
+    PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
+    final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
+    final EditorHighlighter cachedEditorHighlighter;
+    boolean alreadyInitializedHighlighter = false;
+
+    if (document != null &&
+        (cachedEditorHighlighter = getEditorHighlighterForCachesBuilding(document)) != null &&
+        PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
+      highlighter = cachedEditorHighlighter;
+      alreadyInitializedHighlighter = true;
+    }
+    else if (virtualFile != null) {
+      highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
+    }
+
+    if (highlighter != null) {
+      return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
+    }
+    return null;
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index b708f38..c0ffbd1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -33,7 +33,7 @@
 import com.intellij.openapi.actionSystem.impl.MouseGestureManager;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.application.impl.LaterInvocator;
 import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.command.UndoConfirmationPolicy;
 import com.intellij.openapi.diagnostic.Logger;
@@ -147,7 +147,6 @@
   @NotNull private final EditorComponentImpl myEditorComponent;
   @NotNull private final EditorGutterComponentImpl myGutterComponent;
   private final TraceableDisposable myTraceableDisposable = new TraceableDisposable(new Throwable());
-  private volatile boolean hasTabs; // optimisation flag: when editor contains no tabs it is dramatically easier to calculate positions
 
   static {
     ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0, 0, UIManager.getFont("Label.font").getFamily()); // load costly font info
@@ -168,6 +167,7 @@
   @NotNull private final CaretCursor myCaretCursor;
   private final ScrollingTimer myScrollingTimer = new ScrollingTimer();
 
+  @SuppressWarnings("RedundantStringConstructorCall")
   private final Object MOUSE_DRAGGED_GROUP = new String("MouseDraggedGroup");
 
   @NotNull private final SettingsImpl mySettings;
@@ -246,8 +246,6 @@
   @Nullable private Color myForcedBackground = null;
   @Nullable private Dimension myPreferredSize;
   private int myVirtualPageHeight;
-  @Nullable private Runnable myGutterSizeUpdater = null;
-  private boolean myGutterNeedsUpdate = false;
   private Alarm myAppleRepaintAlarm;
 
   private final Alarm myMouseSelectionStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@@ -317,8 +315,12 @@
   }
 
   EditorImpl(@NotNull Document document, boolean viewer, @Nullable Project project) {
+    assertIsDispatchThread();
     myProject = project;
     myDocument = (DocumentEx)document;
+    if (myDocument instanceof DocumentImpl) {
+      ((DocumentImpl)myDocument).requestTabTracking();
+    }
     myScheme = createBoundColorSchemeDelegate(null);
     initTabPainter();
     myIsViewer = viewer;
@@ -433,13 +435,13 @@
         if (myPrimaryCaret != null) {
           myPrimaryCaret.updateVisualPosition(); // repainting old primary caret's row background
         }
-        ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+        updateCaretVisualPosition(e);
         myPrimaryCaret = myCaretModel.getPrimaryCaret();
       }
 
       @Override
       public void caretRemoved(CaretEvent e) {
-        ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+        updateCaretVisualPosition(e);
         myPrimaryCaret = myCaretModel.getPrimaryCaret(); // repainting new primary caret's row background
         myPrimaryCaret.updateVisualPosition();
       }
@@ -548,7 +550,13 @@
         }
       });
     }
-    updateHasTabsFlag(document.getImmutableCharSequence());
+  }
+
+  private static void updateCaretVisualPosition(CaretEvent e) {
+    CaretImpl caretImpl = ((CaretImpl)e.getCaret());
+    if (caretImpl != null) {
+      caretImpl.updateVisualPosition(); // repainting caret region
+    }
   }
 
   @NotNull
@@ -575,7 +583,10 @@
     myPrefixWidthInPixels = 0;
     if (myPrefixText != null) {
       for (char c : myPrefixText) {
-        myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+        LOG.assertTrue(myPrefixAttributes != null);
+        if (myPrefixAttributes != null) {
+          myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+        }
       }
     }
     mySoftWrapModel.recalculate();
@@ -791,6 +802,9 @@
     if (myConnection != null) {
       myConnection.disconnect();
     }
+    if (myDocument instanceof DocumentImpl) {
+      ((DocumentImpl)myDocument).giveUpTabTracking();
+    }
     Disposer.dispose(myDisposable);
   }
 
@@ -898,9 +912,7 @@
     new UiNotifyConnector(myEditorComponent, new Activatable.Adapter(){
       @Override
       public void showNotify() {
-        if (myGutterNeedsUpdate) {
-          updateGutterSize();
-        }
+        myGutterComponent.updateSize();
       }
     });
 
@@ -1505,7 +1517,8 @@
   private final int[] myLastXOffsets = new int[myLastStartOffsets.length];
   private final int[] myLastXs = new int[myLastStartOffsets.length];
   private int myCurrentCachePosition;
-  private int myLastCacheHits, myTotalRequests; // todo remove
+  private int myLastCacheHits;
+  private int myTotalRequests; // todo remove
 
   private int getTabbedTextWidth(int startOffset, int targetColumn, int xOffset) {
     int x = xOffset;
@@ -1621,7 +1634,7 @@
 
   @Override
   public void repaint(final int startOffset, int endOffset) {
-    if (!isShowing() || myScrollPane == null || myDocument.isInBulkUpdate()) {
+    if (!isShowing() || myDocument.isInBulkUpdate()) {
       return;
     }
 
@@ -1638,7 +1651,7 @@
   }
 
   private boolean isShowing() {
-    return myGutterComponent != null && myGutterComponent.isShowing();
+    return myGutterComponent.isShowing();
   }
 
   private void repaintToScreenBottom(int startLine) {
@@ -1679,9 +1692,6 @@
   }
 
   private void bulkUpdateFinished() {
-    if (myScrollPane == null) {
-      return;
-    }
 
     clearTextWidthCache();
 
@@ -1700,7 +1710,7 @@
     if (isStickySelection()) {
       setStickySelection(false);
     }
-    if (myDocument.isInBulkUpdate() || myScrollingModel == null) {
+    if (myDocument.isInBulkUpdate()) {
       // Assuming that the job is done at bulk listener callback methods.
       return;
     }
@@ -1716,7 +1726,7 @@
   }
 
   private void changedUpdate(DocumentEvent e) {
-    if (myScrollPane == null || myDocument.isInBulkUpdate()) return;
+    if (myDocument.isInBulkUpdate()) return;
 
     clearTextWidthCache();
     mySelectionModel.removeBlockSelection();
@@ -1754,16 +1764,10 @@
     Point caretLocation = visualPositionToXY(getCaretModel().getVisualPosition());
     int scrollOffset = caretLocation.y - myCaretUpdateVShift;
     getScrollingModel().scrollVertically(scrollOffset);
-    updateHasTabsFlag(e.getNewFragment());
   }
 
-  private void updateHasTabsFlag(@NotNull CharSequence newChars) {
-    if (!hasTabs) {
-      hasTabs = StringUtil.contains(newChars, 0, newChars.length(), '\t');
-    }
-  }
   public boolean hasTabs() {
-    return hasTabs;
+    return !(myDocument instanceof DocumentImpl) || ((DocumentImpl)myDocument).mightContainTabs();
   }
 
   public boolean isScrollToCaret() {
@@ -1784,24 +1788,12 @@
   }
 
   private void updateGutterSize() {
-    if (myGutterSizeUpdater != null) return;
-    myGutterSizeUpdater = new Runnable() {
+    LaterInvocator.invokeLater(new Runnable() {
       @Override
       public void run() {
-        if (!isDisposed()) {
-          if (isShowing()) {
-            myGutterComponent.updateSize();
-            myGutterNeedsUpdate = false;
-          }
-          else {
-            myGutterNeedsUpdate = true;
-          }
-        }
-        myGutterSizeUpdater = null;
+        myGutterComponent.updateSize();
       }
-    };
-
-    SwingUtilities.invokeLater(myGutterSizeUpdater);
+    });
   }
 
   void validateSize() {
@@ -1945,7 +1937,7 @@
     }
 
     if (isReleased) {
-      g.setColor(new Color(128, 255, 128));
+      g.setColor(new JBColor(new Color(128, 255, 128), new Color(128, 255, 128)));
       g.fillRect(clip.x, clip.y, clip.width, clip.height);
       return;
     }
@@ -2239,7 +2231,7 @@
     myLastBackgroundColor = null;
 
     int start = clipStartOffset;
-    int end = clipEndOffset;
+
     if (!myPurePaintingMode) {
       getSoftWrapModel().registerSoftWrapsIfNecessary();
     }
@@ -2250,7 +2242,7 @@
       return;
     }
 
-    IterationState iterationState = new IterationState(this, start, end, isPaintSelection());
+    IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection());
     TextAttributes attributes = iterationState.getMergedAttributes();
     Color backColor = getBackgroundColor(attributes);
     int fontType = attributes.getFontType();
@@ -2322,7 +2314,7 @@
           position.y += lineHeight;
           start = lEnd;
         }
-        else if (collapsedFolderAt.getEndOffset() == end) {
+        else if (collapsedFolderAt.getEndOffset() == clipEndOffset) {
           softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
           if (softWrap != null) {
             position.x = drawSoftWrapAwareBackground(
@@ -3677,19 +3669,16 @@
     return logicalToVisualPosition(logicalPos, true);
   }
 
-  // TODO den remove as soon as the problem is fixed.
-  private final ThreadLocal<Integer> stackDepth = new ThreadLocal<Integer>();
-
-  // TODO den remove as soon as the problem is fixed.
   @Override
   @NotNull
   public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
-    stackDepth.set(0);
-    return doLogicalToVisualPosition(logicalPos, softWrapAware);
+    return doLogicalToVisualPosition(logicalPos, softWrapAware,0);
   }
 
   @NotNull
-  private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
+  private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware,
+                                                   // TODO den remove as soon as the problem is fixed.
+                                                   int stackDepth) {
     assertReadAccess();
     if (!myFoldingModel.isFoldingEnabled() && !mySoftWrapModel.isSoftWrappingEnabled()) {
       return new VisualPosition(logicalPos.line, logicalPos.column);
@@ -3703,25 +3692,12 @@
         offset = outermostCollapsed.getStartOffset();
         LogicalPosition foldStart = offsetToLogicalPosition(offset);
         // TODO den remove as soon as the problem is fixed.
-        Integer depth = stackDepth.get();
-        if (depth >= 0) {
-          stackDepth.set(depth + 1);
-          if (depth > 15) {
-            LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
-                      logicalPos + "'. State: " + dumpState());
-            stackDepth.set(-1);
-          }
+        if (stackDepth > 15) {
+          LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
+                    logicalPos + "'. State: " + dumpState());
+          stackDepth = -1;
         }
-        // TODO den remove as soon as the problem is fixed.
-        try {
-          return doLogicalToVisualPosition(foldStart, true);
-        }
-        finally {
-          depth = stackDepth.get();
-          if (depth > 0) {
-            stackDepth.set(depth - 1);
-          }
-        }
+        return doLogicalToVisualPosition(foldStart, true, stackDepth+1);
       }
       else {
         offset = outermostCollapsed.getEndOffset() + 3;  // WTF?
@@ -3988,7 +3964,7 @@
       return false;
     }
 
-    if (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint())) {
+    if (myInitialMouseEvent!= null && (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint()))) {
       myIgnoreMouseEventsConsecutiveToInitial = false;
       myInitialMouseEvent = null;
       return false;
@@ -4197,7 +4173,9 @@
             }
           } else {
             final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret;
-            setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+            if (blockStart != null) {
+              setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+            }
           }
         }
         else {
@@ -5002,7 +4980,7 @@
   }
 
   void assertIsDispatchThread() {
-    ApplicationManagerEx.getApplicationEx().assertIsDispatchThread();
+    ApplicationManager.getApplication().assertIsDispatchThread();
   }
 
   private static void assertReadAccess() {
@@ -5392,7 +5370,9 @@
             public void run() {
               int docLength = doc.getTextLength();
               ProperTextRange range = composedTextRange.intersection(new TextRange(0, docLength));
-              doc.deleteString(range.getStartOffset(), range.getEndOffset());
+              if (range != null) {
+                doc.deleteString(range.getStartOffset(), range.getEndOffset());
+              }
             }
           });
         }
@@ -6745,7 +6725,7 @@
 
   private class TablessBorder extends SideBorder {
     private TablessBorder() {
-      super(UIUtil.getBorderColor(), SideBorder.ALL);
+      super(JBColor.border(), SideBorder.ALL);
     }
 
     @Override
@@ -6769,7 +6749,7 @@
     public Insets getBorderInsets(Component c) {
       Container splitters = SwingUtilities.getAncestorOfClass(EditorsSplitters.class, c);
       boolean thereIsSomethingAbove = !SystemInfo.isMac || UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR ||
-                                      EditorImpl.this.myProject != null && !ToolWindowManagerEx.getInstanceEx(EditorImpl.this.myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
+                                      myProject != null && !ToolWindowManagerEx.getInstanceEx(myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
       return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0);
     }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
index a2f45fe..6ec29e5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
@@ -36,6 +36,7 @@
 import com.intellij.openapi.command.UndoConfirmationPolicy;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorFontType;
 import com.intellij.openapi.editor.ex.*;
 import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
@@ -45,7 +46,7 @@
 import com.intellij.openapi.ui.popup.Balloon;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.ProperTextRange;
-import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.wm.ToolWindowAnchor;
 import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
 import com.intellij.ui.*;
@@ -428,7 +429,7 @@
     }
 
     @Override
-    public void paint(Graphics g) {
+    public void paint(@NotNull Graphics g) {
       ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
 
       final Rectangle bounds = getBounds();
@@ -437,7 +438,7 @@
       errorIconBounds.y = bounds.height / 2 - errorIconBounds.height / 2;
       
       try {
-        if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+        if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
           g.setColor(getEditor().getColorsScheme().getDefaultBackground());
           g.fillRect(0, 0, bounds.width, bounds.height);
 
@@ -493,7 +494,7 @@
     }
 
     @Override
-    public void uninstallUI(JComponent c) {
+    public void uninstallUI(@NotNull JComponent c) {
       super.uninstallUI(c);
       myCachedTrack = null;
     }
@@ -528,7 +529,7 @@
 
     @Override
     protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
-      if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+      if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
         super.paintThumb(g, c, thumbBounds);
         return;
       }
@@ -565,13 +566,13 @@
 
     @Override
     protected int getThickness() {
-      if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) return super.getThickness();
+      if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) return super.getThickness();
       return super.getThickness() + (isMacOverlayScrollbar() ? 2 : 7);
     }
 
     @Override
     protected void doPaintTrack(Graphics g, JComponent c, Rectangle bounds) {
-      if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+      if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
         g.setColor(getEditor().getColorsScheme().getDefaultBackground());
         g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
         //return;
@@ -609,7 +610,9 @@
     }
 
     private void paintTrackBasement(Graphics g, Rectangle bounds) {
-      if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+      if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
+        g.setColor(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground());
+        g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
         return;
       }
 
@@ -647,13 +650,13 @@
     private void drawMarkup(final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) {
       final Queue<PositionedStripe> thinEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
         @Override
-        public int compare(PositionedStripe o1, PositionedStripe o2) {
+        public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
           return o1.yEnd - o2.yEnd;
         }
       });
       final Queue<PositionedStripe> wideEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
         @Override
-        public int compare(PositionedStripe o1, PositionedStripe o2) {
+        public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
           return o1.yEnd - o2.yEnd;
         }
       });
@@ -757,12 +760,21 @@
                           boolean drawBottomDecoration) {
       int x = isMirrored() ? 3 : 5;
       int paintWidth = width;
+      boolean flatStyle = Registry.is("ide.new.markup.markers");
       if (thinErrorStripeMark) {
         paintWidth /= 2;
-        paintWidth += 1;
+        paintWidth += flatStyle ? 0 : 1;
         x = isMirrored() ? width + 2 : 0;
       }
       if (color == null) return;
+      Color darker = UIUtil.isUnderDarcula()? color : ColorUtil.shift(color, 0.75);
+
+      if (flatStyle) {
+        g.setColor(darker);
+        g.fillRect(x, yStart, paintWidth, yEnd - yStart + 1);
+        return;
+      }
+
       g.setColor(color);
       g.fillRect(x + 1, yStart, paintWidth - 2, yEnd - yStart + 1);
 
@@ -774,7 +786,6 @@
         //top decoration
         UIUtil.drawLine(g, x + 1, yStart, x + paintWidth - 2, yStart);
       }
-      Color darker = ColorUtil.shift(color, 0.75);
 
       g.setColor(darker);
       if (drawBottomDecoration) {
@@ -787,7 +798,7 @@
 
     // mouse events
     @Override
-    public void mouseClicked(final MouseEvent e) {
+    public void mouseClicked(@NotNull final MouseEvent e) {
       CommandProcessor.getInstance().executeCommand(myEditor.getProject(), new Runnable() {
         @Override
         public void run() {
@@ -801,11 +812,11 @@
     }
 
     @Override
-    public void mousePressed(MouseEvent e) {
+    public void mousePressed(@NotNull MouseEvent e) {
     }
 
     @Override
-    public void mouseReleased(MouseEvent e) {
+    public void mouseReleased(@NotNull MouseEvent e) {
     }
 
     private int getWidth() {
@@ -824,7 +835,7 @@
     }
 
     @Override
-    public void mouseMoved(MouseEvent e) {
+    public void mouseMoved(@NotNull MouseEvent e) {
       EditorImpl.MyScrollBar scrollBar = myEditor.getVerticalScrollBar();
       int buttonHeight = scrollBar.getDecScrollButtonHeight();
       int lineCount = getDocument().getLineCount() + myEditor.getSettings().getAdditionalLinesCount();
@@ -897,16 +908,16 @@
     }
 
     @Override
-    public void mouseEntered(MouseEvent e) {
+    public void mouseEntered(@NotNull MouseEvent e) {
     }
 
     @Override
-    public void mouseExited(MouseEvent e) {
+    public void mouseExited(@NotNull MouseEvent e) {
       cancelMyToolTips(e, true);
     }
 
     @Override
-    public void mouseDragged(MouseEvent e) {
+    public void mouseDragged(@NotNull MouseEvent e) {
       cancelMyToolTips(e, true);
     }
 
@@ -943,13 +954,15 @@
   }
 
   public void markDirtied(@NotNull ProperTextRange yPositions) {
-    int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
-    int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
-                                                               : Math
-                .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
-    ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
+    if (myDirtyYPositions != WHOLE_DOCUMENT) {
+      int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
+      int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
+                                                                 : Math
+                  .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
+      ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
 
-    myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+      myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+    }
 
     myEditorScrollbarTop = 0;
     myEditorSourceHeight = 0;
@@ -1137,7 +1150,7 @@
           myHighlighters.add(rangeHighlighter);
       }
       Collections.sort(myHighlighters, new Comparator<RangeHighlighterEx>() {
-        public int compare(RangeHighlighterEx ex1, RangeHighlighterEx ex2) {
+        public int compare(@NotNull RangeHighlighterEx ex1, @NotNull RangeHighlighterEx ex2) {
           LogicalPosition startPos1 = myEditor.offsetToLogicalPosition(ex1.getAffectedAreaStartOffset());
           LogicalPosition startPos2 = myEditor.offsetToLogicalPosition(ex2.getAffectedAreaStartOffset());
           if (startPos1.line != startPos2.line) return 0;
@@ -1167,7 +1180,7 @@
           }
 
           @Override
-          protected void paintComponent(Graphics g) {
+          protected void paintComponent(@NotNull Graphics g) {
             if (myVisualLine ==-1) return;
             Dimension size = getPreferredSize();
             EditorGutterComponentEx gutterComponentEx = myEditor.getGutterComponentEx();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
new file mode 100644
index 0000000..5a9c704
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor.impl;
+
+import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.LazyRangeMarkerFactory;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.WeakList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory {
+  private final Project myProject;
+  private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY");
+
+  public LazyRangeMarkerFactoryImpl(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
+    myProject = project;
+
+    EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
+      @Override
+      public void beforeDocumentChange(DocumentEvent e) {
+        transformRangeMarkers(e);
+      }
+
+      @Override
+      public void documentChanged(DocumentEvent e) {
+        transformRangeMarkers(e);
+      }
+
+      private void transformRangeMarkers(@NotNull DocumentEvent e) {
+        Document document = e.getDocument();
+        VirtualFile file = fileDocumentManager.getFile(document);
+        if (file == null) {
+          return;
+        }
+
+        WeakList<LazyMarker> lazyMarkers = getMarkers(file);
+        if (lazyMarkers == null) {
+          return;
+        }
+
+        List<LazyMarker> markers = lazyMarkers.toStrongList();
+        for (LazyMarker marker : markers) {
+          if (file.equals(marker.getFile())) {
+            marker.getOrCreateDelegate();
+          }
+        }
+      }
+    }, project);
+  }
+
+  static WeakList<LazyMarker> getMarkers(@NotNull VirtualFile file) {
+    return file.getUserData(LazyRangeMarkerFactoryImpl.LAZY_MARKERS_KEY);
+  }
+
+  private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+    WeakList<LazyMarker> markers = getMarkers(file);
+
+    if (markers == null) {
+      markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
+    }
+    markers.add(marker);
+  }
+
+  private static void removeFromLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+    WeakList<LazyMarker> markers = getMarkers(file);
+
+    if (markers != null) {
+      markers.remove(marker);
+    }
+  }
+
+  @Override
+  @NotNull
+  public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+      @Override
+      public RangeMarker compute() {
+        // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor
+        final LazyMarker marker = new OffsetLazyMarker(file, offset);
+        addToLazyMarkersList(marker, file);
+        return marker;
+      }
+    });
+  }
+
+  @Override
+  @NotNull
+  public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+      @Override
+      public RangeMarker compute() {
+        final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
+        if (document != null) {
+          final int offset = calculateOffset(myProject, file, document, line, column);
+          return document.createRangeMarker(offset, offset, persistent);
+        }
+
+        final LazyMarker marker = new LineColumnLazyMarker(file, line, column);
+        addToLazyMarkersList(marker, file);
+        return marker;
+      }
+    });
+  }
+
+  abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker {
+    protected RangeMarker myDelegate; // the real range marker which is created only when document is opened, or (this) which means it's disposed
+    protected final VirtualFile myFile;
+    protected final int myInitialOffset;
+
+    private LazyMarker(@NotNull VirtualFile file, int offset) {
+      myFile = file;
+      myInitialOffset = offset;
+    }
+
+    boolean isDelegated() {
+      return myDelegate != null;
+    }
+
+    @NotNull
+    public VirtualFile getFile() {
+      return myFile;
+    }
+
+    @Nullable
+    protected final RangeMarker getOrCreateDelegate() {
+      if (myDelegate == null) {
+        Document document = FileDocumentManager.getInstance().getDocument(myFile);
+        if (document == null) {
+          return null;
+        }
+        myDelegate = createDelegate(myFile, document);
+        removeFromLazyMarkersList(this, myFile);
+      }
+      return isDisposed() ? null : myDelegate;
+    }
+
+    @Nullable
+    protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
+
+    @Override
+    @NotNull
+    public Document getDocument() {
+      RangeMarker delegate = getOrCreateDelegate();
+      if (delegate == null) {
+        //noinspection ConstantConditions
+        return FileDocumentManager.getInstance().getDocument(myFile);
+      }
+      return delegate.getDocument();
+    }
+
+    @Override
+    public int getStartOffset() {
+      return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getStartOffset();
+    }
+
+    public boolean isDisposed() {
+      return myDelegate == this;
+    }
+
+
+    @Override
+    public int getEndOffset() {
+      return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getEndOffset();
+    }
+
+    @Override
+    public boolean isValid() {
+      RangeMarker delegate = getOrCreateDelegate();
+      return delegate != null && !isDisposed() && delegate.isValid();
+    }
+
+    @Override
+    public void setGreedyToLeft(boolean greedy) {
+      getOrCreateDelegate().setGreedyToLeft(greedy);
+    }
+
+    @Override
+    public void setGreedyToRight(boolean greedy) {
+      getOrCreateDelegate().setGreedyToRight(greedy);
+    }
+
+    @Override
+    public boolean isGreedyToRight() {
+      return getOrCreateDelegate().isGreedyToRight();
+    }
+
+    @Override
+    public boolean isGreedyToLeft() {
+      return getOrCreateDelegate().isGreedyToLeft();
+    }
+
+    @Override
+    public void dispose() {
+      assert !isDisposed();
+      RangeMarker delegate = myDelegate;
+      if (delegate == null) {
+        removeFromLazyMarkersList(this, myFile);
+        myDelegate = this; // mark of disposed marker
+      }
+      else {
+        delegate.dispose();
+      }
+    }
+  }
+
+  private static class OffsetLazyMarker extends LazyMarker {
+    private OffsetLazyMarker(@NotNull VirtualFile file, int offset) {
+      super(file, offset);
+    }
+
+    @Override
+    public boolean isValid() {
+      RangeMarker delegate = myDelegate;
+      if (delegate == null) {
+        Document document = FileDocumentManager.getInstance().getDocument(myFile);
+        return document != null;
+      }
+
+      return super.isValid();
+    }
+
+    @Override
+    @NotNull
+    public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
+      final int offset = Math.min(myInitialOffset, document.getTextLength());
+      return document.createRangeMarker(offset, offset);
+    }
+  }
+
+  private class LineColumnLazyMarker extends LazyMarker {
+    private final int myLine;
+    private final int myColumn;
+
+    private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) {
+      super(file, -1);
+      myLine = line;
+      myColumn = column;
+    }
+
+    @Override
+    @Nullable
+    public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
+      if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
+        return null;
+      }
+
+      int offset = calculateOffset(myProject, file, document, myLine, myColumn);
+      return document.createRangeMarker(offset, offset);
+    }
+
+    @Override
+    public boolean isValid() {
+      RangeMarker delegate = myDelegate;
+      if (delegate == null) {
+        Document document = FileDocumentManager.getInstance().getDocument(myFile);
+        return document != null && (document.getTextLength() != 0 || myLine == 0 && myColumn == 0);
+      }
+
+      return super.isValid();
+    }
+
+    @Override
+    public int getStartOffset() {
+      getOrCreateDelegate();
+      return super.getStartOffset();
+    }
+
+    @Override
+    public int getEndOffset() {
+      getOrCreateDelegate();
+      return super.getEndOffset();
+    }
+  }
+
+  private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
+    int offset;
+    if (line < document.getLineCount()) {
+      final int lineStart = document.getLineStartOffset(line);
+      final int lineEnd = document.getLineEndOffset(line);
+      final CharSequence docText = document.getCharsSequence();
+      final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType());
+
+      offset = lineStart;
+      int col = 0;
+      while (offset < lineEnd && col < column) {
+        col += docText.charAt(offset) == '\t' ? tabSize : 1;
+        offset++;
+      }
+    }
+    else {
+      offset = document.getTextLength();
+    }
+    return offset;
+  }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
index 2f5a811..731d1e2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
@@ -567,7 +567,7 @@
 
   @Override
   public void copySelectionToClipboard() {
-    CopyPasteSupport.copySelectionToClipboard(myEditor);
+    EditorCopyPasteHelper.getInstance().copySelectionToClipboard(myEditor);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
index 6f1b982..d8b6697 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
@@ -303,14 +303,7 @@
     if (!isSoftWrappingEnabled()) {
       return 0;
     }
-    int result = 0;
-    FoldingModel foldingModel = myEditor.getFoldingModel();
-    for (SoftWrap softWrap : myStorage.getSoftWraps()) {
-      if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) {
-        result++; // Assuming that soft wrap has single line feed all the time
-      }
-    }
-    return result;
+    return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time
   }
 
   /**
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
similarity index 94%
rename from platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
rename to platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
index a5c477f..165ff57 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.openapi.fileEditor.impl;
+package com.intellij.openapi.editor.impl;
 
 import com.intellij.ide.DataManager;
 import com.intellij.injected.editor.DocumentWindow;
@@ -23,7 +23,6 @@
 import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
-import com.intellij.openapi.editor.impl.DocumentImpl;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
 import com.intellij.openapi.project.Project;
@@ -37,11 +36,12 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
-
   public static final Key<String> OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY");
   public static final Key<Boolean> OVERRIDE_ENSURE_NEWLINE_KEY = Key.create("OVERRIDE_ENSURE_NEWLINE_KEY");
 
@@ -61,7 +61,7 @@
     strip(document);
   }
 
-  private void strip(final Document document) {
+  private void strip(@NotNull final Document document) {
     if (!document.isWritable()) return;
     FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
     VirtualFile file = fileDocumentManager.getFile(document);
@@ -149,7 +149,7 @@
     ((DocumentImpl)document).clearLineModificationFlagsExcept(caretLines);
   }
 
-  public static boolean stripIfNotCurrentLine(Document document, boolean inChangedLinesOnly) {
+  public static boolean stripIfNotCurrentLine(@NotNull Document document, boolean inChangedLinesOnly) {
     if (document instanceof DocumentWindow) {
       document = ((DocumentWindow)document).getDelegate();
     }
@@ -168,10 +168,11 @@
     if (activeEditor != null && activeEditor.getCaretModel().supportsMultipleCarets()) {
       List<Caret> carets = activeEditor.getCaretModel().getAllCarets();
       List<VisualPosition> visualCarets = new ArrayList<VisualPosition>(carets.size());
-      List<Integer> caretOffsets = new ArrayList<Integer>(carets.size());
-      for (Caret caret : carets) {
+      int[] caretOffsets = new int[carets.size()];
+      for (int i = 0; i < carets.size(); i++) {
+        Caret caret = carets.get(i);
         visualCarets.add(caret.getVisualPosition());
-        caretOffsets.add(caret.getOffset());
+        caretOffsets[i] = caret.getOffset();
       }
 
       markAsNeedsStrippingLater = ((DocumentImpl)document).stripTrailingSpaces(activeEditor.getProject(), inChangedLinesOnly, isVirtualSpaceEnabled, caretOffsets);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
index c2353d5..03b03fa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
@@ -277,6 +277,8 @@
     myTabs.getTabAt(index).setTooltipText(text);
   }
 
+  public boolean isTitleShortened(int index) { return myTabs.getTabAt(index).isTitleShortened(); }
+
   public void setBackgroundColorAt(final int index, final Color color) {
     myTabs.getTabAt(index).setTabColor(color);
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
index 3519ab6..06a3966 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
@@ -34,6 +34,7 @@
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.ui.ThreeComponentsSplitter;
 import com.intellij.openapi.util.*;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
@@ -319,6 +320,16 @@
 
           if (disposeIfNeeded && getTabCount() == 0) {
             removeFromSplitter();
+            if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE) {
+              final EditorsSplitters owner = getOwner();
+              if (owner != null) {
+                final ThreeComponentsSplitter splitter = UIUtil.getParentOfType(ThreeComponentsSplitter.class, owner);
+                if (splitter != null) {
+                  splitter.revalidate();
+                  splitter.repaint();
+                }
+              }
+            }
           }
           else {
             myPanel.revalidate();
@@ -453,6 +464,10 @@
     }
   }
 
+  private boolean isTitleShortenedAt(int index) {
+    return myTabbedPane != null && myTabbedPane.isTitleShortened(index);
+  }
+
   private void setBackgroundColorAt(final int index, final Color color) {
     if (myTabbedPane != null) {
       myTabbedPane.setBackgroundColorAt(index, color);
@@ -897,7 +912,9 @@
     final int index = findEditorIndex(findFileComposite(file));
     if (index != -1) {
       setTitleAt(index, EditorTabbedContainer.calcTabTitle(getManager().getProject(), file));
-      setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS ? getManager().getFileTooltipText(file) : null);
+      setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS || isTitleShortenedAt(index)
+                              ? getManager().getFileTooltipText(file)
+                              : null);
     }
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
index f396b1e..091ff11 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
@@ -37,6 +37,7 @@
 import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
 import com.intellij.openapi.editor.impl.EditorFactoryImpl;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.*;
 import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index e36a120..c7fa51f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -227,7 +227,7 @@
       fm.doWhenFocusSettlesDown(run);
     }
     else {
-      run.run();
+      UIUtil.invokeAndWaitIfNeeded(run);
     }
 
     return result;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
index 69a91ec..b19b2aa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
@@ -16,7 +16,6 @@
 package com.intellij.openapi.fileEditor.impl;
 
 import com.intellij.ProjectTopics;
-import com.intellij.ide.IdeEventQueue;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.StorageScheme;
 import com.intellij.openapi.components.impl.stores.IProjectStore;
@@ -30,6 +29,7 @@
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.NotNullLazyKey;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.*;
 import com.intellij.util.NotNullFunction;
 import com.intellij.util.NullableFunction;
@@ -114,9 +114,7 @@
 
     if (deniedFiles.isEmpty()) return Collections.emptyList();
 
-    final int savedEventCount = IdeEventQueue.getInstance().getEventCount();
     UnlockOption unlockOption = askToUnlock(deniedFiles);
-    IdeEventQueue.getInstance().setEventCount(savedEventCount);
 
     if (unlockOption == null) return deniedFiles;
 
@@ -144,7 +142,9 @@
   }
 
   private boolean isProjectFile(@NotNull VirtualFile file) {
-    if (ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return true;
+    ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+    if (fileIndex.isInContent(file)) return true;
+    if (!Registry.is("ide.hide.excluded.files") && fileIndex.isExcluded(file) && !fileIndex.isUnderIgnored(file)) return true;
     
     if (myProject instanceof ProjectEx) {
       IProjectStore store = ((ProjectEx)myProject).getStateStore();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
index 60b42f7..690e7c7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
@@ -278,19 +278,22 @@
   }
 
   protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
-    if (editor.getCaretModel().supportsMultipleCarets()) {
-      CaretModel caretModel = editor.getCaretModel();
-      List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
-      for (TextEditorState.CaretState caretState : state.CARETS) {
-        states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
-                                  new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
-                                  new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+    if (state.CARETS != null) {
+      if (editor.getCaretModel().supportsMultipleCarets()) {
+        CaretModel caretModel = editor.getCaretModel();
+        List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
+        for (TextEditorState.CaretState caretState : state.CARETS) {
+          states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
+                                    new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
+                                    new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+        }
+        caretModel.setCaretsAndSelections(states);
       }
-      caretModel.setCaretsAndSelections(states);
-    } else {
-      LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
-      editor.getCaretModel().moveToLogicalPosition(pos);
-      editor.getSelectionModel().removeSelection();
+      else {
+        LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
+        editor.getCaretModel().moveToLogicalPosition(pos);
+        editor.getSelectionModel().removeSelection();
+      }
     }
     EditorEx editorEx = editor instanceof EditorEx ? (EditorEx)editor : null;
     boolean preciselyScrollVertically =
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
index 6c78ec1..4b4d191 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
@@ -30,6 +30,7 @@
 import com.intellij.openapi.wm.IdeFrame;
 import com.intellij.openapi.wm.impl.FocusManagerImpl;
 import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,6 @@
 import java.awt.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseWheelEvent;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -230,12 +230,7 @@
   }
 
   private static void resetPopupTrigger(final MouseEvent e) {
-    try {
-      final Field popupTrigger = e.getClass().getDeclaredField("popupTrigger");
-      popupTrigger.setAccessible(true);
-      popupTrigger.set(e, false);
-    }
-    catch (Exception ignored) { }
+    ReflectionUtil.setField(MouseEvent.class, e, boolean.class, "popupTrigger", false);
   }
 
   /**
@@ -247,14 +242,7 @@
    */
   public static boolean patchClickCount(final MouseEvent e) {
     if (e.getClickCount() != 1 && e.getButton() > 3) {
-      try {
-        final Field clickCount = e.getClass().getDeclaredField("clickCount");
-        clickCount.setAccessible(true);
-        clickCount.set(e, 1);
-        return true;
-      }
-      catch (Exception ignored) {
-      }
+      ReflectionUtil.setField(MouseEvent.class, e, int.class, "clickCount", 1);
     }
     return false;
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
index 7b4f5a0..7c65a80 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
@@ -99,8 +99,8 @@
     if (Registry.is("editor.add.carets.on.double.control.arrows")) {
       ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, KeyEvent.VK_CONTROL, KeyEvent.VK_UP);
       ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, KeyEvent.VK_CONTROL, KeyEvent.VK_DOWN);
-      ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
-      ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
+      ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
+      ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
     }
 
     ourKeymapManagerInitialized = true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
index 2853645..13a8aae 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
@@ -17,10 +17,10 @@
 
 import com.intellij.ide.DataManager;
 import com.intellij.ide.IdeEventQueue;
-import com.intellij.openapi.actionSystem.ActionManager;
 import com.intellij.openapi.actionSystem.ActionPlaces;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
 import com.intellij.openapi.keymap.KeymapManager;
 import com.intellij.openapi.util.Clock;
 import com.intellij.openapi.util.Couple;
@@ -39,6 +39,10 @@
 
 /**
  * Support for keyboard shortcuts like Control-double-click or Control-double-click+A
+ *
+ * Timings that are used in the implementation to detect double click were tuned for SearchEverywhere
+ * functionality (invoked on double Shift), so if you need to change them, please make sure
+ * SearchEverywhere behaviour remains intact.
  */
 public class ModifierKeyDoubleClickHandler {
   private static final ModifierKeyDoubleClickHandler INSTANCE = new ModifierKeyDoubleClickHandler();
@@ -121,7 +125,7 @@
           return false;
         } else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get() && myActionKeyCode != -1) {
           if (keyCode == myActionKeyCode) {
-            if (event.getID() == KeyEvent.KEY_RELEASED) {
+            if (event.getID() == KeyEvent.KEY_PRESSED) {
               run(keyEvent);
             }
             return true;
@@ -192,7 +196,7 @@
     }
 
     private void run(KeyEvent event) {
-      final ActionManager actionManager = ActionManager.getInstance();
+      final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx();
       final AnAction action = actionManager.getAction(myActionId);
       final AnActionEvent anActionEvent = new AnActionEvent(event,
                                                             DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()),
@@ -200,7 +204,9 @@
                                                             action.getTemplatePresentation(),
                                                             actionManager,
                                                             0);
+      actionManager.fireBeforeActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
       action.actionPerformed(anActionEvent);
+      actionManager.fireAfterActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
     }
 
     private boolean isActionBound() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
index b99f192..ebb3686 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
@@ -393,7 +393,7 @@
     group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree()));
     group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree()));
 
-    group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.Actions.Properties) {
+    group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.ToolbarDecorator.Edit) {
       {
         registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), myActionsTree.getTree());
       }
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
index 104dc7b..d7c7dca 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
@@ -1,18 +1,64 @@
+/*
+ * 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.
+ */
 package com.intellij.openapi.options;
 
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 
 public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implements SearchableConfigurable, Configurable.NoScroll {
+  private final String id;
+  private final String displayName;
+  private final String helpTopic;
+
   private UI ui;
 
+  protected ConfigurableBase(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic) {
+    this.id = id;
+    this.displayName = displayName;
+    this.helpTopic = helpTopic;
+  }
+
+  @NotNull
+  @Override
+  public final String getId() {
+    return id;
+  }
+
+  @Nls
+  @Override
+  public final String getDisplayName() {
+    return displayName;
+  }
+
+  @Nullable
+  @Override
+  public final String getHelpTopic() {
+    return helpTopic;
+  }
+
   @Nullable
   @Override
   public Runnable enableSearch(String option) {
     return null;
   }
 
+  @NotNull
   protected abstract S getSettings();
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
index e454099..0ecb19a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
 package com.intellij.openapi.options;
 
 import org.jetbrains.annotations.NotNull;
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
new file mode 100644
index 0000000..9812165
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.options;
+
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.ReflectionUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public final class SimpleConfigurable<UI extends ConfigurableUi<S>, S> extends ConfigurableBase<UI, S> {
+  private final Class<UI> uiClass;
+  private final Getter<S> settingsGetter;
+
+  private SimpleConfigurable(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+    super(id, displayName, helpTopic);
+
+    this.uiClass = uiClass;
+    this.settingsGetter = settingsGetter;
+  }
+
+  public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+    return new SimpleConfigurable<UI, S>(id, displayName, helpTopic, uiClass, settingsGetter);
+  }
+
+  public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+    return create(id, displayName, id, uiClass, settingsGetter);
+  }
+
+  @NotNull
+  @Override
+  protected S getSettings() {
+    return settingsGetter.get();
+  }
+
+  @Override
+  protected UI createUi() {
+    return ReflectionUtil.newInstance(uiClass);
+  }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
index 35b75fe..47d3881 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
@@ -33,6 +33,7 @@
     myParent = parent;
   }
 
+  @Override
   public JComponent createComponent() {
     myTabbedPane = new TabbedPaneWrapper(myParent);
     createConfigurableTabs();
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
index 6ee4a1b..07e5a93 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
@@ -36,6 +36,7 @@
 import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.EdtRunnable;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.IdeGlassPaneUtil;
 import com.intellij.ui.DocumentAdapter;
@@ -366,6 +367,9 @@
           myOwnDetails.setContent(myContentWrapper);
           myOwnDetails.setBannerMinHeight(mySearchWrapper.getHeight());
           myOwnDetails.setText(getBannerText(configurable));
+          if (Registry.is("ide.file.settings.order.new")) {
+            myOwnDetails.forProject(myTree.getConfigurableProject(configurable));
+          }
 
           final ConfigurableContent content = myConfigurable2Content.get(current);
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
index 5524df2..e0ab248 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
@@ -308,7 +308,7 @@
       myHandle.setOpaque(false);
       content.add(myHandle, BorderLayout.WEST);
       content.add(myComponent, BorderLayout.CENTER);
-      myProjectIcon = new JLabel(" ", AllIcons.General.ProjectConfigurable, SwingConstants.LEFT);
+      myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
       myProjectIcon.setOpaque(true);
       content.add(myProjectIcon, BorderLayout.EAST);
       myRendererComponent.add(content, BorderLayout.CENTER);
@@ -407,32 +407,17 @@
       Project project = getConfigurableProject(base);
       if (project != null && Registry.is("ide.file.settings.order.new")) {
         myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground());
+        myProjectIcon.setIcon(selected ? AllIcons.General.ProjectConfigurableSelected : AllIcons.General.ProjectConfigurable);
         myProjectIcon.setVisible(true);
-        tree.setToolTipText(OptionsBundle.message(project.isDefault()
+        myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault()
                                                   ? "configurable.default.project.tooltip"
                                                   : "configurable.current.project.tooltip"));
       } else {
         myProjectIcon.setVisible(false);
-        tree.setToolTipText(null);
       }
       return result;
     }
 
-    private Project getConfigurableProject(SimpleNode node) {
-      if (node == null) {
-        return null;
-      }
-      if (node instanceof EditorNode) {
-        EditorNode editor = (EditorNode)node;
-        Configurable configurable = editor.getConfigurable();
-        if (configurable instanceof ConfigurableWrapper) {
-          ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
-          return wrapper.getExtensionPoint().getProject();
-        }
-      }
-      return getConfigurableProject(node.getParent());
-    }
-
     protected JComponent createItemComponent() {
       myTextLabel = new ErrorLabel();
       return myTextLabel;
@@ -642,6 +627,24 @@
     }
 
     @Override
+    public final String getToolTipText(MouseEvent event) {
+      if (event != null) {
+        Point point = event.getPoint();
+        Component component = getDeepestRendererComponentAt(point.x, point.y);
+        if (component instanceof JLabel) {
+          JLabel label = (JLabel)component;
+          if (label.getIcon() != null) {
+            String text = label.getToolTipText();
+            if (text != null) {
+              return text;
+            }
+          }
+        }
+      }
+      return super.getToolTipText(event);
+    }
+
+    @Override
     protected boolean paintNodes() {
       return false;
     }
@@ -877,4 +880,27 @@
 
     }
   }
+
+  Project getConfigurableProject(Configurable configurable) {
+    if (configurable instanceof ConfigurableWrapper) {
+      ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+      return wrapper.getExtensionPoint().getProject();
+    }
+    return getConfigurableProject(myConfigurable2Node.get(configurable));
+  }
+
+  private static Project getConfigurableProject(SimpleNode node) {
+    if (node == null) {
+      return null;
+    }
+    if (node instanceof EditorNode) {
+      EditorNode editor = (EditorNode)node;
+      Configurable configurable = editor.getConfigurable();
+      if (configurable instanceof ConfigurableWrapper) {
+        ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+        return wrapper.getExtensionPoint().getProject();
+      }
+    }
+    return getConfigurableProject(node.getParent());
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
index a393d93..27bb8eb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
@@ -56,7 +56,10 @@
   private final ScheduledFuture<?> myCheckCancelledFuture;
 
   public ProgressManagerImpl(Application application) {
-    if (/*!application.isUnitTestMode() && */!DISABLED) {
+    if (DISABLED) {
+      myCheckCancelledFuture = null;
+    }
+    else {
       myCheckCancelledFuture = JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
         @Override
         public void run() {
@@ -65,9 +68,6 @@
         }
       }, 0, 10, TimeUnit.MILLISECONDS);
     }
-    else {
-      myCheckCancelledFuture = null;
-    }
   }
 
   @Override
@@ -105,8 +105,8 @@
   private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection {
     private final ProgressIndicator myOld;
 
-    private NonCancelableIndicator(ProgressIndicator old) {
-      myOld = old;
+    private NonCancelableIndicator() {
+      myOld = myThreadIndicator.get();
     }
 
     @Override
@@ -124,16 +124,17 @@
     }
   }
 
+  @NotNull
   @Override
   public final NonCancelableSection startNonCancelableSection() {
-    NonCancelableIndicator nonCancelor = new NonCancelableIndicator(myThreadIndicator.get());
+    NonCancelableIndicator nonCancelor = new NonCancelableIndicator();
     myThreadIndicator.set(nonCancelor);
     return nonCancelor;
   }
 
   @Override
   public void executeNonCancelableSection(@NotNull Runnable runnable) {
-    executeProcessUnderProgress(runnable, new NonCancelableIndicator(getProgressIndicator()));
+    executeProcessUnderProgress(runnable, new NonCancelableIndicator());
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
index 6ffa084..d1abc08 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
@@ -49,6 +49,7 @@
 import com.intellij.ui.mac.foundation.Foundation;
 import com.intellij.ui.mac.foundation.ID;
 import com.intellij.ui.mac.foundation.MacUtil;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -59,7 +60,6 @@
 import java.awt.event.*;
 import java.awt.image.BufferStrategy;
 import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -887,18 +887,12 @@
 
       if (rootPane != null) { // Workaround for bug in native code to hold rootPane
         try {
-          Field field = rootPane.getClass().getDeclaredField("glassPane");
-          field.setAccessible(true);
-          field.set(rootPane, null);
+          ReflectionUtil.resetField(rootPane.getClass(), null, "glassPane");
+          ReflectionUtil.resetField(rootPane.getClass(), null, "contentPane");
 
-          field = rootPane.getClass().getDeclaredField("contentPane");
-          field.setAccessible(true);
-          field.set(rootPane, null);
           rootPane = null;
 
-          field = Window.class.getDeclaredField("windowListener");
-          field.setAccessible(true);
-          field.set(this, null);
+          ReflectionUtil.resetField(Window.class, null, "windowListener");
         }
         catch (Exception ignored) {
         }
@@ -906,9 +900,7 @@
 
       // http://bugs.sun.com/view_bug.do?bug_id=6614056
       try {
-        final Field field = Dialog.class.getDeclaredField("modalDialogs");
-        field.setAccessible(true);
-        final List<?> list = (List<?>)field.get(null);
+        final List<?> list = ReflectionUtil.getField(Dialog.class, null, null, "modalDialogs");
         list.remove(this);
       }
       catch (final Exception ignored) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
index b1f792c..354f89c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -617,12 +617,21 @@
     Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
       public void run() {
         try {
-          URL requestUrl = new URL(url);
-          if (!StandardFileSystems.FILE_PROTOCOL.equals(requestUrl.getProtocol())) {
-            HttpConfigurable.getInstance().prepareURL(url);
-            requestUrl = new URL(url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString());
+          final String urlToCheck;
+          if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
+            urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
+          } else {
+            urlToCheck = url;
           }
-          inputStreams[0] = requestUrl.openStream();
+
+          HttpURLConnection connection = ApplicationManager.getApplication() != null ?
+                                         HttpConfigurable.getInstance().openHttpConnection(urlToCheck) :
+                                         (HttpURLConnection)new URL(urlToCheck).openConnection();
+          connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+          connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+          connection.connect();
+
+          inputStreams[0] = connection.getInputStream();
         }
         catch (IOException e) {
           exception[0] = e;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
index 7177138..a2d32fd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
@@ -67,7 +67,9 @@
   @Override
   @NotNull
   public VirtualFile createChild(@NotNull VirtualFile parent, @NotNull String name, boolean isDirectory) {
-    return getRemoteFileManager().getOrCreateFile((VirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + '/' + name), parent.getPath() + '/' + name, isDirectory);
+    String parentPath = parent.getPath();
+    boolean hasEndSlash = parentPath.charAt(parentPath.length() - 1) == '/';
+    return getRemoteFileManager().getOrCreateFile((HttpVirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + (hasEndSlash ? "" : '/') + name), parentPath + (hasEndSlash ? "" : '/') + name, isDirectory);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
similarity index 94%
rename from platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
rename to platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
index ba49cfb..a8a1a44 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
@@ -35,7 +35,7 @@
 import java.io.OutputStream;
 import java.util.List;
 
-class VirtualFileImpl extends HttpVirtualFile {
+class HttpVirtualFileImpl extends HttpVirtualFile {
   private final HttpFileSystemBase myFileSystem;
   @Nullable private final RemoteFileInfoImpl myFileInfo;
   private FileType myInitialFileType;
@@ -45,7 +45,7 @@
 
   private List<VirtualFile> myChildren;
 
-  VirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable VirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
+  HttpVirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable HttpVirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
     if (parent != null) {
       if (parent.myChildren == null) {
         parent.myChildren = new SmartList<VirtualFile>();
@@ -63,7 +63,7 @@
           ApplicationManager.getApplication().invokeLater(new Runnable() {
             @Override
             public void run() {
-              VirtualFileImpl file = VirtualFileImpl.this;
+              HttpVirtualFileImpl file = HttpVirtualFileImpl.this;
               FileDocumentManager.getInstance().reloadFiles(file);
               if (!localFile.getFileType().equals(myInitialFileType)) {
                 FileContentUtilCore.reparseFiles(file);
@@ -135,8 +135,7 @@
 
   @Override
   public VirtualFile getParent() {
-    if (myParentPath == null) return null;
-    return myFileSystem.findFileByPath(myParentPath, true);
+    return myParentPath == null ? null : myFileSystem.findFileByPath(myParentPath, true);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
index b69c0be..904233a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
@@ -17,7 +17,6 @@
 
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener;
 import com.intellij.util.EventDispatcher;
@@ -35,7 +34,10 @@
  */
 public class RemoteFileManagerImpl extends RemoteFileManager implements Disposable {
   private final LocalFileStorage myStorage;
-  private final Map<Pair<Boolean, Url>, VirtualFileImpl> myRemoteFiles = new THashMap<Pair<Boolean, Url>, VirtualFileImpl>();
+
+  private final Map<Url, HttpVirtualFileImpl> remoteFiles = new THashMap<Url, HttpVirtualFileImpl>();
+  private final Map<Url, HttpVirtualFileImpl> remoteDirectories = new THashMap<Url, HttpVirtualFileImpl>();
+
   private final EventDispatcher<HttpVirtualFileListener> myDispatcher = EventDispatcher.create(HttpVirtualFileListener.class);
   private final List<RemoteContentProvider> myProviders = new ArrayList<RemoteContentProvider>();
   private final DefaultRemoteContentProvider myDefaultRemoteContentProvider;
@@ -55,19 +57,19 @@
     return myDefaultRemoteContentProvider;
   }
 
-  public synchronized VirtualFileImpl getOrCreateFile(@Nullable VirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
-    Pair<Boolean, Url> key = Pair.create(directory, url);
-    VirtualFileImpl file = myRemoteFiles.get(key);
+  public synchronized HttpVirtualFileImpl getOrCreateFile(@Nullable HttpVirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
+    Map<Url, HttpVirtualFileImpl> cache = directory ? remoteDirectories : remoteFiles;
+    HttpVirtualFileImpl file = cache.get(url);
     if (file == null) {
       if (directory) {
-        file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, null);
+        file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, null);
       }
       else {
         RemoteFileInfoImpl fileInfo = new RemoteFileInfoImpl(url, this);
-        file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
+        file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
         fileInfo.addDownloadingListener(new MyDownloadingListener(file));
       }
-      myRemoteFiles.put(key, file);
+      cache.put(url, file);
     }
     return file;
   }
@@ -133,9 +135,9 @@
   }
 
   private class MyDownloadingListener extends FileDownloadingAdapter {
-    private final VirtualFileImpl myFile;
+    private final HttpVirtualFileImpl myFile;
 
-    public MyDownloadingListener(final VirtualFileImpl file) {
+    public MyDownloadingListener(final HttpVirtualFileImpl file) {
       myFile = file;
     }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
index efaf84d..98c3884 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.ShutDownTracker;
 import com.intellij.openapi.util.io.FileAttributes;
 import com.intellij.openapi.util.io.FileSystemUtil;
 import com.intellij.openapi.util.io.FileUtil;
@@ -30,6 +31,7 @@
 import com.intellij.openapi.vfs.VfsBundle;
 import com.intellij.openapi.vfs.impl.ZipHandler;
 import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
+import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.EnumeratorStringDescriptor;
 import com.intellij.util.io.IOUtil;
@@ -169,7 +171,6 @@
 
       info = new CacheLibraryInfo(mirrorFile.getName(), originalAttributes.lastModified, originalAttributes.length);
       CacheLibraryInfo.ourCachedLibraryInfo.put(path, info);
-      CacheLibraryInfo.ourCachedLibraryInfo.force();
       return mirrorFile;
     }
     catch (IOException ex) {
@@ -260,6 +261,23 @@
       }
       assert info != null;
       ourCachedLibraryInfo = info;
+      FlushingDaemon.everyFiveSeconds(new Runnable() {
+        @Override
+        public void run() {
+          flushCachedLibraryInfos();
+        }
+      });
+
+      ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
+        @Override
+        public void run() {
+          flushCachedLibraryInfos();
+        }
+      });
+    }
+
+    private static void flushCachedLibraryInfos() {
+      if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force();
     }
 
     private CacheLibraryInfo(@NotNull String path, long time, long length) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
index ba44d2b..2ecb283 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,17 +19,15 @@
 import com.intellij.openapi.editor.impl.EditorComponentImpl;
 import com.intellij.openapi.fileEditor.impl.EditorWindowHolder;
 import com.intellij.openapi.util.Computable;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.text.JTextComponent;
 import java.awt.*;
-import java.lang.reflect.Field;
 
 public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy");
-  @NonNls private static final String FOCUS_TRAVERSAL_POLICY_FIELD = "focusTraversalPolicy";
 
   protected Component getDefaultComponentImpl(Container focusCycleRoot) {
     if (!(focusCycleRoot instanceof JComponent)) {
@@ -103,15 +101,7 @@
   }
 
   private static FocusTraversalPolicy getFocusTraversalPolicyAwtImpl(final JComponent component) {
-    try {
-      final Field field = Container.class.getDeclaredField(FOCUS_TRAVERSAL_POLICY_FIELD);
-      field.setAccessible(true);
-      return (FocusTraversalPolicy)field.get(component);
-    }
-    catch (Exception e) {
-      LOG.error(e);
-      return null;
-    }
+    return ReflectionUtil.getField(Container.class, component, FocusTraversalPolicy.class, "focusTraversalPolicy");
   }
 
   protected final boolean accept(final Component aComponent) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
index 83696e0..71f9645 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,8 +20,9 @@
 import com.intellij.ide.dnd.DnDAware;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.Divider;
 import com.intellij.openapi.ui.Painter;
-import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
 import com.intellij.openapi.ui.popup.Balloon;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
@@ -42,6 +43,8 @@
 
 public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEventQueue.EventDispatcher, Painter.Listener {
 
+  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.IdeGlassPaneImpl");
+
   private final List<EventListener> myMouseListeners = new ArrayList<EventListener>();
   private final Set<EventListener> mySortedMouseListeners = new TreeSet<EventListener>(new Comparator<EventListener>() {
     @Override
@@ -360,9 +363,12 @@
         }
         else {
           cursor = Cursor.getDefaultCursor();
-          getRootPane().setCursor(cursor);
-
-
+          JRootPane rootPane = getRootPane();
+          if (rootPane != null) {
+            rootPane.setCursor(cursor);
+          } else {
+            LOG.warn("Root pane is null. Event: " + e);
+          }
           restoreLastComponent(null);
           myLastOriginalCursor = null;
           myLastCursorComponent = null;
@@ -375,7 +381,7 @@
   private boolean canProcessCursorFor(Component target) {
     if (target instanceof JMenu ||
         target instanceof JMenuItem ||
-        target instanceof Splitter.Divider ||
+        target instanceof Divider ||
         target instanceof JSeparator ||
         (target instanceof JEditorPane && ((JEditorPane)target).getEditorKit() instanceof HTMLEditorKit)) {
       return false;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
index d6e1d99..8b78b16 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
@@ -27,9 +27,11 @@
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.DataProvider;
 import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.ui.popup.Balloon;
 import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.wm.*;
@@ -41,7 +43,7 @@
 import com.intellij.ui.content.ContentManager;
 import com.intellij.ui.content.ContentManagerListener;
 import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -50,12 +52,18 @@
 import java.awt.*;
 import java.awt.event.InputEvent;
 import java.beans.PropertyChangeListener;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.*;
 import java.util.List;
 
 @SuppressWarnings({"ConstantConditions"})
 public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
+  private final Map<String, ToolWindow> myToolWindows = new HashMap<String, ToolWindow>();
+  private final Project myProject;
+
+  public ToolWindowHeadlessManagerImpl(Project project) {
+    myProject = project;
+  }
+
   @Override
   public boolean canShowNotification(@NotNull String toolWindowId) {
     return false;
@@ -65,7 +73,184 @@
   public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) {
   }
 
-  public static final ToolWindow HEADLESS_WINDOW = new ToolWindowEx() {
+  private ToolWindow doRegisterToolWindow(final String id, @Nullable Disposable parentDisposable) {
+    MockToolWindow tw = new MockToolWindow(myProject);
+    myToolWindows.put(id, tw);
+    if (parentDisposable != null)  {
+      Disposer.register(parentDisposable, new Disposable() {
+        @Override
+        public void dispose() {
+          unregisterToolWindow(id);
+        }
+      });
+    }
+    return tw;
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull String id,
+                                       @NotNull JComponent component,
+                                       @NotNull ToolWindowAnchor anchor,
+                                       Disposable parentDisposable,
+                                       boolean canWorkInDumbMode) {
+    return doRegisterToolWindow(id, parentDisposable);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
+    return doRegisterToolWindow(id, null);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull String id,
+                                       @NotNull JComponent component,
+                                       @NotNull ToolWindowAnchor anchor,
+                                       Disposable parentDisposable,
+                                       boolean canWorkInDumbMode,
+                                       boolean canCloseContents) {
+    return doRegisterToolWindow(id, parentDisposable);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull String id,
+                                       @NotNull JComponent component,
+                                       @NotNull ToolWindowAnchor anchor,
+                                       Disposable parentDisposable) {
+    return doRegisterToolWindow(id, parentDisposable);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
+    return doRegisterToolWindow(id, null);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull final String id,
+                                       final boolean canCloseContent,
+                                       @NotNull final ToolWindowAnchor anchor,
+                                       final boolean secondary) {
+    return doRegisterToolWindow(id, null);
+  }
+
+  @Override
+  public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
+                                       final Disposable parentDisposable, final boolean dumbAware) {
+    return doRegisterToolWindow(id, parentDisposable);
+  }
+
+  @Override
+  public void unregisterToolWindow(@NotNull String id) {
+    myToolWindows.remove(id);
+  }
+
+  @Override
+  public void activateEditorComponent() {
+  }
+
+  @Override
+  public boolean isEditorComponentActive() {
+    return false;
+  }
+
+  @Override
+  public String[] getToolWindowIds() {
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
+  @Override
+  public String getActiveToolWindowId() {
+    return null;
+  }
+
+  @Override
+  public ToolWindow getToolWindow(String id) {
+    return myToolWindows.get(id);
+  }
+
+  @Override
+  public void invokeLater(Runnable runnable) {
+  }
+
+  @Override
+  public IdeFocusManager getFocusManager() {
+    return IdeFocusManagerHeadless.INSTANCE;
+  }
+
+  @Override
+  public void notifyByBalloon(@NotNull final String toolWindowId,
+                              @NotNull final MessageType type,
+                              @NotNull final String text,
+                              @Nullable final Icon icon,
+                              @Nullable final HyperlinkListener listener) {
+  }
+
+  @Override
+  public Balloon getToolWindowBalloon(String id) {
+    return null;
+  }
+
+  @Override
+  public void initToolWindow(ToolWindowEP bean) {
+
+  }
+
+  @Override
+  public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+
+  }
+
+  @Override
+  public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+  }
+
+  @Override
+  public String getLastActiveToolWindowId() {
+    return null;
+  }
+
+  @Override
+  public String getLastActiveToolWindowId(Condition<JComponent> condition) {
+    return null;
+  }
+
+  @Override
+  public DesktopLayout getLayout() {
+    return new DesktopLayout();
+  }
+
+  @Override
+  public void setLayoutToRestoreLater(DesktopLayout layout) {
+  }
+
+  @Override
+  public DesktopLayout getLayoutToRestoreLater() {
+    return new DesktopLayout();
+  }
+
+  @Override
+  public void setLayout(@NotNull DesktopLayout layout) {
+  }
+
+  @Override
+  public void clearSideStack() {
+  }
+
+  @Override
+  public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
+  }
+
+  @Override
+  public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
+    return new ArrayList<String>();
+  }
+
+  public static class MockToolWindow implements ToolWindowEx {
+    ContentManager myContentManager = new MockContentManager();
+
+    public MockToolWindow(@NotNull Project project) {
+      Disposer.register(project, myContentManager);
+    }
+
     @Override
     public boolean isActive() {
       return false;
@@ -206,7 +391,7 @@
 
     @Override
     public ContentManager getContentManager() {
-      return MOCK_CONTENT_MANAGER;
+      return myContentManager;
     }
 
     @Override
@@ -270,9 +455,9 @@
     public boolean isUseLastFocusedOnActivation() {
       return false;
     }
-  };
+  }
 
-  @NonNls private static final ContentManager MOCK_CONTENT_MANAGER = new ContentManager() {
+  private static class MockContentManager implements ContentManager {
     private final List<Content> myContents = new ArrayList<Content>();
     private Content mySelected;
 
@@ -284,15 +469,25 @@
 
     @Override
     public void addContent(@NotNull final Content content) {
+      myContents.add(content);
+      if (mySelected == null) mySelected = content;
     }
 
     @Override
     public void addContent(@NotNull Content content, int order) {
       myContents.add(order, content);
+      if (mySelected == null) mySelected = content;
     }
 
     @Override
     public void addContent(@NotNull final Content content, final Object constraints) {
+      addContent(content);
+    }
+
+    @Override
+    public void addSelectedContent(@NotNull final Content content) {
+      addContent(content);
+      setSelectedContent(content);
     }
 
     @Override
@@ -304,10 +499,6 @@
     }
 
     @Override
-    public void addSelectedContent(@NotNull final Content content) {
-    }
-
-    @Override
     public boolean canCloseAllContents() {
       return false;
     }
@@ -319,6 +510,9 @@
 
     @Override
     public Content findContent(final String displayName) {
+      for (Content each : myContents) {
+        if (each.getDisplayName().equals(displayName)) return each;
+      }
       return null;
     }
 
@@ -359,18 +553,24 @@
 
     @Override
     public Content getContent(final JComponent component) {
+      Content[] contents = getContents();
+      for (Content content : contents) {
+        if (Comparing.equal(component, content.getComponent())) {
+          return content;
+        }
+      }
       return null;
     }
 
     @Override
     @Nullable
     public Content getContent(final int index) {
-      return null;
+      return myContents.get(index);
     }
 
     @Override
     public int getContentCount() {
-      return 0;
+      return myContents.size();
     }
 
     @Override
@@ -381,7 +581,7 @@
 
     @Override
     public int getIndexOfContent(final Content content) {
-      return -1;
+      return myContents.indexOf(content);
     }
 
     @Override
@@ -393,35 +593,37 @@
     @Override
     @NotNull
     public Content[] getSelectedContents() {
-      return new Content[0];
+      return mySelected != null ? new Content[]{mySelected} : new Content[0];
     }
 
     @Override
     public boolean isSelected(@NotNull final Content content) {
-      return false;
+      return content == mySelected;
     }
 
     @Override
     public void removeAllContents(final boolean dispose) {
       for (int i = myContents.size() - 1; i >= 0; i--) {
         Content content = myContents.get(i);
-        removeContent(content, true);
+        removeContent(content, dispose);
       }
       mySelected = null;
     }
 
     @Override
     public boolean removeContent(@NotNull final Content content, final boolean dispose) {
-      Disposer.dispose(content);
+      if (dispose) Disposer.dispose(content);
+      boolean result = myContents.remove(content);
       if (mySelected == content) {
-        mySelected = null;
+        mySelected = ContainerUtil.getFirstItem(myContents);
       }
-      return myContents.remove(content);
+      return result;
     }
 
     @NotNull
     @Override
     public ActionCallback removeContent(@NotNull Content content, boolean dispose, boolean trackFocus, boolean implicitFocus) {
+      removeContent(content, dispose);
       return new ActionCallback.Done();
     }
 
@@ -451,33 +653,36 @@
     @NotNull
     @Override
     public ActionCallback setSelectedContentCB(@NotNull Content content) {
+      setSelectedContent(content);
       return new ActionCallback.Done();
     }
 
     @Override
     public void setSelectedContent(@NotNull final Content content, final boolean requestFocus) {
+      setSelectedContent(content);
     }
 
     @NotNull
     @Override
     public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus) {
-      return new ActionCallback.Done();
+      return setSelectedContentCB(content);
     }
 
     @Override
     public void setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus) {
+      setSelectedContent(content);
     }
 
     @NotNull
     @Override
     public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus, final boolean forcedFocus) {
-      return new ActionCallback.Done();
+      return setSelectedContentCB(content);
     }
 
     @NotNull
     @Override
     public ActionCallback setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus, boolean implicit) {
-      return new ActionCallback.Done();
+      return setSelectedContentCB(content);
     }
 
     @NotNull
@@ -506,161 +711,4 @@
     public ContentFactory getFactory() {
       return ServiceManager.getService(ContentFactory.class);
     }
-  };
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull String id,
-                                       @NotNull JComponent component,
-                                       @NotNull ToolWindowAnchor anchor,
-                                       Disposable parentDisposable,
-                                       boolean canWorkInDumbMode) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull String id,
-                                       @NotNull JComponent component,
-                                       @NotNull ToolWindowAnchor anchor,
-                                       Disposable parentDisposable,
-                                       boolean canWorkInDumbMode,
-                                       boolean canCloseContents) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull String id,
-                                       @NotNull JComponent component,
-                                       @NotNull ToolWindowAnchor anchor,
-                                       Disposable parentDisposable) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull final String id,
-                                       final boolean canCloseContent,
-                                       @NotNull final ToolWindowAnchor anchor,
-                                       final boolean secondary) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
-                                       final Disposable parentDisposable, final boolean dumbAware) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public void unregisterToolWindow(@NotNull String id) {
-  }
-
-  @Override
-  public void activateEditorComponent() {
-  }
-
-  @Override
-  public boolean isEditorComponentActive() {
-    return false;
-  }
-
-  @Override
-  public String[] getToolWindowIds() {
-    return ArrayUtil.EMPTY_STRING_ARRAY;
-  }
-
-  @Override
-  public String getActiveToolWindowId() {
-    return null;
-  }
-
-  @Override
-  public ToolWindow getToolWindow(String id) {
-    return HEADLESS_WINDOW;
-  }
-
-  @Override
-  public void invokeLater(Runnable runnable) {
-  }
-
-  @Override
-  public IdeFocusManager getFocusManager() {
-    return IdeFocusManagerHeadless.INSTANCE;
-  }
-
-  @Override
-  public void notifyByBalloon(@NotNull final String toolWindowId,
-                              @NotNull final MessageType type,
-                              @NotNull final String text,
-                              @Nullable final Icon icon,
-                              @Nullable final HyperlinkListener listener) {
-  }
-
-  @Override
-  public Balloon getToolWindowBalloon(String id) {
-    return null;
-  }
-
-  @Override
-  public void initToolWindow(ToolWindowEP bean) {
-
-  }
-
-  @Override
-  public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
-
-  }
-
-  @Override
-  public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
-  }
-
-  @Override
-  public String getLastActiveToolWindowId() {
-    return null;
-  }
-
-  @Override
-  public String getLastActiveToolWindowId(Condition<JComponent> condition) {
-    return null;
-  }
-
-  @Override
-  public DesktopLayout getLayout() {
-    return new DesktopLayout();
-  }
-
-  @Override
-  public void setLayoutToRestoreLater(DesktopLayout layout) {
-  }
-
-  @Override
-  public DesktopLayout getLayoutToRestoreLater() {
-    return new DesktopLayout();
-  }
-
-  @Override
-  public void setLayout(@NotNull DesktopLayout layout) {
-  }
-
-  @Override
-  public void clearSideStack() {
-  }
-
-  @Override
-  public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
-  }
-
-  @Override
-  public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
-    return new ArrayList<String>();
-  }
-}
+  }}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
index 6c6bcd1..120579b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -16,9 +16,11 @@
 package com.intellij.openapi.wm.impl;
 
 import com.intellij.Patches;
+import com.intellij.execution.util.ExecUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.IdeFrame;
 import com.intellij.openapi.wm.WindowManager;
 import org.jetbrains.annotations.Nullable;
@@ -29,6 +31,8 @@
 import java.awt.peer.ComponentPeer;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import static com.intellij.util.ArrayUtil.newLongArray;
 import static com.intellij.util.containers.ContainerUtil.newHashSet;
@@ -254,11 +258,17 @@
         setWM("MARCO_WM", "METACITY_WM");
       }
       else if ("awesome".equals(wmName)) {
-        setWM("SAWFISH_WM");
+        String version = getAwesomeWMVersion();
+        if (StringUtil.compareVersionNumbers(version, "3.5") >= 0) {
+          setWM("SAWFISH_WM");
+        }
+        else if (version != null) {
+          setWM("OTHER_NONREPARENTING_WM", "LG3D_WM");
+        }
       }
     }
-    catch (Throwable e) {
-      LOG.warn(e);
+    catch (Throwable t) {
+      LOG.warn(t);
     }
   }
 
@@ -273,6 +283,7 @@
           if (id != null) {
             field(xwmClass, "awt_wmgr").set(null, id);
             field(xwmClass, "WMID").set(xwm, id);
+            LOG.info("impersonated WM: " + wmConstant);
             break;
           }
         }
@@ -281,6 +292,23 @@
     }
   }
 
+  @Nullable
+  private static String getAwesomeWMVersion() {
+    try {
+      String version = ExecUtil.execAndReadLine("awesome", "--version");
+      if (version != null) {
+        Matcher m = Pattern.compile("awesome v([0-9.]+)").matcher(version);
+        if (m.find()) {
+          return m.group(1);
+        }
+      }
+    }
+    catch (Throwable t) {
+      LOG.warn(t);
+    }
+    return null;
+  }
+
   // full-screen support
 
   public static boolean isFullScreenSupported() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
index 7a772e7..2c68185 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -19,11 +19,13 @@
  */
 package com.intellij.openapi.wm.impl.commands;
 
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileEditor.impl.EditorWindow;
 import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
 import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
 import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Expirable;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.openapi.wm.impl.FloatingDecorator;
 import com.intellij.openapi.wm.impl.IdeFrameImpl;
@@ -44,10 +46,16 @@
   private final IdeFocusManager myFocusManager;
   private final Expirable myTimestamp;
 
+  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInEditorComponentCmd");
+
   public RequestFocusInEditorComponentCmd(@NotNull final EditorsSplitters splitters, IdeFocusManager
                                           focusManager, final Runnable finishCallBack, boolean forced){
     super(finishCallBack);
 
+    boolean shouldLogFocuses = Registry.is("ide.log.focuses");
+    if (shouldLogFocuses) {
+      LOG.info(new Exception());
+    }
     myComponent = null;
     final EditorWindow window = splitters.getCurrentWindow();
     if (window != null) {
@@ -94,7 +102,8 @@
       }
 
       if(myComponent != null){
-        myFocusManager.requestFocus(myComponent, myForced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
+        final boolean forced = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == null;
+        myFocusManager.requestFocus(myComponent, myForced || forced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
           public void run() {
             // if owner is active window or it has active child window which isn't floating decorator then
             // don't bring owner window to font. If we will make toFront every time then it's possible
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
index 9140fc2..82dba74 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -186,14 +186,11 @@
 
   private String getTitle2Text(ReopenProjectAction action, JComponent pathLabel) {
     String fullText = action.getProjectPath();
-    int labelWidth = pathLabel.getWidth();
     if (fullText == null || fullText.length() == 0) return " ";
 
-    String home = SystemProperties.getUserHome();
-    if (FileUtil.startsWith(fullText, home)) {
-      fullText = "~" + fullText.substring(home.length());
-    }
+    fullText = FileUtil.getLocationRelativeToUserHome(fullText, false);
 
+    int labelWidth = pathLabel.getWidth();
     if (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) {
       return myPathShortener.getShortPath(action);
     }
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
index e31b067..8d85ae1 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
@@ -116,11 +116,24 @@
     return new IllegalStateException("Unknown connection type"); //TODO
   }
 
-  public void copyTo(RemoteConnectionCredentialsWrapper copy) {
+  public void copyTo(final RemoteConnectionCredentialsWrapper copy) {
     copy.myCredentialsTypeHolder = new UserDataHolderBase();
-    copy.setPlainSshCredentials(getPlainSshCredentials());
-    copy.setVagrantConnectionType(getVagrantCredentials());
-    copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+    switchType(new RemoteSdkConnectionAcceptor() {
+      @Override
+      public void ssh(@NotNull RemoteCredentialsHolder cred) {
+        copy.setPlainSshCredentials(getPlainSshCredentials());
+      }
+
+      @Override
+      public void vagrant(@NotNull VagrantBasedCredentialsHolder cred) {
+        copy.setVagrantConnectionType(getVagrantCredentials());
+      }
+
+      @Override
+      public void deployment(@NotNull WebDeploymentCredentialsHolder cred) {
+        copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+      }
+    });
   }
 
   public String getId() {
diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
index a5ebae6..9e2b60a 100644
--- a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
+++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
@@ -21,6 +21,7 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -43,6 +44,10 @@
   @NotNull
   public abstract RemoteCredentials getVagrantSettings(@NotNull Project project, String vagrantFolder);
 
+  public abstract void getVagrantSettingsAsync(@Nullable Project project,
+                                               @NotNull String vagrantFolder,
+                                               @NotNull Consumer<RemoteCredentials> onSuccess);
+
   @NotNull
   public abstract RemoteCredentials getCredentials(@NotNull String folder) throws IOException;
 
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index 4e65063..d8b204c 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -223,6 +223,7 @@
     if (selected == null
         || !myComponent.isEnabled()
         || !myComponent.isShowing()
+        || !myComponent.getVisibleRect().intersects(getVisibleRect(selected))
         || !myComponent.isFocusOwner() && !processIfUnfocused
         || isPopup()) {
       hideHint();
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index 50a7ebb..2a7d44d 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
@@ -29,6 +29,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.util.PlatformUtils;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -38,7 +39,6 @@
 import java.awt.*;
 import java.io.File;
 import java.io.InputStream;
-import java.lang.reflect.Field;
 import java.net.URL;
 import java.util.List;
 import java.util.Locale;
@@ -111,9 +111,7 @@
       final Toolkit toolkit = Toolkit.getDefaultToolkit();
       final Class<? extends Toolkit> aClass = toolkit.getClass();
       if ("sun.awt.X11.XToolkit".equals(aClass.getName())) {
-        final Field awtAppClassName = aClass.getDeclaredField("awtAppClassName");
-        awtAppClassName.setAccessible(true);
-        awtAppClassName.set(toolkit, getFrameClass());
+        ReflectionUtil.setField(aClass, toolkit, null, "awtAppClassName", getFrameClass());
       }
     }
     catch (Exception ignore) { }
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index c6c209e..513d5ce 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
@@ -200,8 +200,7 @@
     if (cmp == myCloseRec) return true;
     if (UIUtil.isDescendingFrom(cmp, myComp)) return true;
     if (myComp == null || !myComp.isShowing()) return false;
-    Rectangle rectangleOnScreen = new Rectangle(myComp.getLocationOnScreen(), myComp.getSize());
-    return rectangleOnScreen.contains(target.getScreenPoint());
+    return myComp.contains(target.getScreenPoint().x, target.getScreenPoint().y);
   }
 
   public boolean isMovingForward(RelativePoint target) {
@@ -614,7 +613,7 @@
     myComp.setBorder(new EmptyBorder(borderSize, borderSize, borderSize, borderSize));
 
     myLayeredPane.add(myComp);
-    myLayeredPane.setLayer(myComp, getLayer());
+    myLayeredPane.setLayer(myComp, getLayer(), 0); // the second balloon must be over the first one
     myPosition.updateBounds(this);
     if (myBlockClicks) {
       myComp.addMouseListener(new MouseAdapter() {
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
index c91be65..1443a93 100644
--- a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
@@ -15,8 +15,6 @@
  */
 package com.intellij.ui;
 
-import java.awt.event.KeyEvent;
-
 /**
  * User: lex
  * Date: Sep 18, 2003
@@ -56,11 +54,4 @@
   protected void installSpeedSearch() {
     new TreeSpeedSearch(this);
   }
-
-
-  protected boolean isToggleEvent(KeyEvent e) {
-    return super.isToggleEvent(e) &&  !SpeedSearchBase.hasActiveSpeedSearch(this);
-  }
-
-
 }
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
new file mode 100644
index 0000000..369dd0c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ui;
+
+import com.intellij.ui.dualView.TreeTableView;
+import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.EventDispatcher;
+import com.intellij.util.ui.ColumnInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class CheckboxTreeTable extends TreeTableView {
+  private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
+
+  public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
+    super(new ListTreeTableModelOnColumns(root, columns));
+    final TreeTableTree tree = getTree();
+    myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
+    CheckboxTreeHelper helper = new CheckboxTreeHelper(CheckboxTreeHelper.DEFAULT_POLICY, myEventDispatcher);
+    helper.initTree(tree, this, renderer);
+    tree.setSelectionRow(0);
+  }
+
+  public void addCheckboxTreeListener(@NotNull CheckboxTreeListener listener) {
+    myEventDispatcher.addListener(listener);
+  }
+
+  public <T> T[] getCheckedNodes(final Class<T> nodeType) {
+    return CheckboxTreeHelper.getCheckedNodes(nodeType, null, getTree().getModel());
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
index 39c8aaf..d5fc8dc 100644
--- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,8 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.ui.tabs.*;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
+import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.intellij.ui.tabs.impl.TabLabel;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,45 @@
   private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
 
   public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) {
-    myTabs = new JBTabsImpl(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent);
+    myTabs = new JBEditorTabs(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent) {
+      @Override
+      public boolean isAlphabeticalMode() {
+        return false;
+      }
+
+      @Override
+      protected void doPaintBackground(Graphics2D g2d, Rectangle clip) {
+        super.doPaintBackground(g2d, clip);
+        if (getTabsPosition() == JBTabsPosition.top && isSingleRow()) {
+          int maxOffset = 0;
+          int maxLength = 0;
+
+          for (int i = getVisibleInfos().size() - 1; i >= 0; i--) {
+            TabInfo visibleInfo = getVisibleInfos().get(i);
+            TabLabel tabLabel = myInfo2Label.get(visibleInfo);
+            Rectangle r = tabLabel.getBounds();
+            if (r.width == 0 || r.height == 0) continue;
+            maxOffset = r.x + r.width;
+            maxLength = r.height;
+            break;
+          }
+
+          maxOffset++;
+          g2d.setPaint(UIUtil.getPanelBackground());
+          g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+          g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground()));
+          g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+          g2d.setPaint(UIUtil.getPanelBackground());
+          g2d.drawLine(clip.x, clip.y + maxLength, clip.width, clip.y + maxLength);
+        }
+      }
+
+      @Override
+      protected void paintSelectionAndBorder(Graphics2D g2d) {
+        super.paintSelectionAndBorder(g2d);
+      }
+    };
+
     myTabs.addListener(new TabsListener.Adapter() {
       @Override
       public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
diff --git a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
index 99c41b5..e219b77 100644
--- a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
+++ b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
 package com.intellij.ui;
 
 import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.Divider;
 import com.intellij.openapi.ui.PseudoSplitter;
 import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.vcs.changes.RefreshablePanel;
@@ -41,7 +42,7 @@
   private final boolean myVertical;
   private final OnOffListener<Integer> myListener;
   private final JPanel myFictivePanel;
-  private Splitter.Divider mySuperDivider;
+  private Splitter.DividerImpl mySuperDivider;
   private float myPreviousProportion;
 
   public SplitterWithSecondHideable(final boolean vertical,
@@ -185,7 +186,7 @@
         return vertical ? myTitledSeparator.getHeight() : myTitledSeparator.getWidth();
       }
 
-      class MyDivider extends Divider {
+      class MyDivider extends DividerImpl {
         @Override
         public void processMouseMotionEvent(MouseEvent e) {
           super.processMouseMotionEvent(e);
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
index 78802cc..e50403a 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
@@ -162,6 +162,25 @@
   private UiActivity myActivityKey;
   private Disposable myProjectDisposable;
 
+  private volatile State myState = State.NEW;
+
+  private enum State {NEW, INIT, SHOWING, SHOWN, CANCEL, DISPOSE}
+
+  private void debugState(String message, State... states) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug(hashCode() + " - " + message);
+      if (!ApplicationManager.getApplication().isDispatchThread()) {
+        LOG.debug("unexpected thread");
+      }
+      for (State state : states) {
+        if (state == myState) {
+          return;
+        }
+      }
+      LOG.debug(new IllegalStateException("myState=" + myState));
+    }
+  }
+
   AbstractPopup() { }
 
   AbstractPopup init(Project project,
@@ -302,6 +321,8 @@
     }
 
     myKeyEventHandler = keyEventHandler;
+    debugState("popup initialized", State.NEW);
+    myState = State.INIT;
     return this;
   }
 
@@ -582,10 +603,18 @@
 
   @Override
   public void cancel(InputEvent e) {
+    if (myState == State.CANCEL || myState == State.DISPOSE) {
+      return;
+    }
+    debugState("cancel popup", State.SHOWN);
+    myState = State.CANCEL;
+
     if (isDisposed()) return;
 
     if (myPopup != null) {
       if (!canClose()) {
+        debugState("cannot cancel popup", State.CANCEL);
+        myState = State.SHOWN;
         return;
       }
       storeDimensionSize(myContent.getSize());
@@ -610,8 +639,13 @@
       }
 
       if (myInStack) {
-        myFocusTrackback.setForcedRestore(!myOk && myFocusable);
-        myFocusTrackback.restoreFocus();
+        if (myFocusTrackback != null) {
+          myFocusTrackback.setForcedRestore(!myOk && myFocusable);
+          myFocusTrackback.restoreFocus();
+        }
+        else if (LOG.isDebugEnabled()) {
+          LOG.debug("cancel before show @ " + Thread.currentThread());
+        }
       }
 
 
@@ -664,6 +698,9 @@
 
     assert ApplicationManager.getApplication().isDispatchThread();
 
+    debugState("show popup", State.INIT);
+    myState = State.SHOWING;
+
     installWindowHook(this);
     installProjectDisposer();
     addActivity();
@@ -673,6 +710,8 @@
     final boolean shouldShow = beforeShow();
     if (!shouldShow) {
       removeActivity();
+      debugState("rejected to show popup", State.SHOWING);
+      myState = State.INIT;
       return;
     }
 
@@ -758,10 +797,11 @@
     PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog);
     myNativePopup = factory.isNativePopup();
     Component popupOwner = myOwner;
-    if (popupOwner instanceof RootPaneContainer) {
+    if (popupOwner instanceof RootPaneContainer && !(popupOwner instanceof IdeFrame && !Registry.is("popup.fix.ide.frame.owner"))) {
       // JDK uses cached heavyweight popup for a window ancestor
       RootPaneContainer root = (RootPaneContainer)popupOwner;
       popupOwner = root.getRootPane();
+      LOG.debug("popup owner fixed for JDK cache");
     }
     if (LOG.isDebugEnabled()) {
       LOG.debug("expected preferred size: " + myContent.getPreferredSize());
@@ -957,6 +997,8 @@
         }
       });
     }
+    debugState("popup shown", State.SHOWING);
+    myState = State.SHOWN;
   }
 
   public void focusPreferredComponent() {
@@ -1232,6 +1274,16 @@
 
   @Override
   public void dispose() {
+    if (myState == State.SHOWN) {
+      LOG.debug("shown popup must be cancelled");
+      cancel();
+    }
+    if (myState == State.DISPOSE) {
+      return;
+    }
+    debugState("dispose popup", State.INIT, State.CANCEL);
+    myState = State.DISPOSE;
+
     if (myDisposed) {
       return;
     }
@@ -1480,8 +1532,8 @@
   @Override
   public Dimension getSize() {
     if (myPopup != null) {
-      final Window popupWindow = SwingUtilities.windowForComponent(myContent);
-      return popupWindow.getSize();
+      final Window popupWindow = getContentWindow(myContent);
+      return (popupWindow == null) ? myForcedSize : popupWindow.getSize();
     } else {
       return myForcedSize;
     }
@@ -1491,7 +1543,8 @@
   public void moveToFitScreen() {
     if (myPopup == null) return;
 
-    final Window popupWindow = SwingUtilities.windowForComponent(myContent);
+    final Window popupWindow = getContentWindow(myContent);
+    if (popupWindow == null) return;
     Rectangle bounds = popupWindow.getBounds();
 
     ScreenUtil.moveRectangleToFitTheScreen(bounds);
@@ -1501,7 +1554,8 @@
 
 
   public static Window setSize(JComponent content, final Dimension size) {
-    final Window popupWindow = SwingUtilities.windowForComponent(content);
+    final Window popupWindow = getContentWindow(content);
+    if (popupWindow == null) return null;
     Insets insets = content.getInsets();
     if (insets != null) {
       size.width += insets.left + insets.right;
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
new file mode 100644
index 0000000..2a79368
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package com.intellij.ui.popup;
+
+import com.intellij.openapi.util.registry.Registry;
+
+import javax.swing.Popup;
+import java.awt.Component;
+import java.awt.GraphicsEnvironment;
+
+/**
+ * @author Sergey Malenkov
+ */
+public final class OurHeavyWeightPopup extends Popup {
+  public OurHeavyWeightPopup(Component owner, Component content, int x, int y) {
+    super(owner, content, x, y);
+  }
+
+  public static boolean isEnabled() {
+    return !GraphicsEnvironment.isHeadless() && Registry.is("our.heavy.weight.popup");
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
index 3017585..1670491 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -58,6 +58,9 @@
 
     class AwtHeavyweight implements Factory {
       public PopupComponent getPopup(Component owner, Component content, int x, int y, JBPopup jbPopup) {
+        if (OurHeavyWeightPopup.isEnabled()) {
+          return new AwtPopupWrapper(new OurHeavyWeightPopup(owner, content, x, y), jbPopup);
+        }
         final PopupFactory factory = PopupFactory.getSharedInstance();
 
         final int oldType = PopupUtil.getPopupType(factory);
@@ -172,7 +175,7 @@
       myJBPopup = jbPopup;
 
       if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) {
-        final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+        final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
         c.setBackground(UIUtil.getPanelBackground());
       }
     }
@@ -220,7 +223,7 @@
     }
 
     public Window getWindow() {
-      final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+      final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
       return c instanceof JWindow ? (JWindow)c : null;
     }
 
diff --git a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
index ac4c1b1..35719ca 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
 package com.intellij.util.ui;
 
 import com.intellij.ide.BrowserUtil;
@@ -48,7 +63,7 @@
    * stacked vertically each on another in a given order.
    *
    * @param childAlignmentX Component.LEFT_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.RIGHT_ALIGNMENT
-   * @param children children components
+   * @param children        children components
    * @return created panel
    */
   @NotNull
@@ -76,7 +91,7 @@
    * stacked each on another in a given order.
    *
    * @param childAlignmentY Component.TOP_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.BOTTOM_ALIGNMENT
-   * @param children children components
+   * @param children        children components
    * @return created panel
    */
   @NotNull
@@ -98,10 +113,11 @@
     for (Component child : children) {
       panel.add(child, childAlignment);
       if (child instanceof JComponent) {
-        JComponent jChild = (JComponent) child;
+        JComponent jChild = (JComponent)child;
         if (verticalOrientation) {
           jChild.setAlignmentX(childAlignment);
-        } else {
+        }
+        else {
           jChild.setAlignmentY(childAlignment);
         }
       }
@@ -259,20 +275,7 @@
     textFieldWithHistory.addPopupMenuListener(new PopupMenuListener() {
       @Override
       public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-        List<String> newHistory = historyProvider.produce();
-        Set<String> newHistorySet = ContainerUtil.newHashSet(newHistory);
-        List<String> oldHistory = textFieldWithHistory.getHistory();
-        List<String> mergedHistory = ContainerUtil.newArrayList();
-        for (String item : oldHistory) {
-          if (!newHistorySet.contains(item)) {
-            mergedHistory.add(item);
-          }
-        }
-        mergedHistory.addAll(newHistory);
-        textFieldWithHistory.setHistory(mergedHistory);
-
-        setLongestAsPrototype(textFieldWithHistory, mergedHistory);
-
+        setHistory(textFieldWithHistory, historyProvider.produce(), true);
         // one-time initialization
         textFieldWithHistory.removePopupMenuListener(this);
       }
@@ -287,11 +290,35 @@
     });
   }
 
+  public static void setHistory(@NotNull TextFieldWithHistory textFieldWithHistory,
+                                @NotNull List<String> history,
+                                boolean mergeWithPrevHistory) {
+    Set<String> newHistorySet = ContainerUtil.newHashSet(history);
+    List<String> prevHistory = textFieldWithHistory.getHistory();
+    List<String> mergedHistory = ContainerUtil.newArrayList();
+    if (mergeWithPrevHistory) {
+      for (String item : prevHistory) {
+        if (!newHistorySet.contains(item)) {
+          mergedHistory.add(item);
+        }
+      }
+    }
+    else {
+      String currentText = textFieldWithHistory.getText();
+      if (StringUtil.isNotEmpty(currentText) && !newHistorySet.contains(currentText)) {
+        mergedHistory.add(currentText);
+      }
+    }
+    mergedHistory.addAll(history);
+    textFieldWithHistory.setHistory(mergedHistory);
+    setLongestAsPrototype(textFieldWithHistory, mergedHistory);
+  }
+
   private static void setLongestAsPrototype(@NotNull JComboBox comboBox, @NotNull List<String> variants) {
     Object prototypeDisplayValue = comboBox.getPrototypeDisplayValue();
     String prototypeDisplayValueStr = null;
     if (prototypeDisplayValue instanceof String) {
-      prototypeDisplayValueStr = (String) prototypeDisplayValue;
+      prototypeDisplayValueStr = (String)prototypeDisplayValue;
     }
     else if (prototypeDisplayValue != null) {
       return;
@@ -413,15 +440,38 @@
     return textPane;
   }
 
-  public static void setHtml(@NotNull JEditorPane editorPane, @NotNull String bodyInnerHtml) {
+  public static void setHtml(@NotNull JEditorPane editorPane,
+                             @NotNull String bodyInnerHtml,
+                             @Nullable Color foregroundColor) {
     String html = String.format(
       "<html><head>%s</head><body>%s</body></html>",
-      UIUtil.getCssFontDeclaration(editorPane.getFont(), null, null, null),
+      UIUtil.getCssFontDeclaration(editorPane.getFont(), foregroundColor, null, null),
       bodyInnerHtml
     );
     editorPane.setText(html);
   }
 
+  @NotNull
+  public static TextFieldWithHistoryWithBrowseButton createTextFieldWithHistoryWithBrowseButton(@Nullable Project project,
+                                                                                                @NotNull String browseDialogTitle,
+                                                                                                @NotNull FileChooserDescriptor fileChooserDescriptor,
+                                                                                                @Nullable NotNullProducer<List<String>> historyProvider) {
+    TextFieldWithHistoryWithBrowseButton textFieldWithHistoryWithBrowseButton = new TextFieldWithHistoryWithBrowseButton();
+    TextFieldWithHistory textFieldWithHistory = textFieldWithHistoryWithBrowseButton.getChildComponent();
+    textFieldWithHistory.setHistorySize(-1);
+    textFieldWithHistory.setMinimumAndPreferredWidth(0);
+    if (historyProvider != null) {
+      addHistoryOnExpansion(textFieldWithHistory, historyProvider);
+    }
+    installFileCompletionAndBrowseDialog(
+      project,
+      textFieldWithHistoryWithBrowseButton,
+      browseDialogTitle,
+      fileChooserDescriptor
+    );
+    return textFieldWithHistoryWithBrowseButton;
+  }
+
   private static class CopyLinkAction extends AnAction {
 
     private final String myUrl;
diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
index a7d09ab..7310b93 100644
--- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
+++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
@@ -170,7 +170,7 @@
 
     @Override
     protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException {
-      return (request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS) &&
+      return (request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS) &&
              XmlRpcServer.SERVICE.getInstance().process(urlDecoder.path(), request, context, handlers);
     }
   }
diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
index 3f88327..1dbf577 100644
--- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
@@ -113,7 +113,7 @@
             @Override
             public void write(ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception {
               if (message instanceof HttpResponse) {
-//                BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
+                //BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
                 HttpResponse response = (HttpResponse)message;
                 BuiltInServer.LOG.debug("OUT HTTP: " + response.status().code() + " " + response.headers().get(CONTENT_TYPE));
               }
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 1c05af2..47c4cef 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -596,6 +596,8 @@
 action.MemberPushDown.description=Push class members down to directly inheriting subclasses
 action.InheritanceToDelegation.text=Replace _Inheritance with Delegation...
 action.InheritanceToDelegation.description=Replace inheritance with delegation
+action.RenameFile.text=Rename File...
+action.RenameFile.description=Rename selected file
 action.Inline.text=I_nline...
 action.Inline.description=Inline the selected method or variable
 action.AnonymousToInner.text=Convert Anon_ymous to Inner...
@@ -1014,8 +1016,8 @@
 action.Vcs.ShowDiffAction.description=Show changes
 action.Vcs.RollbackChanges.text=Rollback Changes
 action.Vcs.RollbackChanges.description=Rollback changes
-action.RollbackLineStatusChanges.text=Rollback
-action.RollbackLineStatusChanges.description=Rollback selected local changes
+action.Vcs.RollbackChangedLines.text=Rollback
+action.Vcs.RollbackChangedLines.description=Rollback changes in selected lines
 action.Vcs.EditSourceAction.text=Edit Source
 action.Vcs.EditSourceAction.description=Edit source
 action.Vcs.ExcludeAction.text=Exclude from Commit
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index bbd737a..5d53935 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -360,6 +360,7 @@
 checkbox.show.code.folding.outline=Show code folding outline
 group.tab.appearance=Tab Appearance
 editbox.tab.limit=Tab limit:
+editbox.tab.title.limit=Tab title limit:
 combobox.editor.tab.placement=Placement:
 checkbox.editor.tabs.in.single.row=Show tabs in single row
 checkbox.editor.tabs.show.close.button=Show "close" button on editor tabs
diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties
index 46750d5..1fbbd0a 100644
--- a/platform/platform-resources-en/src/messages/CommonBundle.properties
+++ b/platform/platform-resources-en/src/messages/CommonBundle.properties
@@ -31,7 +31,6 @@
 action.help=Help
 action.rerun=Rerun
 button.reset=&Reset
-button.reset.to.default=&Reset to Default
 button.delete=Delete
 button.copy=Copy...
 button.close=&Close
diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties
index 598cc97..aafd688 100644
--- a/platform/platform-resources-en/src/messages/DiffBundle.properties
+++ b/platform/platform-resources-en/src/messages/DiffBundle.properties
@@ -67,6 +67,8 @@
 merge.partial.diff.action.name.1.2=Compare middle and right panel contents
 merge.dialog.exit.without.applying.changes.confirmation.message=Are you sure you want to exit without applying changes?
 cancel.visual.merge.dialog.title=Cancel Visual Merge
+merge.dialog.apply.partially.resolved.changes.confirmation.message=There are {0, choice, 0#|1#one change|2#{0, number} changes}{0, choice, 0#|1#'{1, choice, 0#|1# and }'}{1, choice, 0#|1#one conflict|2#{1, number} conflicts} left unprocessed.\nAre you sure you want to save changes and finish merging?
+apply.partially.resolved.merge.dialog.title=Apply Changes
 merge.all.changes.have.processed.save.and.finish.confirmation.text=All changes have been processed.\nWould you like to save changes and finish merging?
 all.changes.processed.dialog.title=All Changes Processed
 merge.save.and.finish.button=Save and &Finish
diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties
index 293d013..8a857db 100644
--- a/platform/platform-resources-en/src/messages/FindBundle.properties
+++ b/platform/platform-resources-en/src/messages/FindBundle.properties
@@ -29,6 +29,7 @@
 find.options.group=Options
 find.options.search.for.text.occurences.checkbox=Search for text &occurrences
 find.options.skip.results.tab.with.one.usage.checkbox=S&kip results tab with one usage
+find.options.skip.results.tab.with.one.occurrence.checkbox=S&kip results tab when only one occurrence is found
 find.options.include.overloaded.methods.checkbox=Include o&verloaded methods
 find.scope.label=&Scope
 find.searched.elements.have.been.changed.error=Searched elements have been changed.\nCannot search for usages.
@@ -69,6 +70,14 @@
 find.replace.with.label=Replace &with:
 find.filter.file.name.group=File name filter
 find.filter.file.mask.checkbox=File m&ask(s)
+find.context.combo.label=Conte&xt: 
+find.context.anywhere.scope.label=anywhere
+find.context.in.comments.scope.label=in comments
+find.context.in.literals.scope.label=in string literals
+find.context.except.literals.scope.label=except string literals
+find.context.except.comments.scope.label=except comments
+find.context.except.comments.and.literals.scope.label=except comments and string literals
+
 find.directory.not.found.error=Directory {0} is not found
 find.invalid.regular.expression.error=Bad pattern \"{0}\": {1}
 find.empty.match.regular.expression.error=Regular expression matches empty string
diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties
index 3d34252..573cff8 100644
--- a/platform/platform-resources-en/src/messages/VcsBundle.properties
+++ b/platform/platform-resources-en/src/messages/VcsBundle.properties
@@ -308,7 +308,7 @@
 changes.action.rollback.nothing=Nothing to {0}
 changes.dialog.editchangelist.error.already.exists=A changelist named ''{0}'' already exists
 error.adding.files.prompt=The following problems have occurred when adding the files:
-error.adding.files.title=Error adding files
+error.adding.files.title=Error Adding Files
 column.name.revision.list.committer=User
 column.name.revision.list.number=Number
 column.name.revision.list.description=Description
diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
index 878c814..058e446 100644
--- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
+++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
@@ -3,6 +3,8 @@
 debugger.configurable.display.name=Debugger
 debugger.dataViews.display.name=Data Views
 debugger.stepping.display.name=Stepping
+# suppress inspection "UnusedProperty"
+debugger.hotswap.display.name=HotSwap
 
 xdebugger.default.content.title=Debug
 xdebugger.debugger.tab.title=Debugger
diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties
index 70e26de..7343727 100644
--- a/platform/platform-resources-en/src/messages/XmlBundle.properties
+++ b/platform/platform-resources-en/src/messages/XmlBundle.properties
@@ -233,3 +233,6 @@
 
 javascript.debugger.settings.choose.file.title=Select
 javascript.debugger.settings.choose.file.subtitle=Select file to debug JavaScript in
+
+setting.value.builtin.server.port.label=Built-in server &port:
+setting.value.can.accept.external.connections=Can accept &external connections
\ No newline at end of file
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index 1f40bac..7aa76ab 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -57,6 +57,9 @@
     <applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
                         serviceImplementation="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter" />
 
+    <applicationService serviceInterface="com.intellij.openapi.editor.EditorCopyPasteHelper"
+                        serviceImplementation="com.intellij.openapi.editor.impl.EditorCopyPasteHelperImpl" />
+
     <applicationService serviceImplementation="com.intellij.openapi.options.ex.IdeConfigurablesGroup"/>
 
     <applicationService serviceInterface="com.intellij.diagnostic.ErrorReportConfigurable"
@@ -190,7 +193,8 @@
     <projectService serviceInterface="com.intellij.openapi.vcs.VcsFileListenerContextHelper"
                     serviceImplementation="com.intellij.openapi.vcs.VcsFileListenerContextHelper"/>
 
-    <projectService serviceImplementation="com.intellij.openapi.editor.LazyRangeMarkerFactory"/>
+    <projectService serviceInterface="com.intellij.openapi.editor.LazyRangeMarkerFactory"
+                    serviceImplementation="com.intellij.openapi.editor.impl.LazyRangeMarkerFactoryImpl"/>
 
     <!-- General -->
     <applicationConfigurable groupId="appearance" key="title.general" bundle="messages.IdeBundle" id="preferences.general" instance="com.intellij.ide.GeneralSettingsConfigurable"/>
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index 9a737df..525ea3c 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -89,6 +89,10 @@
     </extensionPoint>
 
     <extensionPoint name="xml.undefinedElementFixProvider" interface="com.intellij.xml.XmlUndefinedElementFixProvider"/>
+
+    <extensionPoint qualifiedName="org.jetbrains.webServerPathHandler" interface="org.jetbrains.builtInWebServer.WebServerPathHandler"/>
+    <extensionPoint qualifiedName="org.jetbrains.webServerFileHandler" interface="org.jetbrains.builtInWebServer.WebServerFileHandler"/>
+    <extensionPoint qualifiedName="org.jetbrains.webServerRootsProvider" interface="org.jetbrains.builtInWebServer.WebServerRootsProvider"/>
   </extensionPoints>
 
   <project-components>
@@ -530,8 +534,21 @@
     <applicationConfigurable groupId="tools" instance="com.intellij.ide.browsers.BrowserSettings" id="reference.settings.ide.settings.web.browsers"
                              key="browsers.settings" bundle="messages.IdeBundle"/>
     <lang.inspectionSuppressor language="XML" implementationClass="com.intellij.codeInspection.XmlInspectionSuppressor"/>
+
+    <httpRequestHandler implementation="org.jetbrains.builtInWebServer.BuiltInWebServer"/>
+    <webBrowserUrlProvider implementation="org.jetbrains.builtInWebServer.BuiltInWebBrowserUrlProvider"/>
+
+    <customPortServerManager implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$MyCustomPortServerManager"/>
+    <xdebugger.configurableProvider implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$BuiltInServerDebuggerConfigurableProvider"/>
+
+    <exportable serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
+    <applicationService serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions" serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
+    <projectService serviceInterface="org.jetbrains.builtInWebServer.WebServerPathToFileManager" serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
   </extensions>
   <extensions defaultExtensionNs="org.jetbrains">
     <urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
+    <webServerPathHandler implementation="org.jetbrains.builtInWebServer.DefaultWebServerPathHandler"/>
+    <webServerFileHandler implementation="org.jetbrains.builtInWebServer.BuiltInWebServer$StaticFileHandler" order="last"/>
+    <webServerRootsProvider implementation="org.jetbrains.builtInWebServer.DefaultWebServerRootsProvider"/>
   </extensions>
 </idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml
index 68111b8..4b03978 100644
--- a/platform/platform-resources/src/META-INF/xdebugger.xml
+++ b/platform/platform-resources/src/META-INF/xdebugger.xml
@@ -10,6 +10,7 @@
     <extensionPoint name="xdebugger.settings" interface="com.intellij.xdebugger.settings.XDebuggerSettings"/>
     <extensionPoint name="xdebugger.breakpointType" interface="com.intellij.xdebugger.breakpoints.XBreakpointType"/>
     <extensionPoint name="xdebugger.debuggerSupport" interface="com.intellij.xdebugger.impl.DebuggerSupport"/>
+    <extensionPoint name="xdebugger.configurableProvider" interface="com.intellij.xdebugger.settings.DebuggerConfigurableProvider"/>
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij">
@@ -29,11 +30,12 @@
     <projectService serviceInterface="com.intellij.xdebugger.impl.XDebuggerHistoryManager"
                     serviceImplementation="com.intellij.xdebugger.impl.XDebuggerHistoryManager"/>
 
-    <applicationConfigurable groupId="build" dynamic="true" key="debugger.configurable.display.name" bundle="messages.XDebuggerBundle" provider="com.intellij.xdebugger.impl.settings.DebuggerConfigurableProvider"/>
+    <applicationConfigurable groupId="build" dynamic="true" key="debugger.configurable.display.name" bundle="messages.XDebuggerBundle" instance="com.intellij.xdebugger.impl.settings.DebuggerConfigurable"/>
 
     <customizableActionGroupProvider implementation="com.intellij.xdebugger.impl.ui.XDebugTabCustomizableActionGroupProvider"/>
 
     <xdebugger.debuggerSupport implementation="com.intellij.xdebugger.impl.XDebuggerSupport" order="first"/>
+    <xdebugger.configurableProvider implementation="com.intellij.xdebugger.impl.settings.XDebuggerConfigurableProvider" order="first"/>
 
     <executor implementation="com.intellij.execution.executors.DefaultDebugExecutor" order="first,after run"/>
   </extensions>
diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt
index 438c23f..57b863f 100644
--- a/platform/platform-resources/src/brokenPlugins.txt
+++ b/platform/platform-resources/src/brokenPlugins.txt
@@ -1,15 +1,14 @@
 // This file contains list of broken plugins.
 // Each line contains plugin ID and list of versions that are broken.
 // If plugin name or version contains a space you can quote it like in command line.
-
-NodeJS   138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
-com.jetbrains.php    136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
+NodeJS   138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
+com.jetbrains.php    138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
 com.jetbrains.lang.ejs    131.17  131.12
 com.jetbrains.twig    133.51  130.1639
-org.jetbrains.plugins.ruby 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704
-Pythonid  3.1
+org.jetbrains.plugins.ruby 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707
+Pythonid  3.1 4.0.25
 Karma    138.21 134.1163 134.1039 134.686  134.31
-org.intellij.scala 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512
+org.intellij.scala 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512
 org.jetbrains.kannotator  0.2.420
 org.jetbrains.kotlin  0.7.1360 0.7.1376 0.8.7
 SBT   1.0.0  1.1.0  1.2.0  1.3.0  1.3.1  1.4.0  1.5.0
diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml
index 58d6f3a..3508b1d 100644
--- a/platform/platform-resources/src/idea/Keymap_Default.xml
+++ b/platform/platform-resources/src/idea/Keymap_Default.xml
@@ -506,6 +506,9 @@
   <action id="EditorPasteFromX11">
     <mouse-shortcut keystroke="button2"/>
   </action>
+  <action id="Vcs.RollbackChangedLines">
+    <keyboard-shortcut first-keystroke="control alt Z"/>
+  </action>
 
   <action id="GotoNextError">
     <keyboard-shortcut first-keystroke="F2"/>
diff --git a/platform/platform-resources/src/idea/Keymap_EclipseMac.xml b/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
index dc1dcb5..f35e24c 100644
--- a/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
+++ b/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
@@ -312,6 +312,10 @@
       <keyboard-shortcut first-keystroke="meta 3"/>
     </action>
 
+    <action id="Vcs.RollbackChangedLines">
+      <keyboard-shortcut first-keystroke="control shift alt Z"/>
+    </action>
+
     <action id="ActivateProjectToolWindow"/>
     <action id="ActivateFavoritesToolWindow"/>
     <action id="ActivateFindToolWindow">
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index 9cebd28..869a8a7 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -563,7 +563,6 @@
     </group>
 
     <group id="DiffPanel.Toolbar">
-      <reference ref="$Copy"/>
       <reference ref="PreviousDiff"/>
       <reference ref="NextDiff"/>
       <separator/>
diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml
index dc15f19..5496ab6 100644
--- a/platform/platform-resources/src/idea/VcsActions.xml
+++ b/platform/platform-resources/src/idea/VcsActions.xml
@@ -265,7 +265,7 @@
       <add-to-group group-id="CloseEditorsGroup" anchor="before" relative-to-action="CloseAllUnpinnedEditors"/>
     </action>
 
-    <action id="RollbackLineStatusChanges" class="com.intellij.openapi.vcs.ex.RollbackLineStatusAction">
+    <action id="Vcs.RollbackChangedLines" class="com.intellij.openapi.vcs.ex.RollbackLineStatusAction" icon="AllIcons.Actions.Reset">
     </action>
 
     <action id="WelcomeScreen.GetFromVcs" class="com.intellij.openapi.wm.impl.welcomeScreen.GetFromVcsAction"
diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
index a901487..dbc05f8 100644
--- a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
@@ -202,42 +202,22 @@
     TestFileStructure fileTree = new TestFileStructure(getModule(), myWorkingDirectory);
 
     fileTree.createDirectoryAndMakeItCurrent("src");
-    PsiFile java2 = fileTree.addTestFile("Test2.java", "empty content");
+    PsiFile java2 = fileTree.addTestFile("Test2.tj", "empty content");
     PsiFile php2 = fileTree.addTestFile("Pair2.php", "empty content");
     PsiFile js2 = fileTree.addTestFile("Pair2.js", "empty content");
 
     PsiDirectory test = fileTree.createDirectoryAndMakeItCurrent("test");
-    PsiFile testJava1 = fileTree.addTestFile("testJava1.java", "empty content");
+    PsiFile testJava1 = fileTree.addTestFile("testJava1.tj", "empty content");
     PsiFile testPhp1 = fileTree.addTestFile("testPhp1.php", "empty content");
     PsiFile testJs1 = fileTree.addTestFile("testJs1.js", "empty content");
 
     GlobalSearchScope testScope = directoryScope(test, true);
 
-    Logger logger = Logger.getInstance(getClass());
-    logFiles(logger, "Previously formatted files: ", myMockCodeStyleManager.getFormattedFiles());
-
-    reformatWithRearrange(myWorkingDirectory, testScope);
-    logFiles(logger, "Currently formatted files: ", myMockCodeStyleManager.getFormattedFiles());
-    logFiles(logger, "Should be formatted", ContainerUtil.newArrayList(testJava1, testPhp1, testJs1));
-
-    assertWasFormatted(testJava1, testPhp1, testJs1);
-    assertWasNotFormatted(java2, php2, js2);
-
     reformatAndOptimize(myWorkingDirectory, testScope);
     assertWasFormatted(testJava1, testPhp1, testJs1);
     assertWasNotFormatted(java2, php2, js2);
   }
 
-  private void logFiles(Logger log, String message, Collection<PsiFile> files) {
-    StringBuilder builder;
-    builder = new StringBuilder();
-    builder.append(message).append('\n');
-    for (PsiFile file : files) {
-      builder.append(file).append('\n');
-    }
-    log.info(builder.toString());
-  }
-
   public void assertWasFormatted(PsiFile... files) {
     final Set<PsiFile> formattedFiles = myMockCodeStyleManager.getFormattedFiles();
     for (PsiFile file : files) {
diff --git a/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java b/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
index 32f5ec2..f8bc13e 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
@@ -103,6 +103,11 @@
     assertEquals(array("/", "foo"), ContainerUtil.collect(Paths.split("/foo").iterator()));
     assertEquals(array("/"), ContainerUtil.collect(Paths.split("/").iterator()));
     assertEquals(array("c:", "foo", "bar"), ContainerUtil.collect(Paths.split("c:/foo/bar").iterator()));
+
+    assertEquals(array("//"), ContainerUtil.collect(Paths.split("//").iterator()));
+    assertEquals(array("//foo"), ContainerUtil.collect(Paths.split("//foo").iterator()));
+    assertEquals(array("//foo"), ContainerUtil.collect(Paths.split("//foo/").iterator()));
+    assertEquals(array("//foo", "bar"), ContainerUtil.collect(Paths.split("//foo/bar").iterator()));
   }
 
   @Test
diff --git a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
index 5a47fdf..db833c2 100644
--- a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -18,16 +18,14 @@
 import com.intellij.lang.impl.PsiBuilderImpl;
 import com.intellij.lexer.Lexer;
 import com.intellij.lexer.LexerBase;
+import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
 import com.intellij.openapi.project.Project;
-import com.intellij.psi.FileViewProvider;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
 import com.intellij.psi.TokenType;
 import com.intellij.psi.impl.DebugUtil;
 import com.intellij.psi.impl.source.tree.ASTStructure;
 import com.intellij.psi.tree.*;
-import com.intellij.testFramework.LightPlatformTestCase;
-import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.LightPlatformLangTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.util.ThreeState;
 import com.intellij.util.diff.DiffTree;
 import com.intellij.util.diff.DiffTreeChangeBuilder;
@@ -36,12 +34,9 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
 import java.util.List;
 
-public class PsiBuilderQuickTest extends LightPlatformTestCase {
+public class PsiBuilderQuickTest extends LightPlatformLangTestCase {
   private static final IFileElementType ROOT = new IFileElementType("ROOT", Language.ANY);
 
   private static final IElementType LETTER = new IElementType("LETTER", Language.ANY);
@@ -57,11 +52,6 @@
   private static final TokenSet WHITESPACE_SET = TokenSet.create(TokenType.WHITE_SPACE);
   private static final TokenSet COMMENT_SET = TokenSet.create(COMMENT);
 
-  @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
-  public PsiBuilderQuickTest() {
-    PlatformTestCase.initPlatformLangPrefix();
-  }
-
   public void testPlain() {
     doTest("a<<b",
            new Parser() {
@@ -428,15 +418,8 @@
            "  PsiElement(OTHER)('}')\n");
   }
 
-  private abstract static class MyLazyElementType extends ILazyParseableElementType implements ILightLazyParseableElementType {
-    protected MyLazyElementType(@NonNls String debugName) {
-      super(debugName, Language.ANY);
-    }
-  }
-
   public void testLightChameleon() {
     final IElementType CHAMELEON_2 = new MyChameleon2Type();
-
     final IElementType CHAMELEON_1 = new MyChameleon1Type(CHAMELEON_2);
 
     doTest("ab{12[.?]}cd{x}",
@@ -478,60 +461,26 @@
            "    PsiElement(OTHER)('}')\n");
   }
 
-  @SuppressWarnings("ConstantConditions")
-  private static PsiBuilderImpl createBuilder(CharSequence text) {
-    ParserDefinition parserDefinition = new ParserDefinition() {
-      @NotNull
-      @Override
-      public Lexer createLexer(Project project) {
-        return new MyTestLexer();
-      }
-
-      @Override
-      public PsiParser createParser(Project project) {
-        return null;
-      }
-
-      @Override
-      public IFileElementType getFileNodeType() {
-        return null;
-      }
-
-      @NotNull
-      @Override
-      public TokenSet getWhitespaceTokens() {
-        return WHITESPACE_SET;
-      }
-
-      @NotNull
-      @Override
-      public TokenSet getCommentTokens() {
-        return COMMENT_SET;
-      }
-
-      @NotNull
-      @Override
-      public TokenSet getStringLiteralElements() {
-        return null;
-      }
-
-      @NotNull
-      @Override
-      public PsiElement createElement(ASTNode node) {
-        return null;
-      }
-
-      @Override
-      public PsiFile createFile(FileViewProvider viewProvider) {
-        return null;
-      }
-
-      @Override
-      public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
-        return null;
-      }
-    };
-    return new PsiBuilderImpl(getProject(), null, parserDefinition, parserDefinition.createLexer(getProject()), null, text, null, null);
+  public void testEndMarkersOverlapping() {
+    doTest("a ",
+           new Parser() {
+             @Override
+             public void parse(PsiBuilder builder) {
+               PsiBuilder.Marker e1 = builder.mark();
+               PsiBuilder.Marker e2 = builder.mark();
+               builder.advanceLexer();
+               e2.done(OTHER);
+               e2.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
+               e1.done(OTHER);
+               e1.setCustomEdgeTokenBinders(null, WhitespacesBinders.DEFAULT_RIGHT_BINDER);
+               assertTrue(builder.eof());
+             }
+           },
+           "Element(ROOT)\n" +
+           "  Element(OTHER)\n" +
+           "    Element(OTHER)\n" +
+           "      PsiElement(LETTER)('a')\n" +
+           "      PsiWhiteSpace(' ')\n");
   }
 
   private interface Parser {
@@ -594,75 +543,44 @@
   }
 
   private static void doFailTest(@NonNls final String text, final Parser parser, @NonNls final String expected) {
-    final PrintStream std = System.err;
-    //noinspection IOResourceOpenedButNotSafelyClosed
-    System.setErr(new PrintStream(new NullStream()));
-    try {
-      try {
-        ParserDefinition parserDefinition = new ParserDefinition() {
-          @NotNull
-          @Override
-          public Lexer createLexer(Project project) {
-            return null;
-          }
-
-          @Override
-          public PsiParser createParser(Project project) {
-            return null;
-          }
-
-          @Override
-          public IFileElementType getFileNodeType() {
-            return null;
-          }
-
-          @NotNull
-          @Override
-          public TokenSet getWhitespaceTokens() {
-            return TokenSet.EMPTY;
-          }
-
-          @NotNull
-          @Override
-          public TokenSet getCommentTokens() {
-            return TokenSet.EMPTY;
-          }
-
-          @NotNull
-          @Override
-          public TokenSet getStringLiteralElements() {
-            return null;
-          }
-
-          @NotNull
-          @Override
-          public PsiElement createElement(ASTNode node) {
-            return null;
-          }
-
-          @Override
-          public PsiFile createFile(FileViewProvider viewProvider) {
-            return null;
-          }
-
-          @Override
-          public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
-            return null;
-          }
-        };
-        final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(parserDefinition, new MyTestLexer(),text);
-        builder.setDebugMode(true);
-        parser.parse(builder);
-        builder.getLightTree();
-        fail("should fail");
+    PlatformTestUtil.withStdErrSuppressed(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(new PlainTextParserDefinition(), new MyTestLexer(), text);
+          builder.setDebugMode(true);
+          parser.parse(builder);
+          builder.getLightTree();
+          fail("should fail");
+        }
+        catch (AssertionError e) {
+          assertEquals(expected, e.getMessage());
+        }
       }
-      catch (AssertionError e) {
-        assertEquals(expected, e.getMessage());
+    });
+  }
+
+  private static PsiBuilderImpl createBuilder(CharSequence text) {
+    ParserDefinition parserDefinition = new PlainTextParserDefinition() {
+      @NotNull
+      @Override
+      public Lexer createLexer(Project project) {
+        return new MyTestLexer();
       }
-    }
-    finally {
-      System.setErr(std);
-    }
+
+      @NotNull
+      @Override
+      public TokenSet getWhitespaceTokens() {
+        return WHITESPACE_SET;
+      }
+
+      @NotNull
+      @Override
+      public TokenSet getCommentTokens() {
+        return COMMENT_SET;
+      }
+    };
+    return new PsiBuilderImpl(getProject(), null, parserDefinition, parserDefinition.createLexer(getProject()), null, text, null, null);
   }
 
   private static class MyTestLexer extends LexerBase {
@@ -719,9 +637,10 @@
     }
   }
 
-  private static class NullStream extends OutputStream {
-    @Override
-    public void write(final int b) throws IOException { }
+  private abstract static class MyLazyElementType extends ILazyParseableElementType implements ILightLazyParseableElementType {
+    protected MyLazyElementType(@NonNls String debugName) {
+      super(debugName, Language.ANY);
+    }
   }
 
   private static class MyChameleon1Type extends MyLazyElementType {
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java
new file mode 100644
index 0000000..2d73640
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase {
+  public void testStoringDesiredXPosition() {
+    init("long line<caret>\n" +
+         "line\n" +
+         "long line\n" +
+         "very long line");
+    cloneCaretBelow();
+    checkResult("long line<caret>\n" +
+                "line<caret>\n" +
+                "long line\n" +
+                "very long line");
+    cloneCaretBelow();
+    checkResult("long line<caret>\n" +
+                "line<caret>\n" +
+                "long line<caret>\n" +
+                "very long line");
+    cloneCaretBelow();
+    checkResult("long line<caret>\n" +
+                "line<caret>\n" +
+                "long line<caret>\n" +
+                "very long<caret> line");
+  }
+
+  public void testCloneAndMove() {
+    init("long line<caret>\n" +
+         "line\n" +
+         "long line");
+    cloneCaretBelow();
+    moveCaretDown();
+    checkResult("long line\n" +
+                "line<caret>\n" +
+                "long line<caret>");
+  }
+
+  public void testCloneBelowAndAbove() {
+    init("line\n" +
+         "<caret>li<caret>ne\n" +
+         "line");
+    cloneCaretBelow();
+    checkResult("line\n" +
+                "<caret>li<caret>ne\n" +
+                "<caret>li<caret>ne");
+    cloneCaretAbove();
+    checkResult("line\n" +
+                "<caret>li<caret>ne\n" +
+                "line");
+    cloneCaretAbove();
+    checkResult("<caret>li<caret>ne\n" +
+                "<caret>li<caret>ne\n" +
+                "line");
+    cloneCaretBelow();
+    checkResult("line\n" +
+                "<caret>li<caret>ne\n" +
+                "line");
+  }
+
+  public void testCloneWithSelection() {
+    init("long <selection>line<caret></selection>\n" +
+         "line\n" +
+         "long line");
+    cloneCaretBelow();
+    checkResult("long <selection>line<caret></selection>\n" +
+                "line\n" +
+                "long <selection>line<caret></selection>");
+  }
+
+  private void cloneCaretBelow() {
+    myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
+  }
+
+  private void cloneCaretAbove() {
+    myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE);
+  }
+
+  private void moveCaretDown() {
+    myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
+  }
+
+  private void init(String text) {
+    myFixture.configureByText(getTestName(false) + ".txt", text);
+  }
+
+  private void checkResult(String text) {
+    myFixture.checkResult(text);
+  }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
index 5dd8bbb..fd774b5 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
@@ -34,6 +34,7 @@
 import java.util.List;
 import java.util.Scanner;
 import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -94,6 +95,20 @@
     ));
   }
 
+  protected static void foldOccurrences(String textToFoldRegexp, final String placeholder) {
+    final Matcher matcher = Pattern.compile(textToFoldRegexp).matcher(myEditor.getDocument().getCharsSequence());
+    myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
+      @Override
+      public void run() {
+        while(matcher.find()) {
+          FoldRegion foldRegion = myEditor.getFoldingModel().addFoldRegion(matcher.start(), matcher.end(), placeholder);
+          assertNotNull(foldRegion);
+          foldRegion.setExpanded(false);
+        }
+      }
+    });
+  }
+
   /**
    * Setups document of the {@link #getEditor() current editor} according to the given text that is expected to contain
    * information about document lines obtained from the {@link DocumentImpl#dumpState()}. 
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
index 5a9d4da..aff78b0 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.editor.impl;
 
 import com.intellij.codeInsight.folding.CodeFoldingManager;
+import com.intellij.openapi.actionSystem.IdeActions;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.VisualPosition;
 import com.intellij.testFramework.EditorTestUtil;
@@ -65,6 +66,29 @@
     verifySoftWrapPositions(58, 93);
   }
 
+  public void testCorrectVisibleLineCountCalculation() throws Exception {
+    init("line containing FOLDED_REGION\n" +
+         "next <caret>line\n" +
+         "last line");
+    foldOccurrences("FOLDED_REGION", "...");
+    EditorTestUtil.configureSoftWraps(myEditor, 16); // wrap right at folded region start
+    verifySoftWrapPositions(16);
+
+    executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
+    checkResultByText("line containing FOLDED_REGION\n" +
+                      "next line\n" +
+                      "last <caret>line");
+  }
+
+  public void testInsertingFirstTab() throws Exception {
+    init(" <caret>space-indented line");
+    EditorTestUtil.configureSoftWraps(myEditor, 100);
+    myEditor.getSettings().setUseTabCharacter(true);
+
+    executeAction(IdeActions.ACTION_EDITOR_TAB);
+    checkResultByText(" \t<caret>space-indented line");
+  }
+
   private void init(String text) throws IOException {
     configureFromFileText(getTestName(false) + ".txt", text);
   }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
index 9f3484b..d11847a 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
@@ -34,6 +34,7 @@
 import com.intellij.openapi.util.ThrowableComputable;
 import com.intellij.openapi.util.Trinity;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.impl.PsiDocumentManagerImpl;
@@ -44,6 +45,7 @@
 import com.intellij.testFramework.Timings;
 import com.intellij.util.CommonProcessors;
 import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.containers.WeakList;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
@@ -1077,13 +1079,13 @@
 
   public void testRangeHighlighterLinesInRangeForLongLinePerformance() throws Exception {
     final int N = 50000;
-    Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2*N));
+    Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2 * N));
 
     final MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, ourProject, true);
     for (int i=0; i<N-1;i++) {
       markupModel.addRangeHighlighter(2*i, 2*i+1, 0, null, HighlighterTargetArea.EXACT_RANGE);
     }
-    markupModel.addRangeHighlighter(N/2, N/2+1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
+    markupModel.addRangeHighlighter(N / 2, N / 2 + 1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
 
     PlatformTestUtil.startPerformanceTest("slow highlighters lookup", (int)(N*Math.log(N)/1000), new ThrowableRunnable() {
       @Override
@@ -1107,6 +1109,42 @@
     RangeHighlighter line = markupModel.addRangeHighlighter(4, 5, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
     List<RangeHighlighter> list = new ArrayList<RangeHighlighter>();
     markupModel.processRangeHighlightersOverlappingWith(2, 9, new CommonProcessors.CollectProcessor<RangeHighlighter>(list));
-    assertEquals(Arrays.asList(line,exact), list);
+    assertEquals(Arrays.asList(line, exact), list);
+  }
+
+  public void testLazyRangeMarkers() {
+    psiFile = createFile("x.txt", "xxx");
+
+    LazyRangeMarkerFactoryImpl factory = (LazyRangeMarkerFactoryImpl)LazyRangeMarkerFactory.getInstance(getProject());
+    VirtualFile virtualFile = psiFile.getVirtualFile();
+    LazyRangeMarkerFactoryImpl.LazyMarker marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0);
+    WeakList<LazyRangeMarkerFactoryImpl.LazyMarker> markers = LazyRangeMarkerFactoryImpl.getMarkers(virtualFile);
+    assertSame(marker, assertOneElement(markers));
+
+    assertFalse(marker.isDelegated());
+    assertTrue(marker.isValid());
+    assertEquals(0, marker.getStartOffset());
+    assertFalse(marker.isDelegated());
+
+    marker.dispose();
+    assertFalse(marker.isValid());
+    assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
+
+
+    marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0);
+    assertFalse(marker.isDelegated());
+    assertTrue(marker.isValid());
+    assertEquals(0, marker.getStartOffset());
+    assertFalse(marker.isDelegated());
+
+    Document document = marker.getDocument();
+    document.insertString(2, "yyy");
+    assertTrue(marker.isDelegated());
+    assertTrue(marker.isValid());
+    assertEquals(0, marker.getStartOffset());
+
+    assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
+    marker.dispose();
+    assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
   }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java
similarity index 98%
rename from platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
rename to platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java
index abfef7c..285aadb 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java
@@ -13,15 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.openapi.editor;
+package com.intellij.openapi.editor.impl;
 
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.impl.ApplicationImpl;
 import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper;
 import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
index e517799..06594d2 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
@@ -245,7 +245,7 @@
     assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile1));
     assertNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile2));
 
-    PsiTestUtil.removeContentEntry(myModule, contextRoot);
+    PsiTestUtil.removeContentEntry(myModule, contextRoot.getFile());
 
     // do not add notification panel until access is requested
     assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile1));
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
index 490aa29..96d85c1 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
@@ -118,6 +118,16 @@
     release();
   }
 
+  public void testRepeatedInvocationOnKeyHold() {
+    press();
+    release();
+    press();
+    key(2);
+    assertInvocationCounts(0, 0, 2);
+    release();
+    assertInvocationCounts(0, 0, 2);
+  }
+
   public void assertInvocationCounts(int shiftKeyCount, int shiftShiftCount, int shiftShiftKeyCount) {
     assertEquals(shiftKeyCount, myShiftKeyActionInvocationCount);
     assertEquals(shiftShiftCount, myShiftShiftActionInvocationCount);
@@ -143,18 +153,24 @@
   }
 
   private void key() {
-    IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
-                                                           KeyEvent.KEY_PRESSED,
-                                                           Clock.getTime(),
-                                                           InputEvent.SHIFT_MASK,
-                                                           KeyEvent.VK_BACK_SPACE,
-                                                           '\b'));
-    IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
-                                                           KeyEvent.KEY_TYPED,
-                                                           Clock.getTime(),
-                                                           InputEvent.SHIFT_MASK,
-                                                           0,
-                                                           '\b'));
+    key(1);
+  }
+
+  private void key(int repeat) {
+    for (int i = 0; i < repeat; i++) {
+      IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
+                                                             KeyEvent.KEY_PRESSED,
+                                                             Clock.getTime(),
+                                                             InputEvent.SHIFT_MASK,
+                                                             KeyEvent.VK_BACK_SPACE,
+                                                             '\b'));
+      IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
+                                                             KeyEvent.KEY_TYPED,
+                                                             Clock.getTime(),
+                                                             InputEvent.SHIFT_MASK,
+                                                             0,
+                                                             '\b'));
+    }
     IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
                                                            KeyEvent.KEY_RELEASED,
                                                            Clock.getTime(),
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
index b06cf06..17a7abc 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
@@ -131,6 +131,7 @@
   /**
    * @deprecated name of this method may be confusing. If you want to check if the file is excluded or ignored use {@link #isExcluded(com.intellij.openapi.vfs.VirtualFile)}.
    * If you want to check if the file is ignored use {@link com.intellij.openapi.fileTypes.FileTypeRegistry#isFileIgnored(com.intellij.openapi.vfs.VirtualFile)}.
+   * If you want to check if the file or one of its parents is ignored use {@link #isUnderIgnored(com.intellij.openapi.vfs.VirtualFile)}.
    */
   @Deprecated
   boolean isIgnored(@NotNull VirtualFile file);
@@ -143,4 +144,13 @@
    * @return true if <code>file</code> is excluded or ignored, false otherwise.
    */
   boolean isExcluded(@NotNull VirtualFile file);
+
+  /**
+   * Checks if the specified file or directory is located under project roots but the file itself or one of its parent directories is ignored
+   * by {@link com.intellij.openapi.fileTypes.FileTypeRegistry#isFileIgnored(com.intellij.openapi.vfs.VirtualFile)}).
+   *
+   * @param file the file to check.
+   * @return true if <code>file</code> is ignored, false otherwise.
+   */
+  boolean isUnderIgnored(@NotNull VirtualFile file);
 }
diff --git a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
index 7acb0fb..7b436b5 100644
--- a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
+++ b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -41,21 +41,21 @@
     return directoryFile.equals(fileIndex.getSourceRootForFile(directoryFile));
   }
 
-  public static boolean isInSource(final PsiDirectory directory) {
+  public static boolean isInSource(@NotNull PsiDirectory directory) {
     return isInSource(directory.getVirtualFile(), directory.getProject());
   }
 
-  public static boolean isInSource(final VirtualFile directoryFile, final Project project) {
+  public static boolean isInSource(@NotNull VirtualFile directoryFile, @NotNull Project project) {
     final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
     return projectFileIndex.isInSourceContent(directoryFile);
   }
 
-  public static boolean isInTestSource(final VirtualFile directoryFile, final Project project) {
+  public static boolean isInTestSource(@NotNull VirtualFile directoryFile, @NotNull Project project) {
     final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
     return projectFileIndex.isInTestSourceContent(directoryFile);
   }
 
-  public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, final @NotNull Project project) {
+  public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, @NotNull final Project project) {
     return getModuleSourceRoot(virtualFile, project) != null;
   }
 
@@ -66,7 +66,7 @@
     return module != null && !module.isDisposed() ? findSourceFolder(module, root) : null;
   }
 
-  public static boolean isLibraryRoot(final VirtualFile directoryFile, final Project project) {
+  public static boolean isLibraryRoot(@NotNull VirtualFile directoryFile, @NotNull Project project) {
     final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
     if (projectFileIndex.isInLibraryClasses(directoryFile)) {
       final VirtualFile parent = directoryFile.getParent();
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
index 83984e1..7a62c35 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -65,4 +66,12 @@
                                           @NotNull Collection<String> urls) {
     return false;
   }
+
+  public boolean addCustomModuleRoots(@NotNull OrderRootType type,
+                                      @NotNull ModuleRootModel rootModel,
+                                      @NotNull Collection<String> result,
+                                      boolean includeProduction,
+                                      boolean includeTests) {
+    return false;
+  }
 }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
index 9fdd8e0..e87d3c7 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
@@ -17,23 +17,23 @@
 package com.intellij.openapi.roots.impl;
 
 import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.OrderEntry;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.Query;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
+import java.util.List;
+
 public abstract class DirectoryIndex {
   public static DirectoryIndex getInstance(Project project) {
     assert !project.isDefault() : "Must not call DirectoryIndex for default project";
     return ServiceManager.getService(project, DirectoryIndex.class);
   }
 
-  @TestOnly
-  public abstract void checkConsistency();
-
   /**
    * The same as {@link #getInfoForFile} but works only for directories or file roots and returns {@code null} for directories
    * which aren't included in project content or libraries
@@ -62,4 +62,13 @@
   public boolean isInitialized() {
     return true;
   }
+
+  @NotNull
+  public abstract OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info);
+
+  @Nullable
+  abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule);
+
+  @NotNull
+  abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule);
 }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
index b31519c..61838f5 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
@@ -17,7 +17,6 @@
 package com.intellij.openapi.roots.impl;
 
 import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.module.Module;
 import com.intellij.openapi.roots.ModuleRootModel;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
@@ -29,10 +28,9 @@
 public interface DirectoryIndexExcludePolicy {
   ExtensionPointName<DirectoryIndexExcludePolicy> EP_NAME = ExtensionPointName.create("com.intellij.directoryIndexExcludePolicy");
 
-  boolean isExcludeRoot(VirtualFile file);
-  boolean isExcludeRootForModule(@NotNull Module module, final VirtualFile file);
   @NotNull
   VirtualFile[] getExcludeRootsForProject();
+
   @NotNull
   VirtualFilePointer[] getExcludeRootsForModule(@NotNull ModuleRootModel rootModel);
 }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
index 87448a5..cd5fbd7 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
@@ -17,13 +17,8 @@
 package com.intellij.openapi.roots.impl;
 
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
 import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-
-import java.util.List;
 
 public abstract class DirectoryInfo {
   /**
@@ -61,16 +56,4 @@
 
   @Nullable
   public abstract Module getModule();
-
-  @NotNull
-  public abstract OrderEntry[] getOrderEntries();
-
-  @Nullable
-  abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule);
-
-  @NotNull
-  abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule);
-
-  @TestOnly
-  abstract void assertConsistency();
 }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
index 0be339b..1c3ca4f 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
@@ -16,34 +16,16 @@
 package com.intellij.openapi.roots.impl;
 
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
-import com.intellij.openapi.roots.OrderRootType;
-import com.intellij.openapi.roots.RootPolicy;
-import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
 
 /**
  * @author nik
  */
-public abstract class DirectoryInfoImpl extends DirectoryInfo {
-  public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
-    @Override
-    public int compare(OrderEntry o1, OrderEntry o2) {
-      String name1 = o1.getOwnerModule().getName();
-      String name2 = o2.getOwnerModule().getName();
-      return name1.compareTo(name2);
-    }
-  };
+public class DirectoryInfoImpl extends DirectoryInfo {
   public static final int MAX_ROOT_TYPE_ID = Byte.MAX_VALUE;
+  private final VirtualFile myRoot;//original project root for which this information is calculated
   private final Module module; // module to which content it belongs or null
   private final VirtualFile libraryClassRoot; // class root in library
   private final VirtualFile contentRoot;
@@ -53,8 +35,9 @@
   private final boolean myExcluded;
   private final byte mySourceRootTypeId;
 
-  DirectoryInfoImpl(Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot,
+  DirectoryInfoImpl(@NotNull VirtualFile root, Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot,
                     boolean inModuleSource, boolean inLibrarySource, boolean isExcluded, int sourceRootTypeId) {
+    myRoot = root;
     this.module = module;
     this.libraryClassRoot = libraryClassRoot;
     this.contentRoot = contentRoot;
@@ -74,30 +57,12 @@
     if (this == o) return true;
     if (o == null || getClass() != o.getClass()) return false;
 
-    DirectoryInfoImpl info = (DirectoryInfoImpl)o;
-
-    return mySourceRootTypeId == info.mySourceRootTypeId &&
-           myInModuleSource == info.myInModuleSource &&
-           myInLibrarySource == info.myInLibrarySource &&
-           myExcluded == info.myExcluded &&
-           Comparing.equal(contentRoot, info.contentRoot) &&
-           Comparing.equal(libraryClassRoot, info.libraryClassRoot) &&
-           Comparing.equal(module, info.module) &&
-           Arrays.equals(getOrderEntries(), info.getOrderEntries()) &&
-           Comparing.equal(sourceRoot, info.sourceRoot);
+    return myRoot.equals(((DirectoryInfoImpl)o).myRoot);
   }
 
   @Override
   public int hashCode() {
-    int result = module != null ? module.hashCode() : 0;
-    result = 31 * result + (libraryClassRoot != null ? libraryClassRoot.hashCode() : 0);
-    result = 31 * result + (contentRoot != null ? contentRoot.hashCode() : 0);
-    result = 31 * result + (sourceRoot != null ? sourceRoot.hashCode() : 0);
-    result = 31 * result + (myInModuleSource ? 1 : 0);
-    result = 31 * result + (myInLibrarySource ? 1 : 0);
-    result = 31 * result + (myExcluded ? 1 : 0);
-    result = 31 * result + (int)mySourceRootTypeId;
-    return result;
+    return myRoot.hashCode();
   }
 
   @SuppressWarnings({"HardCodedStringLiteral"})
@@ -111,98 +76,9 @@
            ", libraryClassRoot=" + getLibraryClassRoot() +
            ", contentRoot=" + getContentRoot() +
            ", sourceRoot=" + getSourceRoot() +
-           ", orderEntries=" + Arrays.toString(getOrderEntries()) +
            "}";
   }
 
-  @NotNull
-  private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) {
-    return new OrderEntry() {
-      @NotNull
-      @Override
-      public VirtualFile[] getFiles(OrderRootType type) {
-        throw new IncorrectOperationException();
-      }
-
-      @NotNull
-      @Override
-      public String[] getUrls(OrderRootType rootType) {
-        throw new IncorrectOperationException();
-      }
-
-      @NotNull
-      @Override
-      public String getPresentableName() {
-        throw new IncorrectOperationException();
-      }
-
-      @Override
-      public boolean isValid() {
-        throw new IncorrectOperationException();
-      }
-
-      @NotNull
-      @Override
-      public Module getOwnerModule() {
-        return ownerModule;
-      }
-
-      @Override
-      public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) {
-        throw new IncorrectOperationException();
-      }
-
-      @Override
-      public int compareTo(@NotNull OrderEntry o) {
-        throw new IncorrectOperationException();
-      }
-
-      @Override
-      public boolean isSynthetic() {
-        throw new IncorrectOperationException();
-      }
-    };
-  }
-
-  @Nullable
-  OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) {
-    OrderEntry[] entries = getOrderEntries();
-    if (entries.length < 10) {
-      for (OrderEntry entry : entries) {
-        if (entry.getOwnerModule() == ownerModule) return entry;
-      }
-      return null;
-    }
-    int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE);
-    return index < 0 ? null : entries[index];
-  }
-
-  @NotNull
-  List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) {
-    OrderEntry[] entries = getOrderEntries();
-    if (entries.length == 1) {
-      OrderEntry entry = entries[0];
-      return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
-    }
-    int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE);
-    if (index < 0) {
-      return Collections.emptyList();
-    }
-    int firstIndex = index;
-    while (firstIndex-1 >= 0 && entries[firstIndex-1].getOwnerModule() == ownerModule) {
-      firstIndex--;
-    }
-    int lastIndex = index+1;
-    while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) {
-      lastIndex++;
-    }
-
-    OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex];
-    System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex);
-
-    return Arrays.asList(subArray);
-  }
-
   public boolean isInProject() {
     return !isExcluded();
   }
@@ -241,15 +117,12 @@
     return module;
   }
 
-  @TestOnly
-  void assertConsistency() {
-    OrderEntry[] entries = getOrderEntries();
-    for (int i=1; i<entries.length; i++) {
-      assert BY_OWNER_MODULE.compare(entries[i-1], entries[i]) <= 0;
-    }
-  }
-
   public int getSourceRootTypeId() {
     return mySourceRootTypeId;
   }
+
+  @NotNull
+  public VirtualFile getRoot() {
+    return myRoot;
+  }
 }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
index 3b5ea4f..8140a3c 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
@@ -79,12 +79,12 @@
   @Override
   @NotNull
   public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile fileOrDir) {
-    return getInfoForFileOrDirectory(fileOrDir).findAllOrderEntriesWithOwnerModule(myModule);
+    return myDirectoryIndex.findAllOrderEntriesWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
   }
 
   @Override
   public OrderEntry getOrderEntryForFile(@NotNull VirtualFile fileOrDir) {
-    return getInfoForFileOrDirectory(fileOrDir).findOrderEntryWithOwnerModule(myModule);
+    return myDirectoryIndex.findOrderEntryWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
   }
 
   @Override
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
index 7937f08..ce09ec2 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
@@ -16,14 +16,9 @@
 package com.intellij.openapi.roots.impl;
 
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
 import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.Collections;
-import java.util.List;
-
 /**
  * @author nik
  */
@@ -53,22 +48,6 @@
     return false;
   }
 
-  @NotNull
-  @Override
-  public OrderEntry[] getOrderEntries() {
-    return OrderEntry.EMPTY_ARRAY;
-  }
-
-  @Nullable
-  OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) {
-    return null;
-  }
-
-  @NotNull
-  List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) {
-    return Collections.emptyList();
-  }
-
   @Override
   public String toString() {
     return "DirectoryInfo: " + myDebugName;
@@ -118,9 +97,6 @@
     return null;
   }
 
-  void assertConsistency() {
-  }
-
   public int getSourceRootTypeId() {
     return 0;
   }
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
index 61a6aee..b13df05 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
@@ -356,6 +356,38 @@
     return false;
   }
 
+  boolean addCustomRootsForModule(OrderRootType type,
+                                  ModuleRootModel rootModel,
+                                  Collection<VirtualFile> result,
+                                  boolean includeProduction,
+                                  boolean includeTests) {
+    for (OrderEnumerationHandler handler : myCustomHandlers) {
+      final List<String> urls = new ArrayList<String>();
+      final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
+      for (String url : urls) {
+        ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result);
+      }
+
+      if (added) return true;
+    }
+    return false;
+  }
+
+  boolean addCustomRootUrlsForModule(OrderRootType type,
+                                     ModuleRootModel rootModel,
+                                     Collection<String> result,
+                                     boolean includeProduction,
+                                     boolean includeTests) {
+    for (OrderEnumerationHandler handler : myCustomHandlers) {
+      final List<String> urls = new ArrayList<String>();
+      final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
+      result.addAll(urls);
+
+      if (added) return true;
+    }
+    return false;
+  }
+
   @Override
   public boolean isRuntimeOnly() {
     return myRuntimeOnly;
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
index ea5742c..fb9a751 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
@@ -240,6 +240,7 @@
         }
       }
     }
+    myOrderEnumerator.addCustomRootsForModule(type, rootModel, result, includeProduction, includeTests);
   }
 
   private void collectModuleRootsUrls(OrderRootType type,
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
index 0bb65c6..e157637 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
@@ -69,6 +69,11 @@
     return myFileIndex.isExcluded(file);
   }
 
+  @Override
+  public boolean isUnderIgnored(@NotNull VirtualFile file) {
+    return myFileIndex.isUnderIgnored(file);
+  }
+
   @Nullable
   @Override
   public Module getModuleForFile(@NotNull VirtualFile file) {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
index acb6598..e241719 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
@@ -85,6 +85,11 @@
   }
 
   @Override
+  public boolean isUnderIgnored(@NotNull VirtualFile file) {
+    return getInfoForFileOrDirectory(file).isIgnored();
+  }
+
+  @Override
   public Module getModuleForFile(@NotNull VirtualFile file) {
     if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
     DirectoryInfo info = getInfoForFileOrDirectory(file);
@@ -95,7 +100,7 @@
   @Override
   @NotNull
   public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) {
-    return Arrays.asList(getInfoForFileOrDirectory(file).getOrderEntries());
+    return Arrays.asList(myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(file)));
   }
 
   @Override
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
index 85a0983..8e80670 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
@@ -131,8 +131,7 @@
     return (ProjectRootManagerImpl)getInstance(project);
   }
 
-  public ProjectRootManagerImpl(Project project,
-                                DirectoryIndex directoryIndex) {
+  public ProjectRootManagerImpl(Project project) {
     myProject = project;
     myRootsCache = new OrderRootsCache(project);
   }
@@ -143,8 +142,6 @@
     return ProjectFileIndex.SERVICE.getInstance(myProject);
   }
 
-  private final Map<ModuleRootListener, MessageBusConnection> myListenerAdapters = new HashMap<ModuleRootListener, MessageBusConnection>();
-
   @Override
   @NotNull
   public List<String> getContentRootUrls() {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
index ca68cee..eb04fb6 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
@@ -25,13 +25,16 @@
 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
 import com.intellij.openapi.roots.libraries.Library;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.LowMemoryWatcher;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
 import com.intellij.util.CollectionQuery;
+import com.intellij.util.EmptyQuery;
 import com.intellij.util.Query;
+import com.intellij.util.containers.ConcurrentHashSet;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.MultiMap;
 import gnu.trove.TObjectIntHashMap;
@@ -41,7 +44,15 @@
 
 import java.util.*;
 
-public class RootIndex extends DirectoryIndex {
+public class RootIndex {
+  public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
+    @Override
+    public int compare(OrderEntry o1, OrderEntry o2) {
+      String name1 = o1.getOwnerModule().getName();
+      String name2 = o2.getOwnerModule().getName();
+      return name1.compareTo(name2);
+    }
+  };
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.RootIndex");
 
   private final Set<VirtualFile> myProjectExcludedRoots = ContainerUtil.newHashSet();
@@ -54,11 +65,20 @@
   };
 
   private final Map<String, List<VirtualFile>> myDirectoriesByPackageNameCache = ContainerUtil.newConcurrentMap();
+  private final Set<String> myNonExistentPackages = new ConcurrentHashSet<String>();
   private final InfoCache myInfoCache;
   private final List<JpsModuleSourceRootType<?>> myRootTypes = ContainerUtil.newArrayList();
   private final TObjectIntHashMap<JpsModuleSourceRootType<?>> myRootTypeId = new TObjectIntHashMap<JpsModuleSourceRootType<?>>();
   @NotNull private final Project myProject;
   private volatile Map<VirtualFile, OrderEntry[]> myOrderEntries;
+  @SuppressWarnings("UnusedDeclaration")
+  private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
+    @Override
+    public void run() {
+      myNonExistentPackages.clear();
+    }
+  });
+
 
   // made public for Upsource
   public RootIndex(@NotNull Project project, @NotNull InfoCache cache) {
@@ -145,7 +165,6 @@
               }
             }
           }
-
         }
       }
     }
@@ -171,7 +190,8 @@
         if (orderEntry instanceof ModuleOrderEntry) {
           final Module depModule = ((ModuleOrderEntry)orderEntry).getModule();
           if (depModule != null) {
-            VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
+            VirtualFile[] importedClassRoots =
+              OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
             for (VirtualFile importedClassRoot : importedClassRoots) {
               depEntries.putValue(importedClassRoot, orderEntry);
             }
@@ -197,7 +217,9 @@
     Set<VirtualFile> allRoots = rootInfo.getAllRoots();
     for (VirtualFile file : allRoots) {
       List<VirtualFile> hierarchy = getHierarchy(file, allRoots, rootInfo);
-      result.put(file, hierarchy == null ? OrderEntry.EMPTY_ARRAY : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy));
+      result.put(file, hierarchy == null
+                       ? OrderEntry.EMPTY_ARRAY
+                       : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy));
     }
     myOrderEntries = result;
     return result;
@@ -211,7 +233,8 @@
     @Nullable VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
     @Nullable VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
     Set<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
-    orderEntries.addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries));
+    orderEntries
+      .addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries));
     for (VirtualFile root : hierarchy) {
       orderEntries.addAll(depEntries.get(root));
     }
@@ -224,12 +247,11 @@
     }
 
     OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
-    Arrays.sort(array, DirectoryInfoImpl.BY_OWNER_MODULE);
+    Arrays.sort(array, BY_OWNER_MODULE);
     return array;
   }
 
 
-  @Override
   public void checkConsistency() {
     for (VirtualFile file : myProjectExcludedRoots) {
       assert file.exists() : file.getPath() + " does not exist";
@@ -247,21 +269,14 @@
 
     int id = myRootTypes.size();
     if (id > DirectoryInfoImpl.MAX_ROOT_TYPE_ID) {
-      LOG.error("Too many different types of module source roots (" + id  + ") registered: " + myRootTypes);
+      LOG.error("Too many different types of module source roots (" + id + ") registered: " + myRootTypes);
     }
     myRootTypes.add(rootType);
     myRootTypeId.put(rootType, id);
     return id;
   }
 
-  @Override
-  public DirectoryInfo getInfoForDirectory(@NotNull VirtualFile dir) {
-    DirectoryInfo info = getInfoForFile(dir);
-    return info.isInProject() ? info : null;
-  }
-
   @NotNull
-  @Override
   public DirectoryInfo getInfoForFile(@NotNull VirtualFile file) {
     if (!file.isValid()) {
       return NonProjectDirectoryInfo.INVALID;
@@ -314,28 +329,41 @@
     return info;
   }
 
-  @Override
   @NotNull
   public Query<VirtualFile> getDirectoriesByPackageName(@NotNull final String packageName, final boolean includeLibrarySources) {
     List<VirtualFile> result = myDirectoriesByPackageNameCache.get(packageName);
     if (result == null) {
+      if (myNonExistentPackages.contains(packageName)) return EmptyQuery.getEmptyQuery();
+
       result = ContainerUtil.newSmartList();
-      
+
       if (StringUtil.isNotEmpty(packageName) && !StringUtil.startsWithChar(packageName, '.')) {
-        String shortName = StringUtil.getShortName(packageName);
-        for (VirtualFile parentDir : getDirectoriesByPackageName(StringUtil.getPackageName(packageName), true)) {
-          VirtualFile child = parentDir.findChild(shortName);
-          if (child != null && child.isDirectory() && getInfoForFile(child).isInProject()
-              && packageName.equals(getPackageName(child))) {
-            result.add(child);
+        int i = packageName.lastIndexOf('.');
+        while (true) {
+          String shortName = packageName.substring(i + 1);
+          String parentPackage = i > 0 ? packageName.substring(0, i) : "";
+          for (VirtualFile parentDir : getDirectoriesByPackageName(parentPackage, true)) {
+            VirtualFile child = parentDir.findChild(shortName);
+            if (child != null && child.isDirectory() && getInfoForFile(child).isInProject()
+                && packageName.equals(getPackageName(child))) {
+              result.add(child);
+            }
           }
+          if (i < 0) break;
+          i = packageName.lastIndexOf('.', i - 1);
         }
       }
 
-      result.addAll(myPackagePrefixRoots.get(packageName));
+      for (VirtualFile file : myPackagePrefixRoots.get(packageName)) {
+        if (file.isDirectory()) {
+          result.add(file);
+        }
+      }
 
       if (!result.isEmpty()) {
         myDirectoriesByPackageNameCache.put(packageName, result);
+      } else {
+        myNonExistentPackages.add(packageName);
       }
     }
 
@@ -351,7 +379,6 @@
     return new CollectionQuery<VirtualFile>(result);
   }
 
-  @Override
   @Nullable
   public String getPackageName(@NotNull final VirtualFile dir) {
     if (dir.isDirectory()) {
@@ -380,7 +407,6 @@
     return parentPackageName.isEmpty() ? subdirName : parentPackageName + "." + subdirName;
   }
 
-  @Override
   @Nullable
   public JpsModuleSourceRootType<?> getSourceRootType(@NotNull DirectoryInfo directoryInfo) {
     return myRootTypes.get(directoryInfo.getSourceRootTypeId());
@@ -487,8 +513,9 @@
         if (source && libraryOrSdkSources.contains(root) &&
             (!sourceOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(sourceOfLibraries.get(root)))) {
           return root;
-        } else if (!source && libraryOrSdkClasses.contains(root) &&
-                   (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
+        }
+        else if (!source && libraryOrSdkClasses.contains(root) &&
+                 (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
           return root;
         }
       }
@@ -569,8 +596,11 @@
     }
   }
 
+
   @NotNull
-  private Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root, @NotNull final List<VirtualFile> hierarchy, @NotNull RootInfo info) {
+  private static Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root,
+                                                               @NotNull final List<VirtualFile> hierarchy,
+                                                               @NotNull RootInfo info) {
     VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy);
     VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
     VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
@@ -590,23 +620,26 @@
     int typeId = moduleSourceRoot != null ? info.rootTypeId.get(moduleSourceRoot) : 0;
 
     Module module = parentModuleForExcluded != null ? parentModuleForExcluded : info.contentRootOf.get(moduleContentRoot);
-    DirectoryInfo directoryInfo = new DirectoryInfoImpl(module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource,
-                                                       parentModuleForExcluded != null, typeId) {
-      @NotNull
-      @Override
-      public OrderEntry[] getOrderEntries() {
-        OrderEntry[] entries = RootIndex.this.getOrderEntries().get(root);
-        return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
-      }
-    };
+    DirectoryInfo directoryInfo =
+      new DirectoryInfoImpl(root, module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource,
+                            parentModuleForExcluded != null, typeId);
 
     String packagePrefix = info.calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
 
     return Pair.create(directoryInfo, packagePrefix);
   }
-  
-  public interface InfoCache {
-    @Nullable DirectoryInfo getCachedInfo(@NotNull VirtualFile dir);
-   void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info);
+
+  @NotNull
+  public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) {
+    if (!(info instanceof DirectoryInfoImpl)) return OrderEntry.EMPTY_ARRAY;
+    OrderEntry[] entries = this.getOrderEntries().get(((DirectoryInfoImpl)info).getRoot());
+    return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
   }
-}
\ No newline at end of file
+
+  public interface InfoCache {
+    @Nullable
+    DirectoryInfo getCachedInfo(@NotNull VirtualFile dir);
+
+    void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info);
+  }
+}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
index 8ece843..540bfe2 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
@@ -213,6 +213,8 @@
     LOG.assertTrue(myContent.contains(entry));
     if (entry instanceof RootModelComponentBase) {
       Disposer.dispose((RootModelComponentBase)entry);
+      RootModelImpl entryModel = ((RootModelComponentBase)entry).getRootModel();
+      LOG.assertTrue(entryModel == this, "Removing from " + this + " content entry obtained from " + entryModel);
     }
     myContent.remove(entry);
   }
@@ -731,6 +733,15 @@
     return myModuleRootManager.getRootModel();
   }
 
+  @Override
+  public String toString() {
+    return "RootModelImpl{" +
+           "module=" + getModule().getName() +
+           ", writable=" + myWritable +
+           ", disposed=" + myDisposed +
+           '}';
+  }
+
   @Nullable
   @Override
   public <T> T getModuleExtension(@NotNull final Class<T> klass) {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
index 7a8e9ca..fa90184 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
@@ -522,10 +522,8 @@
 
   private boolean isUnderRoots(@NotNull String url) {
     for (VirtualFilePointerContainer container : myRoots.values()) {
-      for (String rootUrl : container.getUrls()) {
-        if (VfsUtilCore.isEqualOrAncestor(rootUrl, url)) {
-          return true;
-        }
+      if (VfsUtilCore.isUnder(url, Arrays.asList(container.getUrls()))) {
+        return true;
       }
     }
     return false;
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
index f12e646..8ed6e68 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
@@ -20,8 +20,6 @@
  */
 public class ServerConnectionManagerImpl extends ServerConnectionManager {
 
-  private static final int POLL_DEPLOYMENTS_DELAY = 2000;
-
   private final Map<RemoteServer<?>, ServerConnection> myConnections = new HashMap<RemoteServer<?>, ServerConnection>();
   private final ServerConnectionEventDispatcher myEventDispatcher = new ServerConnectionEventDispatcher();
 
@@ -34,29 +32,10 @@
       connection = doCreateConnection(server, this);
       myConnections.put(server, connection);
       myEventDispatcher.fireConnectionCreated(connection);
-      pollDeployments(connection);
     }
     return connection;
   }
 
-  private void pollDeployments(final ServerConnection connection) {
-    connection.computeDeployments(new Runnable() {
-
-      @Override
-      public void run() {
-        new Alarm().addRequest(new Runnable() {
-
-          @Override
-          public void run() {
-            if (connection == getConnection(connection.getServer())) {
-              pollDeployments(connection);
-            }
-          }
-        }, POLL_DEPLOYMENTS_DELAY, ModalityState.any());
-      }
-    });
-  }
-
   @NotNull
   @Override
   public <C extends ServerConfiguration> ServerConnection createTemporaryConnection(@NotNull RemoteServer<C> server) {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
index 7a1f27f..8a46887 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
@@ -6,6 +6,7 @@
 import com.intellij.ide.util.treeView.NodeDescriptor;
 import com.intellij.ide.util.treeView.NodeRenderer;
 import com.intellij.ide.util.treeView.TreeVisitor;
+import com.intellij.openapi.application.ModalityState;
 import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
@@ -13,7 +14,6 @@
 import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
 import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
@@ -28,6 +28,7 @@
 import com.intellij.ui.SideBorder;
 import com.intellij.ui.components.panels.Wrapper;
 import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.Alarm;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -56,6 +57,8 @@
   private static final String MESSAGE_CARD = "message";
   private static final String EMPTY_SELECTION_MESSAGE = "Select a server or deployment in the tree to view details";
 
+  private static final int POLL_DEPLOYMENTS_DELAY = 2000;
+
   private final Tree myTree;
   private final CardLayout myPropertiesPanelLayout;
   private final JPanel myPropertiesPanel;
@@ -188,6 +191,7 @@
       @Override
       public void onConnectionCreated(@NotNull ServerConnection<?> connection) {
         getBuilder().queueUpdate();
+        pollDeployments(connection);
       }
 
       @Override
@@ -210,6 +214,24 @@
     }
   }
 
+  private static void pollDeployments(final ServerConnection connection) {
+    connection.computeDeployments(new Runnable() {
+
+      @Override
+      public void run() {
+        new Alarm().addRequest(new Runnable() {
+
+          @Override
+          public void run() {
+            if (connection == ServerConnectionManager.getInstance().getConnection(connection.getServer())) {
+              pollDeployments(connection);
+            }
+          }
+        }, POLL_DEPLOYMENTS_DELAY, ModalityState.any());
+      }
+    });
+  }
+
   private JComponent createToolbar() {
     DefaultActionGroup group = new DefaultActionGroup();
     group.add(ActionManager.getInstance().getAction(SERVERS_TOOL_WINDOW_TOOLBAR));
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
index fa4355e..5a3d150 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
@@ -15,9 +15,6 @@
  */
 package com.intellij.remoteServer.util;
 
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.execution.configurations.ConfigurationType;
 import com.intellij.ide.DataManager;
 import com.intellij.ide.actions.ShowSettingsUtilImpl;
 import com.intellij.ide.util.projectWizard.WizardContext;
@@ -25,11 +22,8 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModulePointer;
-import com.intellij.openapi.module.ModulePointerManager;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.ex.SingleConfigurableEditor;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.ComboBox;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.util.Condition;
@@ -38,12 +32,7 @@
 import com.intellij.remoteServer.ServerType;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.configuration.RemoteServersManager;
-import com.intellij.remoteServer.configuration.ServerConfiguration;
-import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
 import com.intellij.remoteServer.impl.configuration.RemoteServerConfigurable;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
 import com.intellij.util.Consumer;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.hash.HashMap;
@@ -224,52 +213,7 @@
     if (account == null) {
       return;
     }
-    createRunConfiguration(account, module, configuration);
-  }
-
-  public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
-  DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account, Module module, DC deploymentConfiguration) {
-
-    Project project = module.getProject();
-
-    String accountName = account.getName();
-
-    String name = generateRunConfigurationName(accountName, module.getName());
-
-    final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
-    final RunnerAndConfigurationSettings runSettings
-      = runManager.createRunConfiguration(name, getRunConfigurationType(account.getType()).getConfigurationFactories()[0]);
-
-    final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
-
-    result.setServerName(accountName);
-
-    final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
-    result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
-
-    result.setDeploymentConfiguration(deploymentConfiguration);
-
-    runManager.addConfiguration(runSettings, false);
-    runManager.setSelectedConfiguration(runSettings);
-
-    return result;
-  }
-
-  private static DeployToServerConfigurationType getRunConfigurationType(ServerType<?> cloudType) {
-    String id = DeployToServerConfigurationType.getId(cloudType);
-    for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
-      if (configurationType instanceof DeployToServerConfigurationType) {
-        DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
-        if (deployConfigurationType.getId().equals(id)) {
-          return deployConfigurationType;
-        }
-      }
-    }
-    return null;
-  }
-
-  private static String generateRunConfigurationName(String serverName, String moduleName) {
-    return CloudBundle.getText("run.configuration.name", serverName, moduleName);
+    CloudRunConfigurationUtil.createRunConfiguration(account, module, configuration);
   }
 
   private static class AccountItem {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java
new file mode 100644
index 0000000..a717571
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package com.intellij.remoteServer.util;
+
+import com.intellij.execution.RunManagerEx;
+import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.configuration.ConfigurationFactoryEx;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.ConfigurationType;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModulePointer;
+import com.intellij.openapi.module.ModulePointerManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
+
+
+public class CloudRunConfigurationUtil {
+
+  public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
+  DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account, Module module, DC deploymentConfiguration) {
+    final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module);
+    DeploymentSource deploymentSource = new ModuleDeploymentSourceImpl(modulePointer);
+    return createRunConfiguration(account, module, deploymentSource, deploymentConfiguration);
+  }
+
+  public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
+  DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account,
+                                                                Module module,
+                                                                DeploymentSource deploymentSource,
+                                                                DC deploymentConfiguration) {
+    Project project = module.getProject();
+
+    String accountName = account.getName();
+
+    String name = generateRunConfigurationName(accountName, module.getName());
+
+    final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
+    ConfigurationFactory configurationFactory = getRunConfigurationType(account.getType()).getConfigurationFactories()[0];
+    final RunnerAndConfigurationSettings runSettings = runManager.createRunConfiguration(name, configurationFactory);
+
+    final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
+
+    result.setServerName(accountName);
+
+    result.setDeploymentSource(deploymentSource);
+
+    result.setDeploymentConfiguration(deploymentConfiguration);
+
+    ((ConfigurationFactoryEx)configurationFactory).onNewConfigurationCreated(runSettings.getConfiguration());
+
+    runManager.addConfiguration(runSettings, false);
+    runManager.setSelectedConfiguration(runSettings);
+
+    return result;
+  }
+
+  private static DeployToServerConfigurationType getRunConfigurationType(ServerType<?> cloudType) {
+    String id = DeployToServerConfigurationType.getId(cloudType);
+    for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
+      if (configurationType instanceof DeployToServerConfigurationType) {
+        DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
+        if (deployConfigurationType.getId().equals(id)) {
+          return deployConfigurationType;
+        }
+      }
+    }
+    return null;
+  }
+
+  private static String generateRunConfigurationName(String serverName, String moduleName) {
+    return CloudBundle.getText("run.configuration.name", serverName, moduleName);
+  }
+}
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
index 41b6a35..f2180d6 100755
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
@@ -24,11 +24,6 @@
   @NotNull
   public abstract BreakpointTarget getTarget();
 
-  /**
-   * Returns line number of the breakpoint. As source is changed (typically with LiveEdit feature,
-   * and particularly by calling {@link ScriptManager#setSourceOnRemote}) this value
-   * may become stale.
-   */
   public abstract int getLine();
 
   /**
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
index 51cf25e..10a2444 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
@@ -26,7 +26,7 @@
   }
 
   @Override
-  public void scriptContentChanged(Script newScript) {
+  public void scriptContentChanged(@NotNull Script newScript) {
   }
 
   @Override
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
index 5b73448..a8038be 100755
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
@@ -50,7 +50,7 @@
   /**
    * Reports that script source has been altered in remote VM.
    */
-  void scriptContentChanged(Script newScript);
+  void scriptContentChanged(@NotNull Script newScript);
 
   /**
    * Reports a navigation event on the target.
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
index befe422..b2ebd33 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
@@ -19,6 +19,7 @@
     return evaluateContext;
   }
 
+  @NotNull
   protected abstract EvaluateContext computeEvaluateContext();
 
   @NotNull
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
index 431a115..c033a69 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
@@ -135,6 +135,10 @@
     }
 
     List<String> sources = readSources(sourcesReader, sourceRoot);
+    if (sources.isEmpty()) {
+      // empty map, meteor can report such ugly maps
+      return null;
+    }
 
     @SuppressWarnings("unchecked")
     List<MappingEntry>[] reverseMappingsBySourceUrl = new List[sources.size()];
diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
index e558f4b..25b8b3e 100644
--- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
+++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
@@ -21,24 +21,24 @@
 
   private final ObjectValue value;
 
-  private final int start;
-  private final int end;
+  private final int startInclusive;
+  private final int endInclusive;
   private final VariableContext context;
 
   private final ValueType componentType;
   private final boolean sparse;
 
-  public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context) {
-    this(value, start, end, context, null, true);
+  public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context) {
+    this(value, startInclusive, endInclusive, context, null, true);
   }
 
-  public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) {
-    super(String.format("[%,d \u2026 %,d]", start, end));
+  public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) {
+    super(String.format("[%,d \u2026 %,d]", startInclusive, endInclusive));
 
     this.value = value;
 
-    this.start = start;
-    this.end = end;
+    this.startInclusive = startInclusive;
+    this.endInclusive = endInclusive;
 
     this.context = context;
 
@@ -51,18 +51,17 @@
     node.setAlreadySorted(true);
 
     int bucketThreshold = XCompositeNode.MAX_CHILDREN_TO_SHOW;
-    int size = end - start;
-    if (!sparse && size > bucketThreshold) {
-      node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, start, end, bucketThreshold)), true);
+    if (!sparse && (endInclusive - startInclusive) > bucketThreshold) {
+      node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, startInclusive, endInclusive + 1, bucketThreshold)), true);
       return;
     }
 
-    value.getIndexedProperties(start, end + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) {
+    value.getIndexedProperties(startInclusive, endInclusive + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) {
       @Override
       public void consumeRanges(@Nullable int[] ranges) {
         if (ranges == null) {
           XValueChildrenList groupList = new XValueChildrenList();
-          addGroups(value, GROUP_FACTORY, groupList, start, end, XCompositeNode.MAX_CHILDREN_TO_SHOW, context);
+          addGroups(value, GROUP_FACTORY, groupList, startInclusive, endInclusive, XCompositeNode.MAX_CHILDREN_TO_SHOW, context);
           node.addChildren(groupList, true);
         }
         else {
@@ -78,12 +77,12 @@
   }
 
   @NotNull
-  public static List<XValueGroup> computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int from, int to, int bucketThreshold) {
-    int size = to - from;
+  public static List<XValueGroup> computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int fromInclusive, int toExclusive, int bucketThreshold) {
+    int size = toExclusive - fromInclusive;
     int bucketSize = (int)Math.pow(bucketThreshold, Math.ceil(Math.log(size) / Math.log(bucketThreshold)) - 1);
     List<XValueGroup> groupList = new ArrayList<XValueGroup>((int)Math.ceil(size / bucketSize));
-    for (; from < to; from += bucketSize) {
-      groupList.add(new LazyVariablesGroup(value, from, from + (Math.min(bucketSize, to - from) - 1), context, ValueType.NUMBER, false));
+    for (; fromInclusive < toExclusive; fromInclusive += bucketSize) {
+      groupList.add(new LazyVariablesGroup(value, fromInclusive, fromInclusive + (Math.min(bucketSize, toExclusive - fromInclusive) - 1), context, ValueType.NUMBER, false));
     }
     return groupList;
   }
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
index 8c71759..3f4b8ea 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
@@ -2,6 +2,7 @@
 
 abstract class BoxableType {
   static final BoxableType STRING = new StandaloneType(new NamePath("String"), "writeString");
+  static final BoxableType ANY_STRING = new StandaloneType(new NamePath("String"), "writeString");
   static final BoxableType INT = new StandaloneType(new NamePath("int"), "writeInt");
   static final BoxableType LONG = new StandaloneType(new NamePath("long"), "writeLong");
   static final BoxableType NUMBER = new StandaloneType(new NamePath("double"), "writeDouble");
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
index 6b27866..31ba16f 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
@@ -20,10 +20,6 @@
     return contextNamespace.getLastComponent();
   }
 
-  String getFullName() {
-    return contextNamespace.getFullText();
-  }
-
   NamePath getClassContextNamespace() {
     return contextNamespace;
   }
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
index b74c73e..6798629 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
@@ -153,7 +153,7 @@
           }
 
           @Override
-          public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+          public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
             throw new UnsupportedOperationException();
           }
 
@@ -162,8 +162,7 @@
             throw new UnsupportedOperationException();
           }
         };
-        QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope);
-        BoxableType itemBoxableType = itemTypeData.getJavaType();
+        BoxableType itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).getType();
 
         final BoxableType arrayType = new ListType(itemBoxableType);
         StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() {
@@ -178,7 +177,7 @@
     });
   }
 
-  StandaloneTypeBinding createStandaloneObjectInputTypeBinding(final ProtocolMetaModel.StandaloneType type, final List<ProtocolMetaModel.ObjectProperty> properties) {
+  StandaloneTypeBinding createStandaloneObjectInputTypeBinding(@NotNull final ProtocolMetaModel.StandaloneType type, @Nullable final List<ProtocolMetaModel.ObjectProperty> properties) {
     final String name = type.id();
     final NamePath fullTypeName = generator.getNaming().inputValue.getFullName(domain.domain(), name);
     generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText());
@@ -198,10 +197,12 @@
           out.doc(type.description());
         }
 
-        out.append("@org.chromium.protocolReader.JsonType").newLine();
+        out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
         out.append("public interface ").append(className.getLastComponent()).openBlock();
         InputClassScope classScope = new InputClassScope(DomainGenerator.this, className);
-        classScope.generateStandaloneTypeBody(out, properties);
+        if (properties != null) {
+          classScope.generateDeclarationBody(out, properties);
+        }
         classScope.writeAdditionalMembers(out);
         out.closeBlock();
         fileUpdater.update();
@@ -309,16 +310,18 @@
     fileUpdater.update();
   }
 
-  private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) throws IOException {
+  private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) {
     if (description != null) {
       out.doc(description);
     }
-    out.append("@org.chromium.protocolReader.JsonType").newLine().append("public interface ").append(className).openBlock();
+    out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock();
     InputClassScope classScope = new InputClassScope(this, new NamePath(className, new NamePath(ClassNameScheme.getPackageName(generator.getNaming().inputPackage, domain.domain()))));
     if (additionalMembersText != null) {
       classScope.addMember(additionalMembersText);
     }
-    classScope.generateMainJsonProtocolInterfaceBody(out, parameters);
+    if (parameters != null) {
+      classScope.generateDeclarationBody(out, parameters);
+    }
     classScope.writeAdditionalMembers(out);
     out.closeBlock();
   }
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
index e545f02..b02905a 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
@@ -114,92 +114,61 @@
     fileSet.deleteOtherFiles();
   }
 
-  QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) {
-    UnqualifiedTypeData unqualifiedType = switchByType(typedObject, new TypeVisitor<UnqualifiedTypeData>() {
+  TypeDescriptor resolveType(@NotNull final ItemDescriptor typedObject, @NotNull final ResolveAndGenerateScope scope) {
+    final boolean optional = typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional();
+    return switchByType(typedObject, new TypeVisitor<TypeDescriptor>() {
       @Override
-      public UnqualifiedTypeData visitRef(String refName) {
-        return new UnqualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()));
+      public TypeDescriptor visitRef(String refName) {
+        return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitBoolean() {
-        return UnqualifiedTypeData.BOOLEAN;
+      public TypeDescriptor visitBoolean() {
+        return new TypeDescriptor(BoxableType.BOOLEAN, optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitEnum(List<String> enumConstants) {
+      public TypeDescriptor visitEnum(List<String> enumConstants) {
         assert scope instanceof MemberScope;
-        return new UnqualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants));
+        return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitString() {
-        return UnqualifiedTypeData.STRING;
+      public TypeDescriptor visitString() {
+        return new TypeDescriptor(BoxableType.STRING, optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitInteger() {
-        return UnqualifiedTypeData.INT;
+      public TypeDescriptor visitInteger() {
+        return new TypeDescriptor(BoxableType.INT, optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitNumber() {
-        return UnqualifiedTypeData.NUMBER;
+      public TypeDescriptor visitNumber() {
+        return new TypeDescriptor(BoxableType.NUMBER, optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitMap() {
-        return UnqualifiedTypeData.MAP;
+      public TypeDescriptor visitMap() {
+        return new TypeDescriptor(BoxableType.MAP, optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitArray(ArrayItemType items) {
-        return new UnqualifiedTypeData(new ListType(scope.resolveType(items).getJavaType()));
+      public TypeDescriptor visitArray(ArrayItemType items) {
+        BoxableType type = scope.resolveType(items).getType();
+        return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING);
       }
 
       @Override
-      public UnqualifiedTypeData visitObject(List<ObjectProperty> properties) {
-        return new UnqualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), false);
+      public TypeDescriptor visitObject(List<ObjectProperty> properties) {
+        return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional);
       }
 
       @Override
-      public UnqualifiedTypeData visitUnknown() {
-        return UnqualifiedTypeData.ANY;
+      public TypeDescriptor visitUnknown() {
+        return new TypeDescriptor(BoxableType.STRING, optional, false, true);
       }
     });
-
-    return unqualifiedType.getQualifiedType(typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional());
-  }
-
-  private static class UnqualifiedTypeData {
-    private final BoxableType typeRef;
-    private final boolean nullable;
-    private final boolean asRawString;
-
-    UnqualifiedTypeData(BoxableType typeRef) {
-      this(typeRef, false);
-    }
-
-    UnqualifiedTypeData(BoxableType typeRef, boolean nullable) {
-      this(typeRef, nullable, false);
-    }
-
-    UnqualifiedTypeData(BoxableType typeRef, boolean nullable, boolean asRawString) {
-      this.typeRef = typeRef;
-      this.nullable = nullable;
-      this.asRawString = asRawString;
-    }
-
-    QualifiedTypeData getQualifiedType(boolean optional) {
-      return new QualifiedTypeData(typeRef, optional, nullable, asRawString);
-    }
-
-    static final UnqualifiedTypeData BOOLEAN = new UnqualifiedTypeData(BoxableType.BOOLEAN, false);
-    static final UnqualifiedTypeData STRING = new UnqualifiedTypeData(BoxableType.STRING, false);
-    static final UnqualifiedTypeData INT = new UnqualifiedTypeData(BoxableType.INT, false);
-    static final UnqualifiedTypeData MAP = new UnqualifiedTypeData(BoxableType.MAP, false);
-    static final UnqualifiedTypeData NUMBER = new UnqualifiedTypeData(BoxableType.NUMBER, false);
-    static final UnqualifiedTypeData ANY = new UnqualifiedTypeData(BoxableType.STRING, false, true);
   }
 
   private void generateParserInterfaceList() throws IOException {
@@ -274,11 +243,11 @@
     return typeMap.resolve(domainName, shortName, direction);
   }
 
-  static String generateMethodNameSubstitute(String originalName, TextOutput out) {
+  static String generateMethodNameSubstitute(@NotNull String originalName, @NotNull TextOutput out) {
     if (!BAD_METHOD_NAMES.contains(originalName)) {
       return originalName;
     }
-    out.append("@org.chromium.protocolReader.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
+    out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
     return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1);
   }
 
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
index 9411f4d..99c95d8 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
@@ -1,8 +1,9 @@
 package org.jetbrains.protocolReader;
 
-import org.jetbrains.jsonProtocol.ProtocolMetaModel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jsonProtocol.ItemDescriptor.Named;
+import org.jetbrains.jsonProtocol.ProtocolMetaModel.ObjectProperty;
 
-import java.io.IOException;
 import java.util.List;
 
 class InputClassScope extends ClassScope {
@@ -10,36 +11,20 @@
     super(generator, namePath);
   }
 
-  public void generateMainJsonProtocolInterfaceBody(TextOutput out, List<ProtocolMetaModel.Parameter> parameters) throws IOException {
-    if (parameters != null) {
-      for (ProtocolMetaModel.Parameter parameter : parameters) {
-        if (parameter.description() != null) {
-          out.doc(parameter.description());
-        }
-
-        String methodName = Generator.generateMethodNameSubstitute(getName(parameter), out);
-        QualifiedTypeData paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter);
-        paramTypeData.writeAnnotations(out);
-        out.append(paramTypeData.getJavaType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine();
+  void generateDeclarationBody(@NotNull TextOutput out, @NotNull List<? extends Named> list) {
+    for (int i = 0, n = list.size(); i < n; i++) {
+      Named named = list.get(i);
+      if (named.description() != null) {
+        out.doc(named.description());
       }
-    }
-  }
 
-  void generateStandaloneTypeBody(TextOutput out, List<ProtocolMetaModel.ObjectProperty> properties) throws IOException {
-    if (properties != null) {
-      for (ProtocolMetaModel.ObjectProperty objectProperty : properties) {
-        String propertyName = getName(objectProperty);
-
-        if (objectProperty.description() != null) {
-          out.doc(objectProperty.description());
-        }
-
-        String methodName = Generator.generateMethodNameSubstitute(propertyName, out);
-        MemberScope memberScope = newMemberScope(propertyName);
-        QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty);
-        propertyTypeData.writeAnnotations(out);
-
-        out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
+      String name = getName(named);
+      String declarationName = Generator.generateMethodNameSubstitute(name, out);
+      TypeDescriptor typeDescriptor = new InputMemberScope(name).resolveType(named);
+      typeDescriptor.writeAnnotations(out);
+      out.append(typeDescriptor.getType().getShortText(getClassContextNamespace())).space().append(declarationName).append("();");
+      if (i != (n - 1)) {
+        out.newLine().newLine();
       }
     }
   }
@@ -49,10 +34,6 @@
     return TypeData.Direction.INPUT;
   }
 
-  private MemberScope newMemberScope(String memberName) {
-    return new InputMemberScope(memberName);
-  }
-
   class InputMemberScope extends MemberScope {
     InputMemberScope(String memberName) {
       super(InputClassScope.this, memberName);
@@ -72,28 +53,28 @@
     }
 
     @Override
-    public BoxableType generateNestedObject(final String description, final List<ProtocolMetaModel.ObjectProperty> propertyList) {
+    public BoxableType generateNestedObject(final String description, final List<ObjectProperty> propertyList) {
       final String objectName = Generator.capitalizeFirstChar(getMemberName());
       addMember(new TextOutConsumer() {
         @Override
         public void append(TextOutput out) {
           out.newLine().doc(description);
           if (propertyList == null) {
-            out.append("@org.chromium.protocolReader.JsonType(allowsOtherProperties=true)").newLine();
+            out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine();
             out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock();
           }
           else {
-            out.append("@org.chromium.protocolReader.JsonType").newLine();
+            out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
             out.append("public interface ").append(objectName).openBlock();
-            for (ProtocolMetaModel.ObjectProperty property : propertyList) {
+            for (ObjectProperty property : propertyList) {
               out.doc(property.description());
 
               String methodName = Generator.generateMethodNameSubstitute(getName(property), out);
-              MemberScope memberScope = newMemberScope(getName(property));
-              QualifiedTypeData propertyTypeData = memberScope.resolveType(property);
+              MemberScope memberScope = new InputMemberScope(getName(property));
+              TypeDescriptor propertyTypeData = memberScope.resolveType(property);
               propertyTypeData.writeAnnotations(out);
 
-              out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
+              out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
             }
           }
           out.closeBlock();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
index 21de2ca..78a83a9 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
@@ -19,7 +19,7 @@
   }
 
   @Override
-  public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+  public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
     return classScope.generator.generator.resolveType(typedObject, this);
   }
 
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
index e867bf9..90b7068 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
@@ -60,7 +60,7 @@
           }
 
           @Override
-          public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+          public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
             throw new UnsupportedOperationException();
           }
 
@@ -68,7 +68,7 @@
           public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> properties) {
             return context.generateNestedObject("Item", description, properties);
           }
-        }).getJavaType());
+        }).getType());
       }
     }, generator.generator.getNaming().outputTypedef, TypeData.Direction.OUTPUT);
   }
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
index fa7f4f1..f88a55d 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
@@ -19,8 +19,8 @@
       return;
     }
 
-    List<P> mandatoryParameters = new ArrayList<P>();
-    List<P> optionalParameters = new ArrayList<P>();
+    List<P> mandatoryParameters = new ArrayList<>();
+    List<P> optionalParameters = new ArrayList<>();
     for (P parameter : parameters) {
       if (parameter.optional()) {
         optionalParameters.add(parameter);
@@ -34,8 +34,8 @@
       generateConstructor(out, mandatoryParameters, null);
       if (mandatoryParameters.size() == 1) {
         P parameter = mandatoryParameters.get(0);
-        QualifiedTypeData typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
-        if (typeData.getJavaType().getFullText().equals("int[]")) {
+        TypeDescriptor typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
+        if (typeData.getType().getFullText().equals("int[]")) {
           BoxableType[] types = new BoxableType[mandatoryParameters.size()];
           types[0] = new ListType(BoxableType.INT) {
             @Override
@@ -94,7 +94,7 @@
         out.append("/**").newLine().append(" * @param v ").append(parameter.description()).newLine().append(" */").newLine();
       }
 
-      CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType().getShortText(getClassContextNamespace());
+      CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType().getShortText(getClassContextNamespace());
       if (type.equals(JsonReaderEx.class.getCanonicalName())) {
         type = "String";
       }
@@ -131,9 +131,10 @@
       mandatoryParameterTypes = new BoxableType[mandatoryParameters.size()];
     }
     for (int i = 0, length = mandatoryParameterTypes.length; i < length; i++) {
+      assert mandatoryParameterTypes != null;
       if (mandatoryParameterTypes[i] == null) {
         P parameter = mandatoryParameters.get(i);
-        mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
+        mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
       }
     }
 
@@ -144,6 +145,7 @@
         out.comma();
       }
 
+      assert mandatoryParameterTypes != null;
       out.append(mandatoryParameterTypes[i].getShortText(getClassContextNamespace()));
       out.space().append(parameter.name());
       needComa = true;
@@ -152,6 +154,7 @@
     for (int i = 0, size = mandatoryParameters.size(); i < size; i++) {
       P parameter = mandatoryParameters.get(i);
       out.newLine();
+      assert mandatoryParameterTypes != null;
       appendWriteValueInvocation(out, parameter, parameter.name(), mandatoryParameterTypes[i]);
     }
     out.closeBlock();
@@ -159,7 +162,7 @@
 
   private void appendWriteValueInvocation(TextOutput out, ItemDescriptor.Named parameter, String valueRefName, @Nullable BoxableType type) {
     if (type == null) {
-      type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
+      type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
     }
 
     boolean blockOpened = false;
@@ -188,7 +191,7 @@
     }
     // todo CallArgument (we should allow write null as value)
     out.append(parameter.name().equals("value") && type.getWriteMethodName().equals("writeString") ? "writeNullableString" : type.getWriteMethodName()).append("(");
-    out.quoute(parameter.name()).comma().append(valueRefName).append(");");
+    out.quote(parameter.name()).comma().append(valueRefName).append(");");
     if (blockOpened) {
       out.closeBlock();
     }
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
index e3e8049..e84c641 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
@@ -18,7 +18,7 @@
   }
 
   void writeCode(TextOutput out) throws IOException {
-    out.append("@org.chromium.protocolReader.JsonParseMethod").newLine();
+    out.append("@org.jetbrains.jsonProtocol.JsonParseMethod").newLine();
     out.append("public abstract ").append(fullName).space();
     appendReadMethodName(out);
     out.append("(").append(Util.JSON_READER_PARAMETER_DEF).append(")").semi().newLine();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java
deleted file mode 100644
index a4ccd0b..0000000
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.jetbrains.protocolReader;
-
-class QualifiedTypeData {
-  private final BoxableType typeRef;
-  private final boolean optional;
-  private final boolean nullable;
-  private final boolean asRawString;
-
-  QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) {
-    this.typeRef = typeRef;
-    this.optional = optional;
-    this.nullable = nullable;
-    this.asRawString = asRawString;
-  }
-
-  boolean isNullable() {
-    return nullable;
-  }
-
-  BoxableType getJavaType() {
-    return typeRef;
-  }
-
-  void writeAnnotations(TextOutput out) {
-    if (optional || asRawString) {
-      out.append("@org.chromium.protocolReader.JsonField(");
-      if (optional) {
-        out.append("optional=true");
-      }
-      if (asRawString) {
-        if (optional) {
-          out.append(", ");
-        }
-        out.append("allowAnyPrimitiveValue=true");
-      }
-      out.append(")").newLine();
-    }
-
-    if (isNullable()) {
-      out.append("@org.chromium.protocolReader.JsonNullable").newLine();
-    }
-  }
-}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
index 8f117d0..c43c9ff 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
@@ -9,7 +9,7 @@
   String getDomainName();
   TypeData.Direction getTypeDirection();
 
-  <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject);
+  <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject);
 
   BoxableType generateNestedObject(String description,
                                    List<ProtocolMetaModel.ObjectProperty> properties);
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
index 0ab11a0..7fbc5f6 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
@@ -4,6 +4,21 @@
 import org.jetbrains.jsonProtocol.ProtocolMetaModel;
 
 class TypeData {
+  public static final StandaloneTypeBinding ANY = new StandaloneTypeBinding() {
+    @Override
+    public BoxableType getJavaType() {
+      return BoxableType.ANY_STRING;
+    }
+
+    @Override
+    public void generate() {
+    }
+
+    @Override
+    public Direction getDirection() {
+      return null;
+    }
+  };
   private final String name;
 
   private Input input;
@@ -119,21 +134,7 @@
           };
         }
         else if (name.equals("any")) {
-          return new StandaloneTypeBinding() {
-            @Override
-            public BoxableType getJavaType() {
-              return BoxableType.STRING;
-            }
-
-            @Override
-            public void generate() {
-            }
-
-            @Override
-            public Direction getDirection() {
-              return null;
-            }
-          };
+          return ANY;
         }
 
         throw new RuntimeException();
@@ -164,21 +165,7 @@
           };
         }
         else if (name.equals("any")) {
-          return new StandaloneTypeBinding() {
-            @Override
-            public BoxableType getJavaType() {
-              return BoxableType.STRING;
-            }
-
-            @Override
-            public void generate() {
-            }
-
-            @Override
-            public Direction getDirection() {
-              return null;
-            }
-          };
+          return ANY;
         }
 
         throw new RuntimeException();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java
new file mode 100644
index 0000000..d142e8b
--- /dev/null
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java
@@ -0,0 +1,50 @@
+package org.jetbrains.protocolReader;
+
+import org.jetbrains.annotations.NotNull;
+
+class TypeDescriptor {
+  private final BoxableType type;
+  private final boolean optional;
+  private final boolean nullable;
+  private final boolean asRawString;
+
+  TypeDescriptor(@NotNull BoxableType type, boolean optional) {
+    this(type, optional, false, false);
+  }
+
+  TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) {
+    this.type = type;
+    this.optional = optional;
+    this.nullable = nullable;
+    this.asRawString = asRawString;
+  }
+
+  boolean isNullable() {
+    return nullable;
+  }
+
+  @NotNull
+  BoxableType getType() {
+    return type;
+  }
+
+  void writeAnnotations(@NotNull TextOutput out) {
+    if (optional || asRawString) {
+      out.append("@org.jetbrains.jsonProtocol.JsonField(");
+      if (optional) {
+        out.append("optional=true");
+      }
+      if (asRawString) {
+        if (optional) {
+          out.append(", ");
+        }
+        out.append("allowAnyPrimitiveValue=true");
+      }
+      out.append(")").newLine();
+    }
+
+    if (isNullable()) {
+      out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine();
+    }
+  }
+}
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java
similarity index 96%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java
index 5dfa26c..3b960b8 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -25,6 +25,7 @@
 
   // read any primitive value as String (true as true, number as string - don't try to parse)
   boolean allowAnyPrimitiveValue() default false;
+
   boolean allowAnyPrimitiveValueAndMap() default false;
 
   boolean optional() default false;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java
similarity index 93%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java
index bbaa82a..8e88ab4 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java
similarity index 93%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java
index a2ede48..92c9cd9 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java
similarity index 91%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java
index c964e80..8016b9b 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
index aa1d19f..056e4dc 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
@@ -234,7 +234,7 @@
     return list;
   }
 
-  public static List<String> readListOfPrimitive(JsonReaderEx reader) {
+  public static List<String> readRawStringArray(JsonReaderEx reader) {
     reader.beginArray();
     if (!reader.hasNext()) {
       reader.endArray();
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java
similarity index 92%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java
index f104d74..b40d4a1 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 /**
  * A base interface for JSON subtype interface. This inheritance serves 2 purposes:
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java
similarity index 94%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java
index 0527551..cc59fed 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java
similarity index 96%
rename from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java
rename to platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java
index 62e2c8c..79dc453 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
index eabc8d8..111e58c 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
@@ -1,6 +1,9 @@
 package org.jetbrains.protocolReader;
 
-import org.chromium.protocolReader.*;
+import org.jetbrains.jsonProtocol.JsonField;
+import org.jetbrains.jsonProtocol.JsonNullable;
+import org.jetbrains.jsonProtocol.JsonOptionalField;
+import org.jetbrains.jsonProtocol.JsonSubtypeCasting;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
index f80b8c5..cc4e256 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
@@ -1,10 +1,10 @@
 package org.jetbrains.protocolReader;
 
 import gnu.trove.THashSet;
-import org.chromium.protocolReader.JsonField;
-import org.chromium.protocolReader.JsonSubtype;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.io.JsonReaderEx;
+import org.jetbrains.jsonProtocol.JsonField;
+import org.jetbrains.jsonProtocol.JsonSubtype;
 import org.jetbrains.jsonProtocol.StringIntPair;
 
 import java.lang.annotation.RetentionPolicy;
@@ -249,7 +249,7 @@
             argumentType = wildcard.getUpperBounds()[0];
           }
         }
-        return new ArrayReader(getFieldTypeParser(argumentType, false, false, null), true, declaredNullable);
+        return new ArrayReader(getFieldTypeParser(argumentType, false, false, method), true, declaredNullable);
       }
       else if (parameterizedType.getRawType() == Map.class) {
         return declaredNullable ? NULLABLE_MAP_PARSER : MAP_PARSER;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
index a76971d..7914a51 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
@@ -2,7 +2,7 @@
 
 import org.jetbrains.io.JsonReaderEx;
 import gnu.trove.THashSet;
-import org.chromium.protocolReader.JsonParseMethod;
+import org.jetbrains.jsonProtocol.JsonParseMethod;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
index cd5afa1..77d4bd1 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
@@ -9,7 +9,7 @@
   private int identLevel;
   private final static int indentGranularity = 2;
   private char[][] indents = {EMPTY_CHARS};
-  private boolean justNewlined;
+  private boolean justNewLined;
   private final StringBuilder out;
 
   public TextOutput(StringBuilder out) {
@@ -41,7 +41,7 @@
 
   public TextOutput newLine() {
     out.append('\n');
-    justNewlined = true;
+    justNewLined = true;
     return this;
   }
 
@@ -122,14 +122,14 @@
     return append("/**").newLine().append(" * ").append(description).newLine().append(" */").newLine();
   }
 
-  public TextOutput quoute(CharSequence s) {
+  public TextOutput quote(CharSequence s) {
     return append('"').append(s).append('"');
   }
 
   public void maybeIndent() {
-    if (justNewlined) {
+    if (justNewLined) {
       out.append(indents[identLevel]);
-      justNewlined = false;
+      justNewLined = false;
     }
   }
 }
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
index 7ef6b3e..4421676 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
@@ -1,7 +1,3 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
 package org.jetbrains.protocolReader;
 
 import org.jetbrains.annotations.Nullable;
@@ -51,7 +47,7 @@
         out.append("name");
       }
       else {
-        out.quoute(fieldName);
+        out.quote(fieldName);
       }
     }
   }
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
index 26dbd72..d6f5afc 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
@@ -1,7 +1,5 @@
 package org.jetbrains.jsonProtocol;
 
-import org.chromium.protocolReader.JsonOptionalField;
-
 import java.util.List;
 
 public interface ItemDescriptor {
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
index c08c50c..a4aeeec 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
@@ -1,9 +1,5 @@
 package org.jetbrains.jsonProtocol;
 
-import org.chromium.protocolReader.JsonField;
-import org.chromium.protocolReader.JsonOptionalField;
-import org.chromium.protocolReader.JsonType;
-
 import java.util.List;
 
 /**
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
index 50aeebb..aafe735 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
@@ -5,7 +5,6 @@
 package org.jetbrains.jsonProtocol;
 
 import org.jetbrains.io.JsonReaderEx;
-import org.chromium.protocolReader.JsonParseMethod;
 import org.jetbrains.jsonProtocol.ProtocolMetaModel.Root;
 
 import java.io.IOException;
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
index 8532b9a..b77acd9 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
@@ -273,7 +273,11 @@
   public void onTestFailure(@NotNull final TestFailedEvent testFailedEvent) {
     addToInvokeLater(new Runnable() {
       public void run() {
-        final String testName = ObjectUtils.assertNotNull(testFailedEvent.getName());
+        final String testName = testFailedEvent.getName();
+        if (testName == null) {
+          logProblem("No test name specified in " + testFailedEvent);
+          return;
+        }
         final String localizedMessage = testFailedEvent.getLocalizedFailureMessage();
         final String stackTrace = testFailedEvent.getStacktrace();
         final boolean isTestError = testFailedEvent.isTestError();
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
index d454ae0..5d4cf54 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
@@ -18,6 +18,7 @@
 import org.jetbrains.annotations.NotNull;
 import com.intellij.execution.testframework.sm.runner.SMTestProxy;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -42,7 +43,7 @@
     }
 
      //Test suit fails if any of its tests fails
-    final List<? extends SMTestProxy> children = mySuiteProxy.getChildren();
+    final List<? extends SMTestProxy> children = new ArrayList<SMTestProxy>(mySuiteProxy.getChildren());
     for (SMTestProxy child : children) {
       if (child.isDefect()) {
         myDefectFound = true;
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
index 565f80a..70c1cdc 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
@@ -82,7 +82,7 @@
   public boolean isRealTypedVar(PsiElement element) {
     if (element!=null && element.getTextLength()>0) {
       String str = getTypedVarString(element);
-      if (str.length()==0) {
+      if (str == null || str.length()==0) {
         return false;
       }
       return isTypedVar( str );
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
index e290ebb..6dba855 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
@@ -272,12 +272,8 @@
 
     element.accept(new PsiRecursiveElementWalkingVisitor() {
       @Override
-      public void visitElement(PsiElement element) {
-        super.visitElement(element);
-
-        if (!(element instanceof PsiErrorElement)) {
-          return;
-        }
+      public void visitErrorElement(PsiErrorElement element) {
+        super.visitErrorElement(element);
 
         final int startOffset = element.getTextRange().getStartOffset();
 
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
index 368240f..f82ad12 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
@@ -22,7 +22,6 @@
 import com.intellij.openapi.ui.ComponentWithBrowseButton;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiFile;
@@ -36,8 +35,6 @@
 import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
 import com.intellij.ui.ComboboxWithBrowseButton;
 import com.intellij.ui.EditorTextField;
-import com.intellij.ui.components.labels.LinkLabel;
-import com.intellij.ui.components.labels.LinkListener;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
@@ -46,7 +43,6 @@
 import javax.swing.event.ChangeListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
-import javax.swing.text.BadLocationException;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -117,7 +113,7 @@
     withinCombo.getComboBox().setEditable(true);
 
     withinCombo.getButton().addActionListener(new ActionListener() {
-      public void actionPerformed(final ActionEvent e) {
+      public void actionPerformed(@NotNull final ActionEvent e) {
         final SelectTemplateDialog dialog = new SelectTemplateDialog(project, false, false);
         dialog.show();
         if (dialog.getExitCode() == OK_EXIT_CODE) {
@@ -191,7 +187,7 @@
       new ListSelectionListener() {
         boolean rollingBackSelection;
 
-        public void valueChanged(ListSelectionEvent e) {
+        public void valueChanged(@NotNull ListSelectionEvent e) {
           if (e.getValueIsAdjusting()) return;
           if (rollingBackSelection) {
             rollingBackSelection=false;
@@ -212,7 +208,7 @@
 
     parameterList.setCellRenderer(
       new DefaultListCellRenderer() {
-        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        public Component getListCellRendererComponent(@NotNull JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
           String name = ((Variable)value).getName();
           if (Configuration.CONTEXT_VAR_NAME.equals(name)) name = SSRBundle.message("complete.match.variable.name");
           if (isReplacementVariable(name)) {
@@ -226,7 +222,7 @@
     maxoccursUnlimited.addChangeListener(new MyChangeListener(maxoccurs, true));
 
     customScriptCode.getButton().addActionListener(new ActionListener() {
-      public void actionPerformed(final ActionEvent e) {
+      public void actionPerformed(@NotNull final ActionEvent e) {
         final EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText());
         dialog.show();
         if (dialog.getExitCode() == OK_EXIT_CODE) {
@@ -505,18 +501,7 @@
     formalArgType = createRegexComponent();
     customScriptCode = new ComponentWithBrowseButton<EditorTextField>(createScriptComponent(), null);
 
-    myRegExHelpLabel = new LinkLabel(SSRBundle.message("regular.expression.help.label"), null, new LinkListener() {
-      public void linkSelected(LinkLabel aSource, Object aLinkData) {
-        try {
-          final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup();
-          helpPopup.showInCenterOf(mainForm);
-        }
-        catch (BadLocationException e) {
-          LOG.info(e);
-        }
-      }
-    });
-
+    myRegExHelpLabel = RegExHelpPopup.createRegExLink(SSRBundle.message("regular.expression.help.label"), regexp, LOG);
     myRegExHelpLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
   }
 
@@ -559,7 +544,7 @@
       inverted = _inverted;
     }
 
-    public void stateChanged(ChangeEvent e) {
+    public void stateChanged(@NotNull ChangeEvent e) {
       final JCheckBox jCheckBox = (JCheckBox)e.getSource();
       component.setEnabled(inverted ^ jCheckBox.isSelected());
     }
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
index 32f1302..ecdccbe 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
@@ -1,6 +1,6 @@
 package com.intellij.structuralsearch.plugin.ui;
 
-import com.intellij.codeInsight.hint.TooltipGroup;
+import com.intellij.codeInsight.hint.TooltipController;
 import com.intellij.codeInsight.template.impl.TemplateImplUtil;
 import com.intellij.codeInsight.template.impl.Variable;
 import com.intellij.openapi.editor.Document;
@@ -11,7 +11,6 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 
 /**
  * Created by IntelliJ IDEA.
@@ -21,7 +20,6 @@
  * To change this template use File | Settings | File Templates.
  */
 public class SubstitutionShortInfoHandler implements DocumentListener, EditorMouseMotionListener, CaretListener {
-  private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0);
 
   private long modificationTimeStamp;
   private final ArrayList<Variable> variables = new ArrayList<Variable>();
@@ -63,9 +61,7 @@
         String varname = elements.subSequence(start + 1, end).toString();
         Variable foundVar = null;
 
-        for(Iterator<Variable> i=variables.iterator();i.hasNext();) {
-          final Variable var = i.next();
-
+        for (final Variable var : variables) {
           if (var.getName().equals(varname)) {
             foundVar = var;
             break;
@@ -79,7 +75,10 @@
     }
 
     if (text.length() > 0) {
-      UIUtil.showTooltip(editor, start, end, text, SS_INFO_TOOLTIP_GROUP);
+      UIUtil.showTooltip(editor, start, end + 1, text);
+    }
+    else {
+      TooltipController.getInstance().cancelTooltips();
     }
   }
 
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
index aa3ca82..e2c16bf 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
@@ -15,17 +15,14 @@
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.ex.EditorEx;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
 import com.intellij.structuralsearch.*;
 import com.intellij.structuralsearch.plugin.StructuralReplaceAction;
 import com.intellij.structuralsearch.plugin.StructuralSearchAction;
 import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
-import com.intellij.structuralsearch.plugin.util.SmartPsiPointer;
+import com.intellij.ui.HintHint;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -41,6 +38,7 @@
 public class UIUtil {
   static Key<SubstitutionShortInfoHandler> LISTENER_KEY = Key.create("sslistener.key");
   private static final String MODIFY_EDITOR_CONTENT = SSRBundle.message("modify.editor.content.command.name");
+  private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0);
   @NonNls private static final String SS_GROUP = "structuralsearchgroup";
 
   @NotNull
@@ -191,18 +189,6 @@
     buf.append(str);
   }
 
-  public static void navigate(PsiElement result) {
-    FileEditorManager.getInstance(result.getProject()).openTextEditor(
-        new OpenFileDescriptor(result.getProject(), result.getContainingFile().getVirtualFile(), result.getTextOffset()), true);
-  }
-
-  public static void navigate(MatchResult result) {
-    final SmartPsiPointer ref = result.getMatchRef();
-
-    FileEditorManager.getInstance(ref.getProject())
-        .openTextEditor(new OpenFileDescriptor(ref.getProject(), ref.getFile(), ref.getOffset()), true);
-  }
-
   public static void invokeAction(Configuration config, SearchContext context) {
     if (config instanceof SearchConfiguration) {
       StructuralSearchAction.triggerAction(config, context);
@@ -212,22 +198,27 @@
     }
   }
 
-  static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text, @NotNull TooltipGroup group) {
-    Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
-    Point top = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start));
+  static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text) {
+    final Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
+    final Point left = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start));
     final int documentLength = editor.getDocument().getTextLength();
     if (end >= documentLength) end = documentLength;
-    Point bottom = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end));
+    final Point right = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end));
 
-    Point bestPoint = new Point(top.x, bottom.y + editor.getLineHeight());
+    final Point bestPoint = new Point(left.x + (right.x - left.x) / 2, right.y + editor.getLineHeight() / 2);
 
-    if (!visibleArea.contains(bestPoint)) {
-      int defaultOffset = editor.logicalPositionToOffset(editor.xyToLogicalPosition(new Point(0, 0)));
-      bestPoint = editor.logicalPositionToXY(editor.offsetToLogicalPosition(defaultOffset));
+    if (visibleArea.x > bestPoint.x) {
+      bestPoint.x = visibleArea.x;
+    }
+    else if (visibleArea.x + visibleArea.width < bestPoint.x) {
+      bestPoint.x = visibleArea.x + visibleArea.width - 5;
     }
 
-    Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint, editor.getComponent().getRootPane().getLayeredPane());
-    TooltipController.getInstance().showTooltip(editor, p, text, false, group);
+    final Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint,
+                                                editor.getComponent().getRootPane().getLayeredPane());
+    final HintHint hint = new HintHint(editor, bestPoint).setAwtTooltip(true).setHighlighterType(true)
+      .setCalloutShift(editor.getLineHeight() / 2 - 1);
+    TooltipController.getInstance().showTooltip(editor, p, text, visibleArea.width, false, SS_INFO_TOOLTIP_GROUP, hint);
   }
 
   public static void updateHighlighter(Editor editor, StructuralSearchProfile profile) {
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
index afd2ae1..a55a16d 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
@@ -1,13 +1,13 @@
 package com.intellij.structuralsearch.plugin.ui;
 
 import com.intellij.navigation.ItemPresentation;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
-import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.structuralsearch.SSRBundle;
 import com.intellij.structuralsearch.plugin.replace.ui.ReplaceCommand;
 import com.intellij.usages.*;
@@ -81,7 +81,7 @@
 
   protected void configureActions() {}
 
-  private class MyUsageTarget implements ConfigurableUsageTarget,ItemPresentation, TypeSafeDataProvider {
+  private class MyUsageTarget implements ConfigurableUsageTarget,ItemPresentation {
     private final String myPresentableText;
 
     MyUsageTarget(String str) {
@@ -179,12 +179,5 @@
     public String getLongDescriptiveName() {
       return _getPresentableText();
     }
-
-    @Override
-    public void calcData(DataKey key, DataSink sink) {
-      if (key == UsageView.USAGE_SCOPE) {
-        sink.put(UsageView.USAGE_SCOPE, GlobalSearchScope.allScope(mySearchContext.getProject()));
-      }
-    }
   }
 }
diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
index de9b668..fe1b6e0 100644
--- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
+++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
@@ -1809,6 +1809,35 @@
     );
   }
 
+  public void testUseStaticImport() {
+    final String in = "class X {{ Math.abs(-1); }}";
+    final String what = "Math.abs('a)";
+    final String by = "Math.abs($a$)";
+    options.setToUseStaticImport(true);
+
+    final String expected = "import static java.lang.Math.abs;class X {{ abs(-1); }}";
+    assertEquals("Replacing with static import", expected, replacer.testReplace(in, what, by, options, true));
+  }
+
+  public void testUseStaticStarImport() {
+    final String in = "class ImportTest {{\n" +
+                      "    Math.abs(-0.5);\n" +
+                      "    Math.sin(0.5);\n" +
+                      "    Math.max(1, 2);\n" +
+                      "}}";
+    final String what = "Math.'m('a*)";
+    final String by = "Math.$m$($a$)";
+    options.setToUseStaticImport(true);
+
+    // depends on default setting being equal to 3 for names count to use import on demand
+    final String expected = "import static java.lang.Math.*;class ImportTest {{\n" +
+                            "    abs(-0.5);\n" +
+                            "    sin(0.5);\n" +
+                            "    max(1,2);\n" +
+                            "}}";
+    assertEquals("Replacing with static star import", expected, replacer.testReplace(in, what, by, options, true));
+  }
+
   public void testReformatAndShortenClassRefPerformance() throws IOException {
     final String testName = getTestName(false);
     final String ext = "java";
diff --git a/platform/testFramework/src/com/intellij/FileSetTestCase.java b/platform/testFramework/src/com/intellij/FileSetTestCase.java
index ba2afa2..d89e175 100644
--- a/platform/testFramework/src/com/intellij/FileSetTestCase.java
+++ b/platform/testFramework/src/com/intellij/FileSetTestCase.java
@@ -16,6 +16,7 @@
 import junit.framework.TestSuite;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -80,6 +81,10 @@
     }
   }
 
+  protected String loadFile(File testFile) throws IOException {
+    return FileUtil.loadFile(testFile);
+  }
+
   protected String getDelimiter() {
     return "---";
   }
@@ -116,7 +121,7 @@
 
     @Override
     protected void runTest() throws Throwable {
-      String content = FileUtil.loadFile(myTestFile);
+      String content = loadFile(myTestFile);
       assertNotNull(content);
 
       List<String> input = new ArrayList<String>();
diff --git a/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java b/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
index 3fa50de..f7a84c0 100644
--- a/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
+++ b/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
@@ -56,7 +56,7 @@
   private final List<Pattern> myTestGroupPatterns;
   private boolean myContainsAllExcludeDefinedGroup;
 
-  private GroupBasedTestClassFilter(Map<String, List<String>> filters, List<String> testGroupNames) {
+  public GroupBasedTestClassFilter(Map<String, List<String>> filters, List<String> testGroupNames) {
     //empty group means all patterns from each defined group should be excluded
     myContainsAllExcludeDefinedGroup = containsAllExcludeDefinedGroup(testGroupNames);
 
@@ -120,6 +120,10 @@
    */
   @NotNull
   public static TestClassesFilter createOn(@NotNull Reader reader, @NotNull List<String> testGroupNames) throws IOException {
+    return new GroupBasedTestClassFilter(readGroups(reader), testGroupNames);
+  }
+
+  public static Map<String, List<String>> readGroups(Reader reader) throws IOException {
     Map<String, List<String>> groupNameToPatternsMap = new HashMap<String, List<String>>();
     String currentGroupName = "";
 
@@ -137,8 +141,7 @@
         groupNameToPatternsMap.get(currentGroupName).add(line);
       }
     }
-
-    return new GroupBasedTestClassFilter(groupNameToPatternsMap, testGroupNames);
+    return groupNameToPatternsMap;
   }
 
   /**
diff --git a/platform/testFramework/src/com/intellij/TestCaseLoader.java b/platform/testFramework/src/com/intellij/TestCaseLoader.java
index 5d11e48..a010703 100644
--- a/platform/testFramework/src/com/intellij/TestCaseLoader.java
+++ b/platform/testFramework/src/com/intellij/TestCaseLoader.java
@@ -62,15 +62,24 @@
       System.out.println("Using patterns: [" + patterns +"]");
     }
     else {
-      URL excludedStream = StringUtil.isEmpty(classFilterName) ? null : getClass().getClassLoader().getResource(classFilterName);
-      if (excludedStream != null) {
-        TestClassesFilter filter;
+      List<URL> groupingFileUrls = Collections.emptyList();
+      if (!StringUtil.isEmpty(classFilterName)) {
         try {
-          List<String> testGroupNames = StringUtil.split(System.getProperty(TARGET_TEST_GROUP, "").trim(), ";");
-          InputStreamReader reader = new InputStreamReader(excludedStream.openStream());
+          groupingFileUrls = Collections.list(getClass().getClassLoader().getResources(classFilterName));
+        }
+        catch (IOException e) {
+          e.printStackTrace();
+        }
+      }
+
+      List<String> testGroupNames = StringUtil.split(System.getProperty(TARGET_TEST_GROUP, "").trim(), ";");
+      Map<String, List<String>> groups = new LinkedHashMap<String, List<String>>();
+
+      for (URL fileUrl : groupingFileUrls) {
+        try {
+          InputStreamReader reader = new InputStreamReader(fileUrl.openStream());
           try {
-            filter = GroupBasedTestClassFilter.createOn(reader, testGroupNames);
-            System.out.println("Using test groups: " + testGroupNames);
+            groups.putAll(GroupBasedTestClassFilter.readGroups(reader));
           }
           finally {
             reader.close();
@@ -78,14 +87,17 @@
         }
         catch (IOException e) {
           e.printStackTrace();
-          filter = TestClassesFilter.ALL_CLASSES;
-          System.out.println("Using all classes");
+          System.err.println("Failed to load test groups from " + fileUrl);
         }
-        myTestClassesFilter = filter;
+      }
+
+      if (groups.isEmpty()) {
+        System.out.println("Using all classes");
+        myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
       }
       else {
-        myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
-        System.out.println("Using all classes");
+        System.out.println("Using test groups: " + testGroupNames);
+        myTestClassesFilter = new GroupBasedTestClassFilter(groups, testGroupNames);
       }
     }
   }
diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
index 24e4074..3c1f961 100644
--- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
@@ -35,10 +35,10 @@
 import com.intellij.openapi.editor.ex.util.EditorUtil;
 import com.intellij.openapi.editor.impl.DocumentImpl;
 import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper;
 import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.ThrowableComputable;
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
index 0c46f14..307fb65 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
@@ -44,6 +44,7 @@
 import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
 import com.intellij.util.Alarm;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
 import com.intellij.util.ThrowableRunnable;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashMap;
@@ -62,11 +63,8 @@
 import javax.swing.tree.TreePath;
 import java.awt.*;
 import java.awt.event.InvocationEvent;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
+import java.io.*;
 import java.lang.ref.SoftReference;
-import java.lang.reflect.Field;
 import java.nio.charset.Charset;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
@@ -823,9 +821,24 @@
   }
 
   private static void patchSystemFileEncoding(String encoding) throws NoSuchFieldException, IllegalAccessException {
-    Field charset = Charset.class.getDeclaredField("defaultCharset");
-    charset.setAccessible(true);
-    charset.set(Charset.class, null);
+    ReflectionUtil.resetField(Charset.class, Charset.class, "defaultCharset");
     System.setProperty("file.encoding", encoding);
   }
+
+  public static void withStdErrSuppressed(@NotNull Runnable r) {
+    PrintStream std = System.err;
+    System.setErr(new PrintStream(NULL));
+    try {
+      r.run();
+    }
+    finally {
+      System.setErr(std);
+    }
+  }
+
+  @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+  private static final OutputStream NULL = new OutputStream() {
+    @Override
+    public void write(int b) throws IOException { }
+  };
 }
diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
index 0f746d4..3960159 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
@@ -220,11 +220,11 @@
     return entry;
   }
 
-  public static void removeContentEntry(Module module, final ContentEntry e) {
+  public static void removeContentEntry(Module module, final VirtualFile contentRoot) {
     ModuleRootModificationUtil.updateModel(module, new Consumer<ModifiableRootModel>() {
       @Override
       public void consume(ModifiableRootModel model) {
-        model.removeContentEntry(e);
+        model.removeContentEntry(findContentEntryWithAssertion(model, contentRoot));
       }
     });
   }
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index fa752b4..6deda3d 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -570,8 +570,12 @@
 
   public static <T> T assertOneElement(Collection<T> collection) {
     Assert.assertNotNull(collection);
-    Assert.assertEquals(toString(collection), 1, collection.size());
-    return collection.iterator().next();
+    Iterator<T> iterator = collection.iterator();
+    String toString = toString(collection);
+    Assert.assertTrue(toString, iterator.hasNext());
+    T t = iterator.next();
+    Assert.assertFalse(toString, iterator.hasNext());
+    return t;
   }
 
   public static <T> T assertOneElement(T[] ts) {
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
index e721401..a309f9a 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
@@ -463,7 +463,7 @@
 
   void type(final char c);
 
-  void type(final String s);
+  void type(@NotNull String s);
 
   void performEditorAction(@NotNull String actionId);
 
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
index 490d2c3..57e7806 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
 
 import com.intellij.psi.PsiFile;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
 
@@ -25,5 +26,5 @@
  * @author peter
  */
 public interface HeavyIdeaTestFixture extends IdeaProjectTestFixture {
-  PsiFile addFileToProject(@NonNls String rootPath, @NonNls String relativePath, @NonNls String fileText) throws IOException;
+  PsiFile addFileToProject(@NonNls @NotNull String rootPath, @NonNls @NotNull String relativePath, @NonNls @NotNull String fileText) throws IOException;
 }
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
index 4857acd..449b1ba 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
@@ -146,7 +146,6 @@
 
   private final TempDirTestFixture myTempDirFixture;
   protected final IdeaProjectTestFixture myProjectFixture;
-  @NonNls private static final String XXX = "XXX";
   private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
   private boolean myAllowDirt;
   private boolean myCaresAboutInjection = true;
@@ -369,7 +368,7 @@
   private long collectAndCheckHighlightings(final boolean checkWarnings,
                                             final boolean checkInfos,
                                             final boolean checkWeakWarnings,
-                                            final VirtualFile[] files) {
+                                            @NotNull VirtualFile[] files) {
     final List<Trinity<PsiFile, Editor, ExpectedHighlightingData>> datas =
       ContainerUtil.map2List(files, new Function<VirtualFile, Trinity<PsiFile, Editor, ExpectedHighlightingData>>() {
         @Override
@@ -787,12 +786,13 @@
     });
   }
 
+  @NotNull
   private DataContext getEditorDataContext() {
     return ((EditorEx)myEditor).getDataContext();
   }
 
   @Override
-  public void type(String s) {
+  public void type(@NotNull String s) {
     for (int i = 0; i < s.length(); i++) {
       type(s.charAt(i));
     }
@@ -804,7 +804,7 @@
     _performEditorAction(actionId);
   }
 
-  private boolean _performEditorAction(String actionId) {
+  private boolean _performEditorAction(@NotNull String actionId) {
     final DataContext dataContext = getEditorDataContext();
 
     final ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
@@ -948,7 +948,7 @@
 
   private static void addGutterIconRenderer(final GutterMark renderer,
                                             final int offset,
-                                            SortedMap<Integer, List<GutterMark>> result) {
+                                            @NotNull SortedMap<Integer, List<GutterMark>> result) {
     if (renderer == null) return;
 
     List<GutterMark> renderers = result.get(offset);
@@ -965,7 +965,7 @@
     return addFileToProject(getTempDirPath(), relativePath, fileText);
   }
 
-  protected PsiFile addFileToProject(final String rootPath, final String relativePath, final String fileText) {
+  protected PsiFile addFileToProject(@NotNull final String rootPath, @NotNull final String relativePath, @NotNull final String fileText) {
     return new WriteCommandAction<PsiFile>(getProject()) {
       @Override
       protected void run(@NotNull Result<PsiFile> result) throws Throwable {
@@ -1377,7 +1377,7 @@
     return PsiDocumentManager.getInstance(getProject()).getDocument(file);
   }
 
-  private PsiFile configureByFileInner(@NonNls String filePath) {
+  private PsiFile configureByFileInner(@NonNls @NotNull String filePath) {
     assertInitialized();
     final VirtualFile file = copyFileToProject(filePath);
     return configureByFileInner(file);
@@ -1401,7 +1401,7 @@
     return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy));
   }
 
-  private PsiFile configureInner(@NotNull final VirtualFile copy, final SelectionAndCaretMarkupLoader loader) {
+  private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) {
     assertInitialized();
     new WriteCommandAction.Simple(getProject()) {
       @Override
@@ -1459,13 +1459,17 @@
   }
 
   @Nullable
-  private Editor createEditor(VirtualFile file) {
+  private Editor createEditor(@NotNull VirtualFile file) {
     final Project project = getProject();
     final FileEditorManager instance = FileEditorManager.getInstance(project);
     if (file.getFileType().isBinary()) {
       return null;
     }
-    return instance.openTextEditor(new OpenFileDescriptor(project, file, 0), false);
+    Editor editor = instance.openTextEditor(new OpenFileDescriptor(project, file), false);
+    if (editor != null) {
+      editor.getCaretModel().moveToOffset(0);
+    }
+    return editor;
   }
 
   private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) throws Exception {
@@ -1487,14 +1491,14 @@
 
     //to initialize caches
     if (!DumbService.isDumb(project)) {
-      CacheManager.SERVICE.getInstance(project).getFilesWithWord(XXX, UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
+      CacheManager.SERVICE.getInstance(project).getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
     }
 
-    List<HighlightInfo> infos;
     final long start = System.currentTimeMillis();
     ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(myJavaFilesFilter, myTestRootDisposable);
 
     //    ProfilingUtil.startCPUProfiling();
+    List<HighlightInfo> infos;
     try {
       infos = doHighlighting();
       removeDuplicatedRangesForInjected(infos);
@@ -1510,7 +1514,7 @@
     return elapsed;
   }
 
-  private static void removeDuplicatedRangesForInjected(List<HighlightInfo> infos) {
+  private static void removeDuplicatedRangesForInjected(@NotNull List<HighlightInfo> infos) {
     Collections.sort(infos, new Comparator<HighlightInfo>() {
       @Override
       public int compare(HighlightInfo o1, HighlightInfo o2) {
@@ -1582,7 +1586,7 @@
     throw exception;
   }
 
-  public static void ensureIndexesUpToDate(Project project) {
+  public static void ensureIndexesUpToDate(@NotNull Project project) {
     if (!DumbService.isDumb(project)) {
       FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, null);
       FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, project, null);
@@ -1625,6 +1629,7 @@
     });
   }
 
+  @NotNull
   public static List<IntentionAction> getAvailableIntentions(@NotNull final Editor editor, @NotNull final PsiFile file) {
     return ApplicationManager.getApplication().runReadAction(new Computable<List<IntentionAction>>() {
       @Override
@@ -1634,6 +1639,7 @@
     });
   }
 
+  @NotNull
   private static List<IntentionAction> doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
     ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo();
     ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1);
@@ -1681,15 +1687,17 @@
     myJavaFilesFilter.allowTreeAccessForAllFiles();
   }
 
-  static class SelectionAndCaretMarkupLoader {
+  private static class SelectionAndCaretMarkupLoader {
     final String filePath;
     final String newFileText;
     final EditorTestUtil.CaretAndSelectionState caretState;
 
-    static SelectionAndCaretMarkupLoader fromFile(String path, String charset) throws IOException {
+    @NotNull
+    static SelectionAndCaretMarkupLoader fromFile(@NotNull String path, String charset) throws IOException {
       return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(FileUtil.loadFile(new File(path), charset)), path);
     }
 
+    @NotNull
     static SelectionAndCaretMarkupLoader fromFile(@NotNull VirtualFile file) {
       final String text;
       try {
@@ -1701,11 +1709,12 @@
       return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(text), file.getPath());
     }
 
-    static SelectionAndCaretMarkupLoader fromText(String text) {
+    @NotNull
+    static SelectionAndCaretMarkupLoader fromText(@NotNull String text) {
       return new SelectionAndCaretMarkupLoader(text, null);
     }
 
-    private SelectionAndCaretMarkupLoader(String fileText, String filePath) {
+    private SelectionAndCaretMarkupLoader(@NotNull String fileText, String filePath) {
       this.filePath = filePath;
       final Document document = EditorFactory.getInstance().createDocument(fileText);
       caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
@@ -1735,11 +1744,10 @@
 
   }
 
-  @SuppressWarnings("ConstantConditions")
   private void checkResult(@NotNull String expectedFile,
                            final boolean stripTrailingSpaces,
-                           final SelectionAndCaretMarkupLoader loader,
-                           String actualText) {
+                           @NotNull SelectionAndCaretMarkupLoader loader,
+                           @NotNull String actualText) {
     assertInitialized();
     Project project = getProject();
     Editor editor = getEditor();
@@ -1773,7 +1781,8 @@
     EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile);
   }
 
-  private String stripTrailingSpaces(String actualText) {
+  @NotNull
+  private String stripTrailingSpaces(@NotNull String actualText) {
     final Document document = EditorFactory.getInstance().createDocument(actualText);
     ((DocumentImpl)document).stripTrailingSpaces(getProject());
     actualText = document.getText();
@@ -1824,6 +1833,7 @@
     }
   }
 
+  @NotNull
   public String getFoldingDescription(boolean withCollapseStatus) {
     CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(myEditor);
 
@@ -1849,7 +1859,7 @@
     return result.toString();
   }
 
-  private void testFoldingRegions(final String verificationFileName, boolean doCheckCollapseStatus) {
+  private void testFoldingRegions(@NotNull String verificationFileName, boolean doCheckCollapseStatus) {
     String expectedContent;
     try {
       expectedContent = FileUtil.loadFile(new File(verificationFileName));
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
index 4adc2aa..27a45cb 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
@@ -235,7 +235,7 @@
   }
 
   @Override
-  public PsiFile addFileToProject(@NonNls String rootPath, @NonNls final String relativePath, @NonNls final String fileText) throws IOException {
+  public PsiFile addFileToProject(@NotNull @NonNls String rootPath, @NotNull @NonNls final String relativePath, @NotNull @NonNls final String fileText) throws IOException {
     final VirtualFile dir = VfsUtil.createDirectories(rootPath + "/" + PathUtil.getParentPath(relativePath));
 
     final VirtualFile[] virtualFile = new VirtualFile[1];
diff --git a/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java b/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
index da7dc5c..9ee314d 100644
--- a/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
+++ b/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
@@ -1,5 +1,7 @@
 package com.intellij.util.io;
 
+import org.jetbrains.annotations.NotNull;
+
 /**
  * @author nik
  */
@@ -12,6 +14,7 @@
     myParent = parent;
   }
 
+  @NotNull
   public TestFileSystemItem build() {
     TestFileSystemBuilder builder = this;
     while (builder.myParent != null) {
@@ -20,23 +23,27 @@
     return builder.myItem;
   }
 
+  @NotNull
   public TestFileSystemBuilder dir(String name) {
     final TestFileSystemItem item = new TestFileSystemItem(name, false, true);
     myItem.addChild(item);
     return new TestFileSystemBuilder(item, this);
   }
 
+  @NotNull
   public TestFileSystemBuilder archive(String name) {
     final TestFileSystemItem item = new TestFileSystemItem(name, true, false);
     myItem.addChild(item);
     return new TestFileSystemBuilder(item, this);
   }
 
+  @NotNull
   public TestFileSystemBuilder file(String name) {
     myItem.addChild(new TestFileSystemItem(name, false, false));
     return this;
   }
 
+  @NotNull
   public TestFileSystemBuilder file(String name, String content) {
     myItem.addChild(new TestFileSystemItem(name, false, false, content));
     return this;
@@ -46,6 +53,7 @@
     return myParent;
   }
 
+  @NotNull
   public static TestFileSystemBuilder fs() {
     return new TestFileSystemBuilder(new TestFileSystemItem("root", false, true), null);
   }
diff --git a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
index 86958ee..4375701 100644
--- a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
+++ b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
@@ -82,6 +82,7 @@
     { "alt DOWN",                 "ShowContent", "MethodDown"},
     { "alt F1",                   "SelectIn", "ProjectViewChangeView"},
     { "alt INSERT",               "FileChooser.NewFolder", "Generate", "NewElement"},
+    { "control F10",              "javaee.UpdateRunningApplication", "liveedit.UpdateRunningApplication"},
     { "control 1",                "FileChooser.GotoHome", "GotoBookmark1", "DuplicatesForm.SendToLeft"},
     { "control 2",                "FileChooser.GotoProject", "GotoBookmark2", "DuplicatesForm.SendToRight"},
     { "control 3",                "GotoBookmark3", "FileChooser.GotoModule"},
@@ -238,7 +239,7 @@
     { "TAB",                      "EditorChooseLookupItemReplace", "NextTemplateVariable", "NextParameter", "EditorIndentSelection", "EditorTab", "NextTemplateParameter"},
     { "alt DOWN",                 "ShowContent", "MoveStatementDown"},
     { "alt HOME",                 "ViewNavigationBar", "ShowNavBar"},
-    { "control F10",              "ShowPopupMenu", "javaee.UpdateRunningApplication"},
+    { "control F10",              "ShowPopupMenu", "javaee.UpdateRunningApplication", "liveedit.UpdateRunningApplication"},
     { "control F11",              "Rerun", "ToggleBookmarkWithMnemonic"},
     { "control D",                "CompareDirs", "EditorDeleteLine", "CompareTwoFiles", "SendEOF", "FileChooser.GotoDesktop"},
     { "control N",                "ShowPopupMenu", "FileChooser.NewFolder"},
diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
index b355723..263c25b 100644
--- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
+++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
@@ -271,6 +271,11 @@
   }
 
   @Override
+  public void addDirectoryToIgnoreImplicitly(@NotNull String path) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
   public void setFilesToIgnore(IgnoredFileBean... ignoredFiles) {
     throw new UnsupportedOperationException();
   }
diff --git a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
index 930321f..dbbaeb4 100644
--- a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
+++ b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
@@ -19,9 +19,7 @@
 import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.lexer.Lexer;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.HighlighterColors;
-import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
 import com.intellij.openapi.editor.markup.TextAttributes;
@@ -39,11 +37,14 @@
 import com.intellij.reference.SoftReference;
 import com.intellij.usageView.UsageTreeColors;
 import com.intellij.usageView.UsageTreeColorsScheme;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
+import com.intellij.usages.impl.rules.UsageType;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.FactoryMap;
 import com.intellij.util.text.CharArrayUtil;
 import com.intellij.util.text.StringFactory;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 import java.lang.ref.WeakReference;
@@ -64,9 +65,7 @@
 
   private final Document myDocument;
   private long myDocumentStamp;
-  private final SyntaxHighlighter myHighlighter;
-
-  private final Lexer myLexer;
+  private final SyntaxHighlighterOverEditorHighlighter myHighlighter;
 
   private abstract static class WeakFactory<T> {
     private WeakReference<T> myRef;
@@ -119,11 +118,10 @@
     myDocument = PsiDocumentManager.getInstance(project).getDocument(file);
     LOG.assertTrue(myDocument != null);
     final FileType fileType = file.getFileType();
-    final SyntaxHighlighter highlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(fileType, project, file.getVirtualFile());
-    myHighlighter = highlighter == null ? new PlainSyntaxHighlighter() : highlighter;
-    myLexer = myHighlighter.getHighlightingLexer();
-    myLexer.start(myDocument.getCharsSequence());
-    myDocumentStamp = myDocument.getModificationStamp();
+    SyntaxHighlighter highlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(fileType, project, file.getVirtualFile());
+    highlighter = highlighter == null ? new PlainSyntaxHighlighter() : highlighter;
+    myHighlighter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file.getVirtualFile(), project);
+    myDocumentStamp = -1;
   }
 
   public static int getStartOffset(final List<RangeMarker> rangeMarkers) {
@@ -194,18 +192,21 @@
                                       int end,
                                       boolean selectUsageWithBold,
                                       @NotNull List<TextChunk> result) {
-    final Lexer lexer = myLexer;
-    final SyntaxHighlighter highlighter = myHighlighter;
+    final Lexer lexer = myHighlighter.getHighlightingLexer();
+    final SyntaxHighlighterOverEditorHighlighter highlighter = myHighlighter;
 
     LOG.assertTrue(start <= end);
 
     int i = StringUtil.indexOf(chars, '\n', start, end);
     if (i != -1) end = i;
 
-    if (lexer.getTokenStart() > start || myDocumentStamp != myDocument.getModificationStamp()) {
-      lexer.start(chars);
+    if (myDocumentStamp != myDocument.getModificationStamp()) {
+      highlighter.restart(chars);
       myDocumentStamp = myDocument.getModificationStamp();
+    } else if(lexer.getTokenStart() > start) {
+      highlighter.resetPosition(0);  // todo restart from nearest position with initial state
     }
+
     boolean isBeginning = true;
 
     for(;lexer.getTokenType() != null; lexer.advance()) {
@@ -218,8 +219,10 @@
       hiEnd = Math.min(hiEnd, end);
       if (hiStart >= hiEnd) { continue; }
 
-      String text = chars.subSequence(hiStart, hiEnd).toString();
-      if (isBeginning && text.trim().isEmpty()) continue;
+      if (isBeginning) {
+        String text = chars.subSequence(hiStart, hiEnd).toString();
+        if(text.trim().isEmpty()) continue;
+      }
       isBeginning = false;
       IElementType tokenType = lexer.getTokenType();
       TextAttributesKey[] tokenHighlights = highlighter.getTokenHighlights(tokenType);
@@ -234,7 +237,7 @@
                                         @NotNull final CharSequence chars,
                                         int hiStart,
                                         final int hiEnd,
-                                        @NotNull TextAttributesKey[] tokenHighlights,
+                                        @NotNull final TextAttributesKey[] tokenHighlights,
                                         final boolean selectUsageWithBold,
                                         @NotNull final List<TextChunk> result) {
     final TextAttributes originalAttrs = convertAttributes(tokenHighlights);
@@ -249,8 +252,12 @@
         int usageStart = segment.getStartOffset();
         int usageEnd = segment.getEndOffset();
         if (rangeIntersect(lastOffset[0], hiEnd, usageStart, usageEnd)) {
-          addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, result);
-          addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, result);
+          addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, null, result);
+
+          UsageType usageType = isHighlightedAsString(tokenHighlights)
+                           ? UsageType.LITERAL_USAGE
+                           : isHighlightedAsComment(tokenHighlights) ? UsageType.COMMENT_USAGE : null;
+          addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, usageType, result);
           lastOffset[0] = usageEnd;
           if (usageEnd > hiEnd) {
             return false;
@@ -260,22 +267,55 @@
       }
     });
     if (lastOffset[0] < hiEnd) {
-      addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, result);
+      addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, null, result);
     }
   }
 
+  public static boolean isHighlightedAsComment(TextAttributesKey... keys) {
+    for (TextAttributesKey key : keys) {
+      if (key == DefaultLanguageHighlighterColors.DOC_COMMENT ||
+          key == SyntaxHighlighterColors.DOC_COMMENT ||
+          key == DefaultLanguageHighlighterColors.LINE_COMMENT ||
+          key == SyntaxHighlighterColors.LINE_COMMENT ||
+          key == DefaultLanguageHighlighterColors.BLOCK_COMMENT ||
+          key == SyntaxHighlighterColors.JAVA_BLOCK_COMMENT
+        ) {
+        return true;
+      }
+      final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
+      if (fallbackAttributeKey != null && isHighlightedAsComment(fallbackAttributeKey)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static boolean isHighlightedAsString(TextAttributesKey... keys) {
+    for (TextAttributesKey key : keys) {
+      if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
+        return true;
+      }
+      final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
+      if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   private static void addChunk(@NotNull CharSequence chars,
                                int start,
                                int end,
                                @NotNull TextAttributes originalAttrs,
                                boolean bold,
+                               @Nullable UsageType usageType,
                                @NotNull List<TextChunk> result) {
     if (start >= end) return;
 
     TextAttributes attrs = bold
                            ? TextAttributes.merge(originalAttrs, new TextAttributes(null, null, null, null, Font.BOLD))
                            : originalAttrs;
-    result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end))));
+    result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end)), usageType));
   }
 
   private static boolean rangeIntersect(int s1, int e1, int s2, int e2) {
diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
index d608303..2248182 100644
--- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
+++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
@@ -20,6 +20,7 @@
 import com.intellij.psi.PsiFile;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.util.ArrayList;
@@ -41,6 +42,7 @@
   private Factory<ProgressIndicator> myProgressIndicatorFactory;
   private Collection<PsiFile> myLargeFiles;
   private boolean myShowFindOptionsPrompt = true;
+  private Runnable mySearchWithProjectFiles;
 
   public FindUsagesProcessPresentation(@NotNull UsageViewPresentation presentation) {
     myUsageViewPresentation = presentation;
@@ -80,6 +82,15 @@
     myProgressIndicatorFactory = progressIndicatorFactory;
   }
 
+  @Nullable
+  public Runnable searchIncludingProjectFileUsages() {
+    return mySearchWithProjectFiles;
+  }
+
+  public void projectFileUsagesFound(@NotNull Runnable searchWithProjectFiles) {
+    mySearchWithProjectFiles = searchWithProjectFiles;
+  }
+
   public void setLargeFilesWereNotScanned(@NotNull Collection<PsiFile> largeFiles) {
     myLargeFiles = largeFiles;
   }
diff --git a/platform/usageView/src/com/intellij/usages/TextChunk.java b/platform/usageView/src/com/intellij/usages/TextChunk.java
index e1c3345..e74debd 100644
--- a/platform/usageView/src/com/intellij/usages/TextChunk.java
+++ b/platform/usageView/src/com/intellij/usages/TextChunk.java
@@ -18,17 +18,25 @@
 import com.intellij.openapi.editor.markup.AttributesFlyweight;
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.usages.impl.rules.UsageType;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class TextChunk {
   public static final TextChunk[] EMPTY_ARRAY = new TextChunk[0];
 
   private final AttributesFlyweight myAttributes;
   private final String myText;
+  private final UsageType myType;
 
   public TextChunk(@NotNull TextAttributes attributes, @NotNull String text) {
+    this(attributes, text, null);
+  }
+
+  public TextChunk(@NotNull TextAttributes attributes, @NotNull String text, @Nullable UsageType type) {
     myAttributes = attributes.getFlyweight();
     myText = text;
+    myType = type;
   }
 
   @NotNull
@@ -45,6 +53,10 @@
     return getText();
   }
 
+  public @Nullable UsageType getType() {
+    return myType;
+  }
+
   @NotNull
   public SimpleTextAttributes getSimpleAttributesIgnoreBackground() {
     SimpleTextAttributes simples = SimpleTextAttributes.fromTextAttributes(getAttributes());
diff --git a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
index aaccbff..418890c 100644
--- a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
+++ b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
@@ -38,11 +38,9 @@
 import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usages.impl.rules.UsageType;
 import com.intellij.usages.rules.*;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.NotNullFunction;
-import com.intellij.util.Processor;
+import com.intellij.util.*;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -79,7 +77,8 @@
   private final int myLineNumber;
   private final int myOffset;
   protected Icon myIcon;
-  private Reference<TextChunk[]> myTextChunks; // allow to be gced and recreated on-demand because it requires a lot of memory
+  private volatile Reference<TextChunk[]> myTextChunks; // allow to be gced and recreated on-demand because it requires a lot of memory
+  private volatile UsageType myUsageType;
 
   public UsageInfo2UsageAdapter(@NotNull final UsageInfo usageInfo) {
     myUsageInfo = usageInfo;
@@ -336,7 +335,7 @@
     UsageInfo[] merged = ArrayUtil.mergeArrays(getMergedInfos(), u2.getMergedInfos());
     myMergedUsageInfos = merged.length == 1 ? merged[0] : merged;
     Arrays.sort(getMergedInfos(), BY_NAVIGATION_OFFSET);
-    initChunks();
+    myTextChunks = null; // chunks will be rebuilt lazily (IDEA-126048)
     return true;
   }
 
@@ -493,4 +492,44 @@
   public String getTooltipText() {
     return myUsageInfo.getTooltipText();
   }
+
+  public @Nullable UsageType getUsageType() {
+    UsageType usageType = myUsageType;
+
+    if (usageType == null) {
+      usageType = UsageType.UNCLASSIFIED;
+      PsiFile file = getPsiFile();
+
+      if (file != null) {
+        ChunkExtractor extractor = ChunkExtractor.getExtractor(file);
+        Segment segment = getFirstSegment();
+
+        if (segment != null) {
+          Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
+
+          if (document != null) {
+            SmartList<TextChunk> chunks = new SmartList<TextChunk>();
+            extractor.createTextChunks(
+              this,
+              document.getCharsSequence(),
+              segment.getStartOffset(),
+              segment.getEndOffset(),
+              false,
+              chunks
+            );
+
+            for(TextChunk chunk:chunks) {
+              UsageType chunkUsageType = chunk.getType();
+              if (chunkUsageType != null) {
+                usageType = chunkUsageType;
+                break;
+              }
+            }
+          }
+        }
+      }
+      myUsageType = usageType;
+    }
+    return usageType;
+  }
 }
diff --git a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
index 8b065b3..170d180 100644
--- a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
+++ b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
@@ -19,6 +19,7 @@
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.actionSystem.KeyboardShortcut;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.colors.CodeInsightColors;
@@ -71,6 +72,7 @@
   @NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions";
   @NonNls private static final String SEARCH_IN_PROJECT_HREF_TARGET = "SearchInProject";
   @NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles";
+  @NonNls private static final String SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET = "SHOW_PROJECT_FILE_OCCURRENCES";
   private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0);
   private final AtomicReference<Usage> myFirstUsage = new AtomicReference<Usage>();
   @NotNull
@@ -80,7 +82,7 @@
   private final UsageTarget[] mySearchFor;
   private final Factory<UsageSearcher> mySearcherFactory;
   private final FindUsagesProcessPresentation myProcessPresentation;
-  @NotNull private final SearchScope mySearchScope;
+  @NotNull private final SearchScope mySearchScopeToWarnOfFallingOutOf;
   private final UsageViewManager.UsageViewStateListener myListener;
   private final UsageViewManagerImpl myUsageViewManager;
   private final AtomicInteger myOutOfScopeUsages = new AtomicInteger();
@@ -92,7 +94,7 @@
                           @NotNull UsageTarget[] searchFor,
                           @NotNull Factory<UsageSearcher> searcherFactory,
                           @NotNull FindUsagesProcessPresentation processPresentation,
-                          @NotNull SearchScope scope,
+                          @NotNull SearchScope searchScopeToWarnOfFallingOutOf,
                           @Nullable UsageViewManager.UsageViewStateListener listener) {
     myProject = project;
     myUsageViewRef = usageViewRef;
@@ -100,7 +102,7 @@
     mySearchFor = searchFor;
     mySearcherFactory = searcherFactory;
     myProcessPresentation = processPresentation;
-    mySearchScope = scope;
+    mySearchScopeToWarnOfFallingOutOf = searchScopeToWarnOfFallingOutOf;
     myListener = listener;
     myUsageViewManager = usageViewManager;
   }
@@ -135,25 +137,43 @@
                             + UsageViewBundle.message("large.files.were.ignored", largeFiles.size()) + "</a>)";
 
       resultLines.add(shortMessage);
-      resultListener = new HyperlinkAdapter(){
-        @Override
-        protected void hyperlinkActivated(HyperlinkEvent e) {
-          if (e.getDescription().equals(LARGE_FILES_HREF_TARGET)) {
-            String detailedMessage = detailedLargeFilesMessage(largeFiles);
-            List<String> strings = new ArrayList<String>(lines);
-            strings.add(detailedMessage);
-            ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
-          }
-          else if (listener != null) {
-            listener.hyperlinkUpdate(e);
-          }
+      resultListener = addHrefHandling(resultListener, LARGE_FILES_HREF_TARGET, new Runnable() {
+        public void run() {
+          String detailedMessage = detailedLargeFilesMessage(largeFiles);
+          List<String> strings = new ArrayList<String>(lines);
+          strings.add(detailedMessage);
+          //noinspection SSBasedInspection
+          ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
         }
-      };
+      });
     }
 
+    Runnable searchIncludingProjectFileUsages = processPresentation.searchIncludingProjectFileUsages();
+    if (searchIncludingProjectFileUsages != null) {
+      resultLines.add("Occurrences in " + ApplicationNamesInfo.getInstance().getProductName() + " project files are skipped. " +
+                      "<a href='" + SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET + "'>Include them</a>");
+      resultListener = addHrefHandling(resultListener, SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET, searchIncludingProjectFileUsages);
+    }
+
+    //noinspection SSBasedInspection
     ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(resultLines), AllIcons.Actions.Find, resultListener);
   }
 
+  private static HyperlinkListener addHrefHandling(@Nullable final HyperlinkListener listener,
+                                                   @NotNull final String hrefTarget, @NotNull final Runnable handler) {
+    return new HyperlinkAdapter() {
+      @Override
+      protected void hyperlinkActivated(HyperlinkEvent e) {
+        if (e.getDescription().equals(hrefTarget)) {
+          handler.run();
+        }
+        else if (listener != null) {
+          listener.hyperlinkUpdate(e);
+        }
+      }
+    };
+  }
+
   @NotNull
   private static String wrapInHtml(@NotNull List<String> strings) {
     return XmlStringUtil.wrapInHtml(StringUtil.join(strings, "<br>"));
@@ -319,7 +339,7 @@
         ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
         if (indicator != null && indicator.isCanceled()) return false;
 
-        if (!UsageViewManagerImpl.isInScope(usage, mySearchScope)) {
+        if (!UsageViewManagerImpl.isInScope(usage, mySearchScopeToWarnOfFallingOutOf)) {
           myOutOfScopeUsages.incrementAndGet();
           return true;
         }
@@ -389,7 +409,7 @@
               List<String> lines = new ArrayList<String>();
               lines.add(StringUtil.escapeXml(message));
               if (myOutOfScopeUsages.get() != 0) {
-                lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
+                lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf));
               }
               if (myProcessPresentation.isShowFindOptionsPrompt()) {
                 lines.add(createOptionsHtml(mySearchFor));
@@ -432,7 +452,7 @@
 
           lines.add("Only one usage found.");
           if (myOutOfScopeUsages.get() != 0) {
-            lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
+            lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf));
           }
           lines.add(createOptionsHtml(mySearchFor));
           MessageType type = myOutOfScopeUsages.get() == 0 ? MessageType.INFO : MessageType.WARNING;
@@ -456,11 +476,13 @@
         hyperlinkListener = null;
       }
       else {
-        lines = Arrays.asList(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope), createSearchInProjectHtml());
+        lines = Arrays.asList(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf), createSearchInProjectHtml());
         hyperlinkListener = createSearchInProjectListener();
       }
 
-      if (!myProcessPresentation.getLargeFiles().isEmpty() || myOutOfScopeUsages.get() != 0) {
+      if (!myProcessPresentation.getLargeFiles().isEmpty() ||
+          myOutOfScopeUsages.get() != 0 ||
+          myProcessPresentation.searchIncludingProjectFileUsages() != null) {
         ApplicationManager.getApplication().invokeLater(new Runnable() {
           @Override
           public void run() {
diff --git a/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java b/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java
new file mode 100644
index 0000000..04690cc
--- /dev/null
+++ b/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+package com.intellij.usages.impl;
+
+import com.intellij.lexer.LayeredLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
+import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* Created by Maxim.Mossienko on 7/31/2014.
+*/
+public class SyntaxHighlighterOverEditorHighlighter implements SyntaxHighlighter {
+  private final Lexer lexer;
+  private LayeredHighlighterIterator layeredHighlighterIterator = null;
+  private final SyntaxHighlighter highlighter;
+
+  public SyntaxHighlighterOverEditorHighlighter(SyntaxHighlighter _highlighter, VirtualFile file, Project project) {
+    if (file.getFileType() == PlainTextFileType.INSTANCE) { // optimization for large files, PlainTextSyntaxHighlighterFactory is slow
+      highlighter = new PlainSyntaxHighlighter();
+      lexer = highlighter.getHighlightingLexer();
+    } else {
+      highlighter = _highlighter;
+      LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
+      EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, file);
+
+      try {
+        if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
+          lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
+        }
+        else {
+          lexer = highlighter.getHighlightingLexer();
+        }
+      }
+      finally {
+        LayeredLexer.ourDisableLayersFlag.set(null);
+      }
+    }
+  }
+
+  @NotNull
+  @Override
+  public Lexer getHighlightingLexer() {
+    return lexer;
+  }
+
+  @NotNull
+  @Override
+  public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+    final SyntaxHighlighter activeSyntaxHighlighter =
+      layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : highlighter;
+    return activeSyntaxHighlighter.getTokenHighlights(tokenType);
+  }
+
+  public void restart(@NotNull CharSequence text) {
+    lexer.start(text);
+
+    if (lexer instanceof LexerEditorHighlighterLexer) {
+      HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
+      if (iterator instanceof LayeredHighlighterIterator) {
+        layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
+      } else {
+        layeredHighlighterIterator = null;
+      }
+    }
+  }
+
+  public void resetPosition(int startOffset) {
+    if (lexer instanceof LexerEditorHighlighterLexer) {
+      ((LexerEditorHighlighterLexer)lexer).resetPosition(startOffset);
+
+      HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
+      if (iterator instanceof LayeredHighlighterIterator) {
+        layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
+      } else {
+        layeredHighlighterIterator = null;
+      }
+    } else {
+      CharSequence text = lexer.getBufferSequence();
+      lexer.start(text, startOffset, text.length());
+    }
+  }
+}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
index 6d7ce9c..b9fc772 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
@@ -33,9 +33,8 @@
 import com.intellij.openapi.wm.ToolWindow;
 import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.openapi.wm.ToolWindowManager;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.LocalSearchScope;
-import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.*;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.ui.content.Content;
 import com.intellij.usageView.UsageViewBundle;
@@ -122,23 +121,23 @@
                                     @NotNull final UsageViewPresentation presentation,
                                     @NotNull final FindUsagesProcessPresentation processPresentation,
                                     @Nullable final UsageViewStateListener listener) {
-    final SearchScope searchScope = getSearchScope(searchFor);
+    final SearchScope searchScope = getMaxSearchScopeToWarnOfFallingOutOf(searchFor);
     return doSearchAndShow(searchFor, searcherFactory, presentation, processPresentation, listener, searchScope);
   }
 
-  UsageView doSearchAndShow(@NotNull final UsageTarget[] searchFor,
+  private UsageView doSearchAndShow(@NotNull final UsageTarget[] searchFor,
                                     @NotNull final Factory<UsageSearcher> searcherFactory,
                                     @NotNull final UsageViewPresentation presentation,
                                     @NotNull final FindUsagesProcessPresentation processPresentation,
                                     @Nullable final UsageViewStateListener listener,
-                                    @NotNull final SearchScope searchScope) {
+                                    @NotNull final SearchScope searchScopeToWarnOfFallingOutOf) {
     final AtomicReference<UsageViewImpl> usageViewRef = new AtomicReference<UsageViewImpl>();
 
     Task.Backgroundable task = new Task.Backgroundable(myProject, getProgressTitle(presentation), true, new SearchInBackgroundOption()) {
       @Override
       public void run(@NotNull final ProgressIndicator indicator) {
         new SearchForUsagesRunnable(UsageViewManagerImpl.this, UsageViewManagerImpl.this.myProject, usageViewRef, presentation, searchFor, searcherFactory,
-                                    processPresentation, searchScope, listener).run();
+                                    processPresentation, searchScopeToWarnOfFallingOutOf, listener).run();
       }
 
       @NotNull
@@ -159,7 +158,7 @@
   }
 
   @NotNull
-  private SearchScope getSearchScope(@NotNull UsageTarget[] searchFor) {
+  private SearchScope getMaxSearchScopeToWarnOfFallingOutOf(@NotNull UsageTarget[] searchFor) {
     UsageTarget target = searchFor[0];
     if (target instanceof TypeSafeDataProvider) {
       final SearchScope[] scope = new SearchScope[1];
@@ -171,7 +170,7 @@
       });
       return scope[0];
     }
-    return GlobalSearchScope.projectScope(myProject);
+    return GlobalSearchScope.allScope(myProject); // by default do not warn of falling out of scope
   }
 
   @Override
@@ -262,10 +261,27 @@
   }
 
   public static boolean isInScope(@NotNull Usage usage, @NotNull SearchScope searchScope) {
-    VirtualFile file = usage instanceof UsageInFile ? ((UsageInFile)usage).getFile() : usage instanceof PsiElementUsage ? PsiUtilCore
-      .getVirtualFile(((PsiElementUsage)usage).getElement()) : null;
-    return file != null && (searchScope instanceof LocalSearchScope
-                         ? ((LocalSearchScope)searchScope).isInScope(file) : ((GlobalSearchScope)searchScope).contains(file));
+    PsiElement element = null;
+    VirtualFile file = usage instanceof UsageInFile ? ((UsageInFile)usage).getFile() :
+                       usage instanceof PsiElementUsage ? PsiUtilCore.getVirtualFile(element = ((PsiElementUsage)usage).getElement()) : null;
+    if (file != null) {
+      return isFileInScope(file, searchScope);
+    }
+    else if(element != null) {
+      return searchScope instanceof EverythingGlobalScope ||
+             searchScope instanceof ProjectScopeImpl ||
+             searchScope instanceof ProjectAndLibrariesScope;
+    }
+    return false;
+  }
+
+  private static boolean isFileInScope(@NotNull VirtualFile file, @NotNull SearchScope searchScope) {
+    if (searchScope instanceof LocalSearchScope) {
+      return ((LocalSearchScope)searchScope).isInScope(file);
+    }
+    else {
+      return ((GlobalSearchScope)searchScope).contains(file);
+    }
   }
 
   @NotNull
diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
index b182bc3..8d1de0b 100644
--- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
+++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.vcs.FileStatus;
 import com.intellij.psi.PsiComment;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.usages.*;
 import com.intellij.usages.rules.PsiElementUsage;
@@ -42,7 +43,13 @@
     if (usage instanceof PsiElementUsage) {
       PsiElementUsage elementUsage = (PsiElementUsage)usage;
 
-      UsageType usageType = getUsageType(elementUsage.getElement(), targets);
+      PsiElement element = elementUsage.getElement();
+      UsageType usageType = getUsageType(element, targets);
+
+      if (usageType == null && element instanceof PsiFile && elementUsage instanceof UsageInfo2UsageAdapter) {
+        usageType = ((UsageInfo2UsageAdapter)elementUsage).getUsageType();
+      }
+
       if (usageType != null) return new UsageTypeGroup(usageType);
 
       if (usage instanceof ReadWriteAccessUsage) {
diff --git a/platform/usageView/usageView.iml b/platform/usageView/usageView.iml
index e3943e4..d69cf73 100644
--- a/platform/usageView/usageView.iml
+++ b/platform/usageView/usageView.iml
@@ -9,6 +9,7 @@
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="lang-api" />
     <orderEntry type="module" module-name="core-impl" />
+    <orderEntry type="module" module-name="editor-ui-ex" />
   </component>
 </module>
 
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/util/resources/misc/registry.properties
similarity index 96%
rename from platform/platform-resources-en/src/misc/registry.properties
rename to platform/util/resources/misc/registry.properties
index 0f430e0..bbda04a 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/util/resources/misc/registry.properties
@@ -316,6 +316,7 @@
 
 svn.use.terminal=false
 svn.use.incoming.optimization=false
+svn.executable.locale=C.UTF-8
 
 completion.enable.relevant.method.chain.suggestions=false
 ide.mac.message.sheets.java.emulation=false
@@ -366,6 +367,12 @@
 allow.dialog.based.popups=true
 allow.dialog.based.popups.description=Allows to use a JDialog as popup toplevel
 
+popup.fix.ide.frame.owner=false
+popup.fix.ide.frame.owner.description=Uses correct owner for IdeFrame, but can break some popups
+
+our.heavy.weight.popup=false
+our.heavy.weight.popup.description=Disables HeavyWeightPopup cache in Swing
+
 focus.fix.lost.cursor=true
 focus.fix.lost.cursor.description=See IDEA-79312
 
@@ -384,7 +391,7 @@
   when there is too much of text to process.\n\
   The ratio is used against the console cycle buffer size (idea.cycle.buffer.size/theRatio=maxTextLength).
 ide.file.settings.order.new=false
-ide.new.project.settings=false
+ide.new.project.settings=true
 ide.new.project.settings.description=Temporary key for new project settings dialog UI
 
 commonjs.complete.required.filename.with.extension=false
@@ -392,4 +399,10 @@
 
 
 fix.jdk7.alt.shortcuts=true
-fix.jdk7.alt.shortcuts.description=Allow to use alt for shortcuts on MacOSX with jdk7+
\ No newline at end of file
+fix.jdk7.alt.shortcuts.description=Allow to use alt for shortcuts on MacOSX with jdk7+
+
+ide.new.markup.markers=true
+ide.new.markup.markers.description=New error stripe markers
+
+spy.js.realtime.evaluation=false
+spy.js.realtime.evaluation.description=Enables spy-js autocomplete and realtime evaluation
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index db897fd..be3f4f2 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.java
@@ -74,6 +74,7 @@
     public static final Icon Forward = IconLoader.getIcon("/actions/forward.png"); // 16x16
     public static final Icon GC = IconLoader.getIcon("/actions/gc.png"); // 16x16
     public static final Icon Get = IconLoader.getIcon("/actions/get.png"); // 16x16
+    public static final Icon GroupByFile = IconLoader.getIcon("/actions/GroupByFile.png"); // 16x16
     public static final Icon GroupByMethod = IconLoader.getIcon("/actions/groupByMethod.png"); // 16x16
     public static final Icon GroupByModule = IconLoader.getIcon("/actions/GroupByModule.png"); // 16x16
     public static final Icon GroupByModuleGroup = IconLoader.getIcon("/actions/GroupByModuleGroup.png"); // 16x16
@@ -459,6 +460,8 @@
     public static final Icon PluginManager = IconLoader.getIcon("/general/pluginManager.png"); // 32x32
     public static final Icon Progress = IconLoader.getIcon("/general/progress.png"); // 8x10
     public static final Icon ProjectConfigurable = IconLoader.getIcon("/general/projectConfigurable.png"); // 9x9
+    public static final Icon ProjectConfigurableBanner = IconLoader.getIcon("/general/projectConfigurableBanner.png"); // 9x9
+    public static final Icon ProjectConfigurableSelected = IconLoader.getIcon("/general/projectConfigurableSelected.png"); // 9x9
     public static final Icon ProjectSettings = IconLoader.getIcon("/general/projectSettings.png"); // 16x16
     public static final Icon ProjectStructure = IconLoader.getIcon("/general/projectStructure.png"); // 16x16
     public static final Icon ProjectTab = IconLoader.getIcon("/general/projectTab.png"); // 16x16
diff --git a/platform/util/src/com/intellij/openapi/ui/Divider.java b/platform/util/src/com/intellij/openapi/ui/Divider.java
new file mode 100644
index 0000000..1b2b6b1
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/ui/Divider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.ui;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public abstract class Divider extends JPanel {
+  public Divider(LayoutManager layout) {
+    super(layout);
+  }
+
+  public abstract void setResizeEnabled(boolean resizeEnabled);
+
+  public abstract void setSwitchOrientationEnabled(boolean switchOrientationEnabled);
+
+  public abstract void setOrientation(boolean vertical);
+}
diff --git a/platform/util/src/com/intellij/openapi/ui/Splitter.java b/platform/util/src/com/intellij/openapi/ui/Splitter.java
index 44d2317..71a0267 100644
--- a/platform/util/src/com/intellij/openapi/ui/Splitter.java
+++ b/platform/util/src/com/intellij/openapi/ui/Splitter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -177,7 +177,7 @@
   }
 
   protected Divider createDivider() {
-    return new Divider();
+    return new DividerImpl();
   }
 
   @Override
@@ -481,12 +481,12 @@
     return myDivider;
   }
 
-  public class Divider extends JPanel {
+  public class DividerImpl extends Divider {
     private boolean myResizeEnabled;
     private boolean mySwitchOrientationEnabled;
     protected Point myPoint;
 
-    public Divider() {
+    public DividerImpl() {
       super(new GridBagLayout());
       myResizeEnabled = true;
       mySwitchOrientationEnabled = false;
@@ -496,7 +496,7 @@
       setOrientation(myVerticalSplit);
     }
 
-    private void setOrientation(boolean isVerticalSplit) {
+    public void setOrientation(boolean isVerticalSplit) {
       removeAll();
 
       setCursor(isVertical() ?
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index 0f95577..cfcbe79 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -1255,10 +1255,15 @@
   }
 
   @Contract("null -> null")
-  public static String getLocationRelativeToUserHome(@Nullable final String path) {
+  public static String getLocationRelativeToUserHome(@Nullable String path) {
+    return getLocationRelativeToUserHome(path, true);
+  }
+
+  @Contract("null,_ -> null")
+  public static String getLocationRelativeToUserHome(@Nullable String path, boolean unixOnly) {
     if (path == null) return null;
 
-    if (SystemInfo.isUnix) {
+    if (SystemInfo.isUnix || !unixOnly) {
       final File projectDir = new File(path);
       final File userHomeDir = new File(SystemProperties.getUserHome());
       if (isAncestor(userHomeDir, projectDir, true)) {
diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
index 3484d06..586668a 100644
--- a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
+++ b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
@@ -35,7 +35,7 @@
 
   static {
     IdeaWin32 instance = null;
-    if (SystemInfo.isWin2kOrNewer) {
+    if (SystemInfo.isWin2kOrNewer && Boolean.parseBoolean(System.getProperty("idea.use.native.fs.for.win", "true"))) {
       try {
         UrlClassLoader.loadPlatformLibrary("IdeaWin32");
         instance = new IdeaWin32();
diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
index 7ee904c..bc37f67 100644
--- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
@@ -923,6 +923,10 @@
     }
   }
 
+  public static String defaultIfEmpty(@Nullable String value, String defaultValue) {
+    return isEmpty(value) ? defaultValue : value;
+  }
+
   @Contract("null -> false")
   public static boolean isNotEmpty(@Nullable String s) {
     return s != null && !s.isEmpty();
@@ -2513,10 +2517,9 @@
   public static String shortenTextWithEllipsis(@NotNull final String text,
                                                final int maxLength,
                                                final int suffixLength,
-                                               boolean useEllipsisSymbol) {
+                                               @NotNull String symbol) {
     final int textLength = text.length();
     if (textLength > maxLength) {
-      String symbol = useEllipsisSymbol ? "\u2026" : "...";
       final int prefixLength = maxLength - suffixLength - symbol.length();
       assert prefixLength > 0;
       return text.substring(0, prefixLength) + symbol + text.substring(textLength - suffixLength);
@@ -2527,6 +2530,15 @@
   }
 
   @NotNull
+  public static String shortenTextWithEllipsis(@NotNull final String text,
+                                               final int maxLength,
+                                               final int suffixLength,
+                                               boolean useEllipsisSymbol) {
+    String symbol = useEllipsisSymbol ? "\u2026" : "...";
+    return shortenTextWithEllipsis(text, maxLength, suffixLength, symbol);
+  }
+
+  @NotNull
   public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength, boolean useEllipsisSymbol) {
     return shortenTextWithEllipsis(path, maxLength, (int)(maxLength * 0.7), useEllipsisSymbol);
   }
@@ -2650,6 +2662,63 @@
     return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s);
   }
 
+  public static String getShortened(String s, int maxWidth) {
+    int length = s.length();
+    if (isEmpty(s) || length <= maxWidth) return s;
+    ArrayList<String> words = new ArrayList<String>();
+
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < length; i++) {
+      char ch = s.charAt(i);
+
+      if (i == length - 1) {
+        builder.append(ch);
+        words.add(builder.toString());
+        builder.delete(0, builder.length());
+        continue;
+      }
+
+      if (i > 0 && (ch == '/' || ch == '\\' || ch == '.' || Character.isUpperCase(ch))) {
+        words.add(builder.toString());
+        builder.delete(0, builder.length());
+      }
+      builder.append(ch);
+    }
+    for (int i = 0; i < words.size(); i++) {
+      String word = words.get(i);
+      if (i < words.size() - 1 && word.length() == 1) {
+        words.remove(i);
+        words.set(i, word + words.get(i));
+      }
+    }
+
+    int removedLength = 0;
+
+    String toPaste = "...";
+    int index;
+    while (true) {
+      index = Math.max(0, (words.size() - 1) / 2);
+      String aWord = words.get(index);
+      words.remove(index);
+      int toCut = length - removedLength - maxWidth + 3;
+      if (words.size() < 2 || (toCut < aWord.length() - 2 && removedLength == 0)) {
+        int pos = (aWord.length() - toCut) / 2;
+        toPaste = aWord.substring(0, pos) + "..." + aWord.substring(pos+toCut);
+        break;
+      }
+      removedLength += aWord.length();
+      if (length - removedLength <= maxWidth - 3) {
+        break;
+      }
+    }
+    for (int i = 0; i < words.size(); i++) {
+      String word = words.get(i);
+      if (i == index || words.size() == 1) builder.append(toPaste);
+      builder.append(word);
+    }
+    return builder.toString().replaceAll("\\.{4,}", "...");
+  }
+
   /**
    * Expirable CharSequence. Very useful to control external library execution time,
    * i.e. when java.util.regex.Pattern match goes out of control.
diff --git a/platform/util/src/com/intellij/ui/JBColor.java b/platform/util/src/com/intellij/ui/JBColor.java
index d2b4a3b..3669e72 100644
--- a/platform/util/src/com/intellij/ui/JBColor.java
+++ b/platform/util/src/com/intellij/ui/JBColor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,9 @@
  */
 package com.intellij.ui;
 
+import com.intellij.util.NotNullProducer;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
 import java.awt.color.ColorSpace;
@@ -32,6 +34,7 @@
   private static volatile boolean DARK = UIUtil.isUnderDarcula();
 
   private final Color darkColor;
+  private final NotNullProducer<Color> func;
 
   public JBColor(int rgb, int darkRGB) {
     this(new Color(rgb), new Color(darkRGB));
@@ -42,6 +45,13 @@
     darkColor = dark;
     //noinspection AssignmentToStaticFieldFromInstanceMethod
     DARK = UIUtil.isUnderDarcula(); //Double check. Sometimes DARK != isDarcula() after dialogs appear on splash screen
+    func = null;
+  }
+
+  public JBColor(NotNullProducer<Color> function) {
+    super(0);
+    darkColor = null;
+    func = function;
   }
 
   public static void setDark(boolean dark) {
@@ -52,99 +62,142 @@
     return darkColor;
   }
 
+  Color getColor() {
+    if (func != null) {
+      return func.produce();
+    } else {
+      return DARK ? getDarkVariant() : this;
+    }
+  }
+
   @Override
   public int getRed() {
-    return DARK ? getDarkVariant().getRed() : super.getRed();
+    final Color c = getColor();
+    return c == this ? super.getRed() : c.getRed();
   }
 
   @Override
   public int getGreen() {
-    return DARK ? getDarkVariant().getGreen() : super.getGreen();
+    final Color c = getColor();
+    return c == this ? super.getGreen() : c.getGreen();
   }
 
   @Override
   public int getBlue() {
-    return DARK ? getDarkVariant().getBlue() : super.getBlue();
+    final Color c = getColor();
+    return c == this ? super.getBlue() : c.getBlue();
   }
 
   @Override
   public int getAlpha() {
-    return DARK ? getDarkVariant().getAlpha() : super.getAlpha();
+    final Color c = getColor();
+    return c == this ? super.getAlpha() : c.getAlpha();
   }
 
   @Override
   public int getRGB() {
-    return DARK ? getDarkVariant().getRGB() : super.getRGB();
+    final Color c = getColor();
+    return c == this ? super.getRGB() : c.getRGB();
   }
 
   @Override
   public Color brighter() {
+    if (func != null) {
+      return new JBColor(new NotNullProducer<Color>() {
+        @NotNull
+        @Override
+        public Color produce() {
+          return func.produce().brighter();
+        }
+      });
+    }
     return new JBColor(super.brighter(), getDarkVariant().brighter());
   }
 
   @Override
   public Color darker() {
+    if (func != null) {
+      return new JBColor(new NotNullProducer<Color>() {
+        @NotNull
+        @Override
+        public Color produce() {
+          return func.produce().darker();
+        }
+      });
+    }
     return new JBColor(super.darker(), getDarkVariant().darker());
   }
 
   @Override
   public int hashCode() {
-    return DARK ? getDarkVariant().hashCode() : super.hashCode();
+    final Color c = getColor();
+    return c == this ? super.hashCode() : c.hashCode();
   }
 
   @Override
   public boolean equals(Object obj) {
-    return DARK ? getDarkVariant().equals(obj) : super.equals(obj);
+    final Color c = getColor();
+    return c == this ? super.equals(obj) : c.equals(obj);
   }
 
   @Override
   public String toString() {
-    return DARK ? getDarkVariant().toString() : super.toString();
+    final Color c = getColor();
+    return c == this ? super.toString() : c.toString();
   }
 
   @Override
   public float[] getRGBComponents(float[] compArray) {
-    return DARK ? getDarkVariant().getRGBComponents(compArray) : super.getRGBComponents(compArray);
+    final Color c = getColor();
+    return c == this ? super.getRGBComponents(compArray) : c.getRGBComponents(compArray);
   }
 
   @Override
   public float[] getRGBColorComponents(float[] compArray) {
-    return DARK ? getDarkVariant().getRGBColorComponents(compArray) : super.getRGBComponents(compArray);
+    final Color c = getColor();
+    return c == this ? super.getRGBComponents(compArray) : c.getRGBColorComponents(compArray);
   }
 
   @Override
   public float[] getComponents(float[] compArray) {
-    return DARK ? getDarkVariant().getComponents(compArray) : super.getComponents(compArray);
+    final Color c = getColor();
+    return c == this ? super.getComponents(compArray) : c.getComponents(compArray);
   }
 
   @Override
   public float[] getColorComponents(float[] compArray) {
-    return DARK ? getDarkVariant().getColorComponents(compArray) : super.getColorComponents(compArray);
+    final Color c = getColor();
+    return c == this ? super.getColorComponents(compArray) : c.getColorComponents(compArray);
   }
 
   @Override
   public float[] getComponents(ColorSpace cspace, float[] compArray) {
-    return DARK ? getDarkVariant().getComponents(cspace, compArray) : super.getComponents(cspace, compArray);
+    final Color c = getColor();
+    return c == this ? super.getComponents(cspace, compArray) : c.getComponents(cspace, compArray);
   }
 
   @Override
   public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
-    return DARK ? getDarkVariant().getColorComponents(cspace, compArray) : super.getColorComponents(cspace, compArray);
+    final Color c = getColor();
+    return c == this ? super.getColorComponents(cspace, compArray) : c.getColorComponents(cspace, compArray);
   }
 
   @Override
   public ColorSpace getColorSpace() {
-    return DARK ? getDarkVariant().getColorSpace() : super.getColorSpace();
+    final Color c = getColor();
+    return c == this ? super.getColorSpace() : c.getColorSpace();
   }
 
   @Override
   public synchronized PaintContext createContext(ColorModel cm, Rectangle r, Rectangle2D r2d, AffineTransform xform, RenderingHints hints) {
-    return DARK ? getDarkVariant().createContext(cm, r, r2d, xform, hints) : super.createContext(cm, r, r2d, xform, hints);
+    final Color c = getColor();
+    return c == this ? super.createContext(cm, r, r2d, xform, hints) : c.createContext(cm, r, r2d, xform, hints);
   }
 
   @Override
   public int getTransparency() {
-    return DARK ? getDarkVariant().getTransparency() : super.getTransparency();
+    final Color c = getColor();
+    return c == this ? super.getTransparency() : c.getTransparency();
   }
 
   public static final JBColor red = new JBColor(Color.red, DarculaColors.RED);
@@ -196,7 +249,34 @@
   public static final Color cyan = new JBColor(Color.cyan, new Color(0, 137, 137));
   public static final Color CYAN = cyan;
 
-  public static Color foreground() {return UIUtil.getLabelForeground();}
+  public static Color foreground() {
+    return new JBColor(new NotNullProducer<Color>() {
+      @NotNull
+      @Override
+      public Color produce() {
+        return UIUtil.getLabelForeground();
+      }
+    });
+  }
 
-  public static Color background() {return UIUtil.getListBackground();}
+  public static Color background() {
+    return new JBColor(new NotNullProducer<Color>() {
+      @NotNull
+      @Override
+      public Color produce() {
+        return UIUtil.getListBackground();
+      }
+    });
+  }
+
+  public static Color border() {
+    return new JBColor(new NotNullProducer<Color>() {
+      @NotNull
+      @Override
+      public Color produce() {
+        //noinspection deprecation
+        return UIUtil.getBorderColor();
+      }
+    });
+  }
 }
diff --git a/platform/util/src/com/intellij/util/EventDispatcher.java b/platform/util/src/com/intellij/util/EventDispatcher.java
index 34361a8..e17c6e4 100644
--- a/platform/util/src/com/intellij/util/EventDispatcher.java
+++ b/platform/util/src/com/intellij/util/EventDispatcher.java
@@ -43,6 +43,7 @@
   }
 
   private EventDispatcher(@NotNull Class<T> listenerClass) {
+    LOG.assertTrue(listenerClass.isInterface(), "listenerClass must be an interface");
     InvocationHandler handler = new InvocationHandler() {
       @Override
       @NonNls
@@ -71,10 +72,7 @@
     };
 
     //noinspection unchecked
-    myMulticaster = (T)Proxy.newProxyInstance(listenerClass.getClassLoader(),
-                                              new Class[]{listenerClass},
-                                              handler
-    );
+    myMulticaster = (T)Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, handler);
   }
 
   @NotNull
@@ -82,7 +80,7 @@
     return myMulticaster;
   }
 
-  private void dispatch(final Method method, final Object[] args) {
+  private void dispatch(@NotNull Method method, Object[] args) {
     method.setAccessible(true);
 
     for (T listener : myListeners) {
diff --git a/platform/util/src/com/intellij/util/PatternUtil.java b/platform/util/src/com/intellij/util/PatternUtil.java
index 7159a90..0b683dd 100644
--- a/platform/util/src/com/intellij/util/PatternUtil.java
+++ b/platform/util/src/com/intellij/util/PatternUtil.java
@@ -17,8 +17,9 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.containers.HashMap;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
@@ -29,30 +30,22 @@
 
 public class PatternUtil {
   private static final Logger LOG = Logger.getInstance("#com.intellij.util.PatternUtil");
-  private static final HashMap<String, String> ourEscapeRules = new HashMap<String, String>();
+
+  public static final Pattern NOTHING = Pattern.compile("(a\\A)");
+
+  private static final Map<String, String> ourEscapeRules = ContainerUtil.newLinkedHashMap();
 
   static {
     // '.' should be escaped first
     ourEscapeRules.put("*", ".*");
     ourEscapeRules.put("?", ".");
-    escape2('+');
-    escape2('(');
-    escape2(')');
-    escape2('[');
-    escape2(']');
-    escape2('/');
-    escape2('^');
-    escape2('$');
-    escape2('{');
-    escape2('}');
-    escape2('|');
+    for (char c : "+()[]/^${}|".toCharArray()) {
+      ourEscapeRules.put(String.valueOf(c), "\\" + c);
+    }
   }
 
-  private static void escape2(char symbol) {
-    ourEscapeRules.put(String.valueOf(symbol), "\\" + symbol);
-  }
-
-  public static String convertToRegex(String mask) {
+  @NotNull
+  public static String convertToRegex(@NotNull String mask) {
     List<String> strings = StringUtil.split(mask, "\\");
     StringBuilder pattern = new StringBuilder();
     String separator = "";
@@ -69,17 +62,26 @@
     return pattern.toString();
   }
 
-  public static Pattern fromMask(@NonNls String mask) {
-//    String pattern = mask.replaceAll("\\.", "\\.").replaceAll("\\*", ".*").replaceAll("\\?", ".");
+  @NotNull
+  public static Pattern fromMask(@NotNull String mask) {
     try {
       return Pattern.compile(convertToRegex(mask));
     }
     catch (PatternSyntaxException e) {
       LOG.error(mask, e);
-      return Pattern.compile("");
+      return NOTHING;
     }
   }
 
+  @Contract("_, !null->!null")
+  public static Pattern compileSafe(String pattern, Pattern def) {
+    try {
+      return Pattern.compile(pattern);
+    }
+    catch (Exception e) {
+      return def;
+    }
+  }
   /**
    * Finds the first match in a list os Strings.
    *
diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java
index a4bf431..df33a80 100644
--- a/platform/util/src/com/intellij/util/ReflectionUtil.java
+++ b/platform/util/src/com/intellij/util/ReflectionUtil.java
@@ -426,6 +426,26 @@
     }
   }
 
+  /**
+   * {@link Class#newInstance()} cannot instantiate private classes
+   */
+  @NotNull
+  public static <T> T newInstance(@NotNull Class<T> aClass, @NotNull Class... parameterTypes) {
+    try {
+      Constructor<T> constructor = aClass.getDeclaredConstructor(parameterTypes);
+      try {
+        constructor.setAccessible(true);
+      }
+      catch (SecurityException e) {
+        return aClass.newInstance();
+      }
+      return constructor.newInstance();
+    }
+    catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   @NotNull
   public static <T> T createInstance(@NotNull Constructor<T> constructor, @NotNull Object... args) {
     try {
diff --git a/platform/util/src/com/intellij/util/Restarter.java b/platform/util/src/com/intellij/util/Restarter.java
index 7f1584d..01e7fc4 100644
--- a/platform/util/src/com/intellij/util/Restarter.java
+++ b/platform/util/src/com/intellij/util/Restarter.java
@@ -153,12 +153,11 @@
   }
 
   public static File createTempExecutable(File executable) throws IOException {
-    String ext = FileUtilRt.getExtension(executable.getName());
-    File copy = FileUtilRt.createTempFile(FileUtilRt.getNameWithoutExtension(executable.getName()),
-                                          StringUtil.isEmptyOrSpaces(ext) ? ".tmp" : ("." + ext),
-                                          false);
-    FileUtilRt.copy(executable, copy);
-    if (!copy.setExecutable(executable.canExecute())) throw new IOException("Cannot make file executable: " + copy);
+    File copy = new File(System.getProperty("user.home") + "/." + System.getProperty("idea.paths.selector") + "/restart/" + executable.getName());
+    if (FileUtilRt.ensureCanCreateFile(copy)) {
+      FileUtilRt.copy(executable, copy);
+      if (!copy.setExecutable(executable.canExecute())) throw new IOException("Cannot make file executable: " + copy);
+    }
     return copy;
   }
 
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index 6052df2..171cfab 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
@@ -828,6 +828,7 @@
 
   @NotNull
   public static <T> List<T> findAll(@NotNull Collection<? extends T> collection, @NotNull Condition<? super T> condition) {
+    if (collection.isEmpty()) return emptyList();
     final List<T> result = new SmartList<T>();
     for (final T t : collection) {
       if (condition.value(t)) {
diff --git a/platform/util/src/com/intellij/util/containers/LongStack.java b/platform/util/src/com/intellij/util/containers/LongStack.java
new file mode 100644
index 0000000..8e1005b
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/LongStack.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package com.intellij.util.containers;
+
+/**
+ * @author lambdamix
+ */
+import java.util.EmptyStackException;
+
+public class LongStack {
+  private long[] data;
+  private int size;
+  public LongStack(int initialCapacity) {
+    data = new long[initialCapacity];
+    size = 0;
+  }
+
+  public LongStack() {
+    this(5);
+  }
+
+  public void push(long t) {
+    if (size >= data.length) {
+      long[] newdata = new long[data.length * 3 / 2];
+      System.arraycopy(data, 0, newdata, 0, size);
+      data = newdata;
+    }
+    data[size++] = t;
+  }
+
+  public long peek() {
+    if (size == 0) throw new EmptyStackException();
+    return data[size - 1];
+  }
+
+  public long pop() {
+    if (size == 0) throw new EmptyStackException();
+    return data[--size];
+  }
+
+  public boolean empty() {
+    return size == 0;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o instanceof LongStack) {
+      LongStack otherStack = (LongStack)o;
+      if (size != otherStack.size) return false;
+      for (int i = 0; i < otherStack.size; i++) {
+        if (data[i] != otherStack.data[i]) return false;
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  public void clear() {
+    size = 0;
+  }
+}
diff --git a/platform/util/src/com/intellij/util/diff/DiffTree.java b/platform/util/src/com/intellij/util/diff/DiffTree.java
index 0bab60d..680b15b 100644
--- a/platform/util/src/com/intellij/util/diff/DiffTree.java
+++ b/platform/util/src/com/intellij/util/diff/DiffTree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.util.diff;
 
 import com.intellij.openapi.util.Ref;
@@ -39,7 +38,6 @@
                    final FlyweightCapableTreeStructure<NT> newTree,
                    final ShallowNodeComparator<OT, NT> comparator,
                    final DiffTreeChangeBuilder<OT, NT> consumer) {
-
     myOldTree = oldTree;
     myNewTree = newTree;
     myComparator = comparator;
@@ -53,7 +51,7 @@
     new DiffTree<OT, NT>(oldTree, newTree, comparator, consumer).build(oldTree.getRoot(), newTree.getRoot(), 0);
   }
 
-  private static enum CompareResult {
+  private enum CompareResult {
     EQUAL, // 100% equal
     DRILL_DOWN_NEEDED, // element types are equal, but elements are composite
     TYPE_ONLY, // only element types are equal
@@ -146,6 +144,7 @@
         newIndex++;
         continue;
       }
+
       CompareResult c12 = looksEqual(comparator, oldChild1, newChild2);
       if (c12 == CompareResult.EQUAL || c12 == CompareResult.DRILL_DOWN_NEEDED || c12 == CompareResult.TYPE_ONLY) {
         myConsumer.nodeInserted(oldNode, newChild1, newIndex);
@@ -170,6 +169,7 @@
         oldIndex++;
         continue;
       }
+
       myConsumer.nodeReplaced(oldChild1, newChild1);
       oldIndex++;
       newIndex++;
diff --git a/platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java b/platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java
new file mode 100644
index 0000000..78f1fdd
--- /dev/null
+++ b/platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package com.intellij.util.io;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author lambdamix
+ */
+public class LongInlineKeyDescriptor implements KeyDescriptor<Long> {
+  public static LongInlineKeyDescriptor INSTANCE = new LongInlineKeyDescriptor();
+
+  @Override
+  public final int getHashCode(Long value) {
+    return value.hashCode();
+  }
+
+  @Override
+  public final boolean isEqual(Long val1, Long val2) {
+    return val1.longValue() == val2.longValue();
+  }
+
+  @Override
+  public final void save(@NotNull DataOutput out, Long value) throws IOException {
+    out.writeLong(value.longValue());
+  }
+
+  @Override
+  public final Long read(@NotNull DataInput in) throws IOException {
+    return in.readLong();
+  }
+
+}
diff --git a/platform/util/src/com/intellij/util/text/StringSearcher.java b/platform/util/src/com/intellij/util/text/StringSearcher.java
index 22e9db2..d5bc95f 100644
--- a/platform/util/src/com/intellij/util/text/StringSearcher.java
+++ b/platform/util/src/com/intellij/util/text/StringSearcher.java
@@ -21,6 +21,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
+import java.util.Locale;
 
 public class StringSearcher {
   private static final Logger LOG = Logger.getInstance("#com.intellij.util.text.StringSearcher");
@@ -48,7 +49,7 @@
     myPattern = pattern;
     myCaseSensitive = caseSensitive;
     myForwardDirection = forwardDirection;
-    myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase().toCharArray();
+    myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase(Locale.US).toCharArray();
     myPatternLength = myPatternArray.length;
     Arrays.fill(mySearchTable, -1);
     myJavaIdentifier = pattern.isEmpty() ||
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index 7ed8021..aec2a35 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.java
@@ -1586,7 +1586,7 @@
                                           @NotNull Graphics g,
                                           boolean useRetinaCondition,
                                           Consumer<Graphics2D> paintRoutine) {
-    if (!useRetinaCondition || !isRetina() || Registry.is("ide.mac.retina.disableDrawingFix", false)) {
+    if (!useRetinaCondition || !isRetina() || Registry.is("ide.mac.retina.disableDrawingFix")) {
       paintRoutine.consume((Graphics2D)g);
     }
     else {
@@ -1904,6 +1904,10 @@
     return INACTIVE_HEADER_COLOR;
   }
 
+  /**
+   * @deprecated
+   * @use JBColor.border()
+   */
   public static Color getBorderColor() {
     return isUnderDarcula() ? Gray._50 : BORDER_COLOR;
   }
@@ -2769,7 +2773,7 @@
 
   @NotNull
   public static Paint getGradientPaint(float x1, float y1, @NotNull Color c1, float x2, float y2, @NotNull Color c2) {
-    return (Registry.is("ui.no.bangs.and.whistles", false)) ? ColorUtil.mix(c1, c2, .5) : new GradientPaint(x1, y1, c1, x2, y2, c2);
+    return (Registry.is("ui.no.bangs.and.whistles")) ? ColorUtil.mix(c1, c2, .5) : new GradientPaint(x1, y1, c1, x2, y2, c2);
   }
 
   @Nullable
diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
index c25ea4e..6cc2124 100644
--- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
+++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
@@ -16,13 +16,13 @@
 package com.intellij.util.xmlb;
 
 import com.intellij.openapi.util.Pair;
+import com.intellij.util.ReflectionUtil;
 import org.jdom.*;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.lang.annotation.Annotation;
 import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.*;
@@ -184,16 +184,9 @@
   /**
    * {@link Class#newInstance()} cannot instantiate private classes
    */
-  static <T> T newInstance(Class<T> aClass) {
+  static <T> T newInstance(@NotNull Class<T> aClass) {
     try {
-      Constructor<T> constructor = aClass.getDeclaredConstructor();
-      try {
-        constructor.setAccessible(true);
-      }
-      catch (SecurityException e) {
-        return aClass.newInstance();
-      }
-      return constructor.newInstance();
+      return ReflectionUtil.newInstance(aClass);
     }
     catch (Exception e) {
       throw new XmlSerializationException(e);
diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
index 2f31dc4..383c07f 100644
--- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
@@ -195,4 +195,23 @@
     assertEquals(Arrays.asList("\n", "\r\n", "\n", "\r\n", "\r", "\r", "aa\r", "bb\r\n", "cc\n", "\r", "dd\n", "\n", "\r\n", "\r"),
                  Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\r\n\n\r\n\r\raa\rbb\r\ncc\n\rdd\n\n\r\n\r")));
   }
+
+  public void testShortened() {
+    String[] names = {"AVeryVeeryLongClassName.java", "com.test.SomeJAVAClassName.java", "strangelowercaseclassname.java", "PrefixPostfix.java", "SomeJAVAClassName.java"};
+    for (String name : names) {
+      for (int i = name.length() + 1; i > 15; i--) {
+        String shortened = StringUtil.getShortened(name, i);
+        assertTrue(shortened.length() <= i);
+        assertTrue(!shortened.contains("...."));
+        int pos = shortened.indexOf("...");
+        if (pos != -1) {
+          assertTrue(name.startsWith(shortened.substring(0, pos)));
+          assertTrue(name.endsWith(shortened.substring(pos + 3)));
+        }
+        else {
+          assertEquals(shortened,  name);
+        }
+      }
+    }
+  }
 }
diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
index 377abeb..9a3fcb9 100644
--- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
+++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
@@ -495,6 +495,22 @@
       "</BeanWithFieldWithTagAnnotation>", bean);
   }
 
+  public void testEscapeCharsInTagText() {
+    BeanWithFieldWithTagAnnotation bean = new BeanWithFieldWithTagAnnotation();
+    bean.STRING_V = "a\nb\"<";
+
+    doSerializerTest(
+      "<BeanWithFieldWithTagAnnotation>\n" +
+      "  <name>a\nb&quot;&lt;</name>\n" +
+      "</BeanWithFieldWithTagAnnotation>", bean);
+  }
+
+  public void testEscapeCharsInAttributeValue() {
+    final BeanWithPropertiesBoundToAttribute bean = new BeanWithPropertiesBoundToAttribute();
+    bean.name = "a\nb\"<";
+    doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"a&#10;b&quot;&lt;\" />", bean);
+  }
+
   public void testShuffledDeserialize() {
     BeanWithPublicFields bean = new BeanWithPublicFields();
     bean.INT_V = 987;
diff --git a/platform/util/util.iml b/platform/util/util.iml
index d0155fd..c015e73 100644
--- a/platform/util/util.iml
+++ b/platform/util/util.iml
@@ -5,6 +5,7 @@
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
     </content>
     <orderEntry type="library" scope="PROVIDED" name="Mac" level="project" />
     <orderEntry type="inheritedJdk" />
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
index 04ce78b..c6b0daa 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
@@ -272,6 +272,7 @@
   public abstract VcsHistoryCache getVcsHistoryCache();
   public abstract ContentRevisionCache getContentRevisionCache();
   public abstract boolean isFileInContent(final VirtualFile vf);
+  public abstract boolean isIgnored(VirtualFile vf);
 
   public abstract boolean dvcsUsedInProject();
 
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
index 006276b..9834ef5 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
@@ -134,6 +134,7 @@
   public abstract List<CommitExecutor> getRegisteredExecutors();
 
   public abstract void addFilesToIgnore(final IgnoredFileBean... ignoredFiles);
+  public abstract void addDirectoryToIgnoreImplicitly(@NotNull String path);
   public abstract void setFilesToIgnore(final IgnoredFileBean... ignoredFiles);
   public abstract IgnoredFileBean[] getFilesToIgnore();
   public abstract boolean isIgnoredFile(@NotNull VirtualFile file);
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
index c09ce97..1091f90 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
@@ -26,7 +26,7 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
 import com.intellij.util.PatternUtil;
@@ -49,7 +49,8 @@
     myType = type;
     if (IgnoreSettingsType.FILE.equals(type)) {
       myFilenameIfFile = new File(path).getName();
-    } else {
+    }
+    else {
       myFilenameIfFile = null;
     }
     myProject = project;
@@ -115,9 +116,10 @@
     if (myType == IgnoreSettingsType.MASK) {
       myMatcher.reset(file.getName());
       return myMatcher.matches();
-    } else {
+    }
+    else {
       // quick check for 'file' == exact match pattern
-      if (IgnoreSettingsType.FILE.equals(myType) && ! myFilenameIfFile.equals(file.getName())) return false;
+      if (IgnoreSettingsType.FILE.equals(myType) && !myFilenameIfFile.equals(file.getName())) return false;
 
       VirtualFile selector = resolve();
       if (Comparing.equal(selector, NullVirtualFile.INSTANCE)) return false;
@@ -130,7 +132,7 @@
           // special case for ignoring the project base dir (IDEADEV-16056)
           return !file.isDirectory() && Comparing.equal(file.getParent(), selector);
         }
-        return VfsUtil.isAncestor(selector, file, false);
+        return VfsUtilCore.isAncestor(selector, file, false);
       }
     }
   }
@@ -146,7 +148,9 @@
 
   @Nullable
   private VirtualFile doResolve() {
-    if (myProject == null || myProject.isDisposed()) { return null; }
+    if (myProject == null || myProject.isDisposed()) {
+      return null;
+    }
     VirtualFile baseDir = myProject.getBaseDir();
 
     String path = FileUtil.toSystemIndependentName(myPath);
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
index b97305c..c8a8eda 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
@@ -17,7 +17,7 @@
 
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
 import java.util.Iterator;
@@ -28,7 +28,7 @@
 public interface VcsDirtyScopeModifier {
   Iterator<FilePath> getDirtyFilesIterator();
   Collection<VirtualFile> getAffectedVcsRoots();
-  @Nullable
+  @NotNull
   Iterator<FilePath> getDirtyDirectoriesIterator(VirtualFile root);
   void recheckDirtyKeys();
 }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
index b9f0855..5e01fea 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
@@ -23,15 +23,20 @@
 import com.intellij.openapi.components.ProjectComponent;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.progress.EmptyProgressIndicator;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.DumbAwareRunnable;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.impl.DirectoryIndexExcludePolicy;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.*;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.*;
 import com.intellij.openapi.vcs.changes.conflicts.ChangelistConflictTracker;
@@ -43,6 +48,7 @@
 import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.EditorNotifications;
 import com.intellij.util.*;
@@ -68,8 +74,10 @@
 /**
  * @author max
  */
-public class ChangeListManagerImpl extends ChangeListManagerEx implements ProjectComponent, ChangeListOwner, JDOMExternalizable, RoamingTypeDisabled {
+public class ChangeListManagerImpl extends ChangeListManagerEx implements ProjectComponent, ChangeListOwner, JDOMExternalizable,
+                                                                          RoamingTypeDisabled {
   public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.ChangeListManagerImpl");
+  private static final String EXCLUDED_CONVERTED_TO_IGNORED_OPTION = "EXCLUDED_CONVERTED_TO_IGNORED";
 
   private final Project myProject;
   private final VcsConfiguration myConfig;
@@ -101,6 +109,7 @@
   private final List<CommitExecutor> myExecutors = new ArrayList<CommitExecutor>();
 
   private final IgnoredFilesComponent myIgnoredIdeaLevel;
+  private boolean myExcludedConvertedToIgnored;
   private ProgressIndicator myUpdateChangesProgressIndicator;
 
   public static final Topic<LocalChangeListsLoadedListener> LISTS_LOADED = new Topic<LocalChangeListsLoadedListener>(
@@ -191,6 +200,7 @@
 
   /**
    * Shows the proposal to delete one or more changelists that were default and became empty.
+   *
    * @return true if the changelists have to be deleted, false if not.
    */
   private boolean showRemoveEmptyChangeListsProposal(@NotNull final VcsConfiguration config, @NotNull Collection<LocalChangeList> lists) {
@@ -242,7 +252,7 @@
   public void unblockModalNotifications() {
     myModalNotificationsBlocked = false;
     if (myListsToBeDeleted.isEmpty()) {
-      return ;
+      return;
     }
     if (showRemoveEmptyChangeListsProposal(myConfig, myListsToBeDeleted)) {
       for (LocalChangeList list : myListsToBeDeleted) {
@@ -261,14 +271,14 @@
       vcsManager.addVcsListener(myVcsListener);
     }
     else {
-      ((ProjectLevelVcsManagerImpl) vcsManager).addInitializationRequest(
+      ((ProjectLevelVcsManagerImpl)vcsManager).addInitializationRequest(
         VcsInitObject.CHANGE_LIST_MANAGER, new DumbAwareRunnable() {
-        public void run() {
-          myUpdater.initialized();
-          broadcastStateAfterLoad();
-          vcsManager.addVcsListener(myVcsListener);
-        }
-      });
+          public void run() {
+            myUpdater.initialized();
+            broadcastStateAfterLoad();
+            vcsManager.addVcsListener(myVcsListener);
+          }
+        });
     }
 
     myConflictTracker.startTracking();
@@ -279,7 +289,9 @@
     synchronized (myDataLock) {
       listCopy = getChangeListsCopy();
     }
-    myProject.getMessageBus().syncPublisher(LISTS_LOADED).processLoadedLists(listCopy);
+    if (!myProject.isDisposed()) {
+      myProject.getMessageBus().syncPublisher(LISTS_LOADED).processLoadedLists(listCopy);
+    }
   }
 
   private void initializeForNewProject() {
@@ -297,11 +309,29 @@
               myIgnoredIdeaLevel.add(IgnoredBeanFactory.ignoreFile(Project.DIRECTORY_STORE_FOLDER + "/workspace.xml", myProject));
             }
           }
+          if (!Registry.is("ide.hide.excluded.files") && !myExcludedConvertedToIgnored) {
+            convertExcludedToIgnored();
+            myExcludedConvertedToIgnored = true;
+          }
         }
       }
     });
   }
 
+  void convertExcludedToIgnored() {
+    for (DirectoryIndexExcludePolicy policy : DirectoryIndexExcludePolicy.EP_NAME.getExtensions(myProject)) {
+      for (VirtualFile file : policy.getExcludeRootsForProject()) {
+        addDirectoryToIgnoreImplicitly(file.getPath());
+      }
+    }
+
+    for (Module module : ModuleManager.getInstance(myProject).getModules()) {
+      for (String url : ModuleRootManager.getInstance(module).getExcludeRootUrls()) {
+        addDirectoryToIgnoreImplicitly(VfsUtilCore.urlToPath(url));
+      }
+    }
+  }
+
   public void projectClosed() {
     ProjectLevelVcsManager.getInstance(myProject).removeVcsListener(myVcsListener);
 
@@ -328,11 +358,12 @@
 
   /**
    * update itself might produce actions done on AWT thread (invoked-after),
-   * so waiting for its completion on AWT thread is not good
-   *
-   * runnable is invoked on AWT thread
+   * so waiting for its completion on AWT thread is not good runnable is invoked on AWT thread
    */
-  public void invokeAfterUpdate(final Runnable afterUpdate, final InvokeAfterUpdateMode mode, @Nullable final String title, @Nullable final ModalityState state) {
+  public void invokeAfterUpdate(final Runnable afterUpdate,
+                                final InvokeAfterUpdateMode mode,
+                                @Nullable final String title,
+                                @Nullable final ModalityState state) {
     myUpdater.invokeAfterUpdate(afterUpdate, mode, title, null, state);
   }
 
@@ -394,13 +425,13 @@
       synchronized (myDataLock) {
         final IgnoredFilesHolder fileHolder = (IgnoredFilesHolder)myComposite.get(FileHolder.HolderType.IGNORED);
 
-        for (Iterator<VcsDirtyScope> iterator = scopes.iterator(); iterator.hasNext();) {
-          final VcsModifiableDirtyScope scope = (VcsModifiableDirtyScope) iterator.next();
+        for (Iterator<VcsDirtyScope> iterator = scopes.iterator(); iterator.hasNext(); ) {
+          final VcsModifiableDirtyScope scope = (VcsModifiableDirtyScope)iterator.next();
           final VcsDirtyScopeModifier modifier = scope.getModifier();
           if (modifier != null) {
             fileHolder.notifyVcsStarted(scope.getVcs());
             final Iterator<FilePath> filesIterator = modifier.getDirtyFilesIterator();
-            for (; filesIterator.hasNext();) {
+            while (filesIterator.hasNext()) {
               final FilePath dirtyFile = filesIterator.next();
               if ((dirtyFile.getVirtualFile() != null) && isIgnoredFile(dirtyFile.getVirtualFile())) {
                 filesIterator.remove();
@@ -411,7 +442,7 @@
             final Collection<VirtualFile> roots = modifier.getAffectedVcsRoots();
             for (VirtualFile root : roots) {
               final Iterator<FilePath> dirIterator = modifier.getDirtyDirectoriesIterator(root);
-              for (; dirIterator.hasNext(); ) {
+              while (dirIterator.hasNext()) {
                 final FilePath dir = dirIterator.next();
                 if ((dir.getVirtualFile() != null) && isIgnoredFile(dir.getVirtualFile())) {
                   dirIterator.remove();
@@ -428,10 +459,10 @@
         }
       }
     }
-    catch(Exception ex) {
+    catch (Exception ex) {
       LOG.error(ex);
     }
-    catch(AssertionError ex) {
+    catch (AssertionError ex) {
       LOG.error(ex);
     }
     for (VirtualFile file : refreshFiles) {
@@ -443,7 +474,7 @@
     final DataHolder dataHolder;
 
     final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
-    if (! vcsManager.hasActiveVcss()) return;
+    if (!vcsManager.hasActiveVcss()) return;
 
     final VcsInvalidated invalidated = myDirtyScopeManager.retrieveScopes();
     if (checkScopeIsEmpty(invalidated)) return;
@@ -458,14 +489,14 @@
       // mark for "modifier" that update started (it would create duplicates of modification commands done by user during update;
       // after update of copies of objects is complete, it would apply the same modifications to copies.)
       synchronized (myDataLock) {
-        dataHolder = new DataHolder((FileHolderComposite) myComposite.copy(), myWorker.copy(), wasEverythingDirty);
+        dataHolder = new DataHolder((FileHolderComposite)myComposite.copy(), myWorker.copy(), wasEverythingDirty);
         myModifier.enterUpdate();
         if (wasEverythingDirty) {
           myUpdateException = null;
           myAdditionalInfo = null;
         }
       }
-      final String scopeInString = (! LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
+      final String scopeInString = (!LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
         @Override
         public String fun(VcsDirtyScope scope) {
           return scope.toString();
@@ -504,7 +535,7 @@
               myWorker.onAfterWorkerSwitch(oldWorker);
               myModifier.setWorker(myWorker);
               LOG.debug("refresh procedure finished, unversioned size: " +
-                           dataHolder.getComposite().getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize() + "\n changes: " + myWorker);
+                        dataHolder.getComposite().getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize() + "\n changes: " + myWorker);
               final boolean statusChanged = !myComposite.equals(dataHolder.getComposite());
               myComposite = dataHolder.getComposite();
               if (statusChanged) {
@@ -535,19 +566,20 @@
     catch (DisposedException e) {
       // OK, we're finishing all the stuff now.
     }
-    catch(ProcessCanceledException e) {
+    catch (ProcessCanceledException e) {
       // OK, we're finishing all the stuff now.
-    } catch (RuntimeInterruptedException ignore) {
     }
-    catch(Exception ex) {
+    catch (RuntimeInterruptedException ignore) {
+    }
+    catch (Exception ex) {
       LOG.error(ex);
     }
-    catch(AssertionError ex) {
+    catch (AssertionError ex) {
       LOG.error(ex);
     }
     finally {
       myDirtyScopeManager.changesProcessed();
-      
+
       synchronized (myDataLock) {
         myDelayedNotificator.getProxyDispatcher().changeListUpdateDone();
         myChangesViewManager.scheduleRefresh();
@@ -556,7 +588,7 @@
   }
 
   private boolean checkScopeIsAllIgnored(VcsInvalidated invalidated) {
-    if (! invalidated.isEverythingDirty()) {
+    if (!invalidated.isEverythingDirty()) {
       filterOutIgnoredFiles(invalidated.getScopes());
       if (invalidated.isEmpty()) {
         return true;
@@ -586,7 +618,8 @@
       }
     };
     final UpdatingChangeListBuilder builder = new UpdatingChangeListBuilder(dataHolder.getChangeListWorker(),
-      dataHolder.getComposite(), disposedGetter, myIgnoredIdeaLevel, gate);
+                                                                            dataHolder.getComposite(), disposedGetter, myIgnoredIdeaLevel,
+                                                                            gate);
 
     for (final VcsDirtyScope scope : scopes) {
       myUpdateChangesProgressIndicator.checkCanceled();
@@ -594,7 +627,7 @@
       final AbstractVcs vcs = scope.getVcs();
       if (vcs == null) continue;
       scope.setWasEverythingDirty(wasEverythingDirty);
-      final VcsModifiableDirtyScope adjustedScope = vcs.adjustDirtyScope((VcsModifiableDirtyScope) scope);
+      final VcsModifiableDirtyScope adjustedScope = vcs.adjustDirtyScope((VcsModifiableDirtyScope)scope);
 
       myChangesViewManager.setBusy(true);
       dataHolder.notifyStartProcessingChanges(adjustedScope);
@@ -614,7 +647,8 @@
     final ContentRevisionCache cache = ProjectLevelVcsManager.getInstance(myProject).getContentRevisionCache();
     if (invalidated.isEverythingDirty()) {
       cache.clearAllCurrent();
-    } else {
+    }
+    else {
       cache.clearScope(invalidated.getScopes());
     }
   }
@@ -625,6 +659,7 @@
       public boolean isCanceled() {
         return myUpdater.isStopped();
       }
+
       @Override
       public void checkCanceled() {
         checkIfDisposed();
@@ -651,7 +686,7 @@
     }
 
     public void notifyStartProcessingChanges(@NotNull final VcsModifiableDirtyScope scope) {
-      if (! myWasEverythingDirty) {
+      if (!myWasEverythingDirty) {
         myComposite.cleanAndAdjustScope(scope);
         myChangeListWorker.notifyStartProcessingChanges(scope);
       }
@@ -661,7 +696,7 @@
     }
 
     public void notifyDoneProcessingChanges() {
-      if (! myWasEverythingDirty) {
+      if (!myWasEverythingDirty) {
         myChangeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
       }
     }
@@ -695,11 +730,14 @@
           handleUpdateException(e);
         }
       }
-    } catch (ProcessCanceledException ignore) {
-    } catch (Throwable t) {
+    }
+    catch (ProcessCanceledException ignore) {
+    }
+    catch (Throwable t) {
       LOG.debug(t);
       Rethrow.reThrowRuntime(t);
-    } finally {
+    }
+    finally {
       if (!myUpdater.isStopped()) {
         dataHolder.notifyDoneProcessingChanges();
       }
@@ -748,8 +786,7 @@
   }
 
   /**
-   * @deprecated 
-   * this method made equivalent to {@link #getChangeListsCopy()} so to don't be confused by method name,
+   * @deprecated this method made equivalent to {@link #getChangeListsCopy()} so to don't be confused by method name,
    * better use {@link #getChangeListsCopy()}
    */
   @NotNull
@@ -816,13 +853,14 @@
 
   Map<VirtualFile, LogicalLock> getLogicallyLockedFolders() {
     synchronized (myDataLock) {
-      return new HashMap<VirtualFile, LogicalLock>(((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
+      return new HashMap<VirtualFile, LogicalLock>(
+        ((LogicallyLockedHolder)myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
     }
   }
 
   public boolean isLogicallyLocked(final VirtualFile file) {
     synchronized (myDataLock) {
-      return ((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).containsKey(file);
+      return ((LogicallyLockedHolder)myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).containsKey(file);
     }
   }
 
@@ -847,7 +885,7 @@
   @Nullable
   Map<VirtualFile, String> getSwitchedRoots() {
     synchronized (myDataLock) {
-      return ((SwitchedFileHolder) myComposite.get(FileHolder.HolderType.ROOT_SWITCH)).getFilesMapCopy();
+      return ((SwitchedFileHolder)myComposite.get(FileHolder.HolderType.ROOT_SWITCH)).getFilesMapCopy();
     }
   }
 
@@ -856,7 +894,7 @@
       return myUpdateException;
     }
   }
-  
+
   public Factory<JComponent> getAdditionalUpdateInfo() {
     synchronized (myDataLock) {
       return myAdditionalInfo;
@@ -937,7 +975,7 @@
             synchronized (myDataLock) {
               for (Map.Entry<String, List<Change>> entry : map.entrySet()) {
                 final List<Change> changes = entry.getValue();
-                for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext();) {
+                for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext(); ) {
                   final Change change = iterator.next();
                   if (getChangeList(change) != null) {
                     // was not actually rolled back
@@ -948,7 +986,7 @@
               }
               for (String listName : map.keySet()) {
                 final LocalChangeList byName = myWorker.getCopyByName(listName);
-                if (byName != null && byName.getChanges().isEmpty() && ! byName.isDefault() && ! byName.isReadOnly()) {
+                if (byName != null && byName.getChanges().isEmpty() && !byName.isDefault() && !byName.isReadOnly()) {
                   myWorker.removeChangeList(listName);
                 }
               }
@@ -1005,15 +1043,14 @@
   }
 
   /**
-   * @deprecated
-   * better use normal comparison, with equals
+   * @deprecated better use normal comparison, with equals
    */
   @Nullable
   public LocalChangeList getIdentityChangeList(Change change) {
     synchronized (myDataLock) {
       final List<LocalChangeList> lists = myWorker.getListsCopy();
       for (LocalChangeList list : lists) {
-        for(Change oldChange: list.getChanges()) {
+        for (Change oldChange : list.getChanges()) {
           if (oldChange == change) {
             return list;
           }
@@ -1168,7 +1205,7 @@
 
     if (exceptions.size() > 0) {
       StringBuilder message = new StringBuilder(VcsBundle.message("error.adding.files.prompt"));
-      for(VcsException ex: exceptions) {
+      for (VcsException ex : exceptions) {
         message.append("\n").append(ex.getMessage());
       }
       Messages.showErrorDialog(myProject, message.toString(), VcsBundle.message("error.adding.files.title"));
@@ -1189,7 +1226,7 @@
               synchronized (myDataLock) {
                 List<Change> changesToMove = new ArrayList<Change>();
                 final LocalChangeList defaultList = getDefaultChangeList();
-                for(Change change: defaultList.getChanges()) {
+                for (Change change : defaultList.getChanges()) {
                   final ContentRevision afterRevision = change.getAfterRevision();
                   if (afterRevision != null) {
                     VirtualFile vFile = afterRevision.getFile().getVirtualFile();
@@ -1208,8 +1245,9 @@
 
           myChangesViewManager.scheduleRefresh();
         }
-      },  InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, VcsBundle.message("change.lists.manager.add.unversioned"), null);
-    } else {
+      }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, VcsBundle.message("change.lists.manager.add.unversioned"), null);
+    }
+    else {
       myChangesViewManager.scheduleRefresh();
     }
   }
@@ -1238,8 +1276,8 @@
   private boolean doCommit(final LocalChangeList changeList, final List<Change> changes, final boolean synchronously) {
     FileDocumentManager.getInstance().saveAllDocuments();
     return new CommitHelper(myProject, changeList, changes, changeList.getName(),
-                     StringUtil.isEmpty(changeList.getComment()) ? changeList.getName() : changeList.getComment(),
-                     new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL, null).doCommit();
+                            StringUtil.isEmpty(changeList.getComment()) ? changeList.getName() : changeList.getComment(),
+                            new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL, null).doCommit();
   }
 
   public void commitChangesSynchronously(LocalChangeList changeList, List<Change> changes) {
@@ -1252,20 +1290,21 @@
 
   @SuppressWarnings({"unchecked"})
   public void readExternal(Element element) throws InvalidDataException {
-    if (! myProject.isDefault()) {
+    if (!myProject.isDefault()) {
       synchronized (myDataLock) {
         myIgnoredIdeaLevel.clear();
         new ChangeListManagerSerialization(myIgnoredIdeaLevel, myWorker).readExternal(element);
-        if ((! myWorker.isEmpty()) && getDefaultChangeList() == null) {
+        if ((!myWorker.isEmpty()) && getDefaultChangeList() == null) {
           setDefaultChangeList(myWorker.getListsCopy().get(0));
         }
       }
+      myExcludedConvertedToIgnored = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION));
       myConflictTracker.loadState(element);
     }
   }
 
   public void writeExternal(Element element) throws WriteExternalException {
-    if (! myProject.isDefault()) {
+    if (!myProject.isDefault()) {
       final IgnoredFilesComponent ignoredFilesComponent;
       final ChangeListWorker worker;
       synchronized (myDataLock) {
@@ -1273,6 +1312,9 @@
         worker = myWorker.copy();
       }
       new ChangeListManagerSerialization(ignoredFilesComponent, worker).writeExternal(element);
+      if (myExcludedConvertedToIgnored) {
+        JDOMExternalizerUtil.writeField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION, String.valueOf(true));
+      }
       myConflictTracker.saveState(element);
     }
   }
@@ -1316,10 +1358,11 @@
         }
         if (vf.isDirectory()) {
           myDirs.add(vf);
-        } else {
+        }
+        else {
           myFiles.add(vf);
         }
-        ++ myCnt;
+        ++myCnt;
       }
     }
 
@@ -1327,7 +1370,8 @@
       final VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
       if (myEveryThing) {
         vcsDirtyScopeManager.markEverythingDirty();
-      } else {
+      }
+      else {
         vcsDirtyScopeManager.filesDirty(myFiles, myDirs);
       }
     }
@@ -1338,12 +1382,21 @@
     scheduleUnversionedUpdate();
   }
 
+  @Override
+  public void addDirectoryToIgnoreImplicitly(@NotNull String path) {
+    myIgnoredIdeaLevel.addIgnoredDirectoryImplicitly(path, myProject);
+  }
+
+  public IgnoredFilesComponent getIgnoredFilesComponent() {
+    return myIgnoredIdeaLevel;
+  }
+
   private void scheduleUnversionedUpdate() {
     final MyDirtyFilesScheduler scheduler = new MyDirtyFilesScheduler(myProject);
 
     synchronized (myDataLock) {
       final VirtualFileHolder unversionedHolder = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED);
-      final IgnoredFilesHolder ignoredHolder = (IgnoredFilesHolder) myComposite.get(FileHolder.HolderType.IGNORED);
+      final IgnoredFilesHolder ignoredHolder = (IgnoredFilesHolder)myComposite.get(FileHolder.HolderType.IGNORED);
 
       scheduler.accept(unversionedHolder.getFiles());
       scheduler.accept(ignoredHolder.values());
@@ -1368,7 +1421,7 @@
   }
 
   private void exchangeWithIgnored(FileHolderComposite composite, VirtualFileHolder vfHolder, List<VirtualFile> unversionedFiles) {
-    for(VirtualFile file: unversionedFiles) {
+    for (VirtualFile file : unversionedFiles) {
       if (isIgnoredFile(file)) {
         vfHolder.removeFile(file);
         composite.getIgnoredFileHolder().addFile(file);
@@ -1594,11 +1647,11 @@
     if (freezeReason != null) {
       if (modalTitle != null) {
         Messages.showErrorDialog(myProject, freezeReason, modalTitle);
-      } else {
+      }
+      else {
         VcsBalloonProblemNotifier.showOverChangesView(myProject, freezeReason, MessageType.WARNING);
       }
     }
     return freezeReason != null;
   }
-
 }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
index a4c30e6..0e20b41 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
@@ -22,12 +22,10 @@
 import com.intellij.openapi.util.text.StringUtil;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
 
 class ChangeListManagerSerialization {
   @NonNls static final String ATT_ID = "id";
@@ -44,6 +42,8 @@
   @NonNls static final String NODE_LIST = "list";
   @NonNls static final String NODE_IGNORED = "ignored";
   @NonNls static final String NODE_CHANGE = "change";
+  @NonNls static final String MANUALLY_REMOVED_FROM_IGNORED = "manually-removed-from-ignored";
+  @NonNls static final String DIRECTORY_TAG = "directory";
 
   private final IgnoredFilesComponent myIgnoredIdeaLevel;
   private final ChangeListWorker myWorker;
@@ -60,9 +60,17 @@
       readChangeList(listNode);
     }
     final List<Element> ignoredNodes = element.getChildren(NODE_IGNORED);
-    for (Element ignoredNode: ignoredNodes) {
+    for (Element ignoredNode : ignoredNodes) {
       readFileToIgnore(ignoredNode);
     }
+    Element manuallyRemovedFromIgnoredTag = element.getChild(MANUALLY_REMOVED_FROM_IGNORED);
+    Set<String> manuallyRemovedFromIgnoredPaths = new HashSet<String>();
+    if (manuallyRemovedFromIgnoredTag != null) {
+      for (Element tag : manuallyRemovedFromIgnoredTag.getChildren(DIRECTORY_TAG)) {
+        manuallyRemovedFromIgnoredPaths.add(tag.getAttributeValue(ATT_PATH));
+      }
+    }
+    myIgnoredIdeaLevel.setDirectoriesManuallyRemovedFromIgnored(manuallyRemovedFromIgnoredPaths);
   }
 
   private void readChangeList(final Element listNode) {
@@ -90,7 +98,6 @@
     if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_READONLY))) {
       list.setReadOnly(true);
     }
-
   }
 
   private void readFileToIgnore(final Element ignoredNode) {
@@ -123,7 +130,10 @@
 
       listNode.setAttribute(ATT_ID, list.getId());
       listNode.setAttribute(ATT_NAME, list.getName());
-      listNode.setAttribute(ATT_COMMENT, list.getComment());
+      String comment = list.getComment();
+      if (comment != null) {
+        listNode.setAttribute(ATT_COMMENT, comment);
+      }
       List<Change> changes = new ArrayList<Change>(list.getChanges());
       Collections.sort(changes, new ChangeComparator());
       for (Change change : changes) {
@@ -131,26 +141,35 @@
       }
     }
     final IgnoredFileBean[] filesToIgnore = myIgnoredIdeaLevel.getFilesToIgnore();
-    for(IgnoredFileBean bean: filesToIgnore) {
-        Element fileNode = new Element(NODE_IGNORED);
-        element.addContent(fileNode);
-        String path = bean.getPath();
-        if (path != null) {
-          fileNode.setAttribute("path", path);
-        }
-        String mask = bean.getMask();
-        if (mask != null) {
-          fileNode.setAttribute("mask", mask);
-        }
+    for (IgnoredFileBean bean : filesToIgnore) {
+      Element fileNode = new Element(NODE_IGNORED);
+      element.addContent(fileNode);
+      String path = bean.getPath();
+      if (path != null) {
+        fileNode.setAttribute("path", path);
       }
+      String mask = bean.getMask();
+      if (mask != null) {
+        fileNode.setAttribute("mask", mask);
+      }
+    }
+    Set<String> manuallyRemovedFromIgnored = myIgnoredIdeaLevel.getDirectoriesManuallyRemovedFromIgnored();
+    if (!manuallyRemovedFromIgnored.isEmpty()) {
+      Element list = new Element(MANUALLY_REMOVED_FROM_IGNORED);
+      for (String path : manuallyRemovedFromIgnored) {
+        list.addContent(new Element(DIRECTORY_TAG).setAttribute(ATT_PATH, path));
+      }
+      element.addContent(list);
+    }
   }
 
   private static class ChangeComparator implements Comparator<Change> {
     @Override
-    public int compare(Change o1, Change o2) {
+    public int compare(@NotNull Change o1, @NotNull Change o2) {
       return Comparing.compare(o1.toString(), o2.toString());
     }
   }
+
   private static void writeChange(final Element listNode, final Change change) {
     Element changeNode = new Element(NODE_CHANGE);
     listNode.addContent(changeNode);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
index 6d13d21..f81c506 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
@@ -16,7 +16,10 @@
 package com.intellij.openapi.vcs.changes;
 
 import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.BeforeAfter;
 
 import java.util.List;
@@ -30,13 +33,41 @@
   private final Document myBefore;
   private final Document myAfter;
   private final List<BeforeAfter<TextRange>> myRanges;
-  private boolean myOneSide;
-  private boolean myIsAddition;
 
-  public FragmentedContent(Document before, Document after, List<BeforeAfter<TextRange>> ranges) {
+  private final boolean myOneSide;
+  private final boolean myIsAddition;
+
+  private final VirtualFile myFileBefore;
+  private final VirtualFile myFileAfter;
+  private final FileType myFileTypeBefore;
+  private final FileType myFileTypeAfter;
+
+  public FragmentedContent(Document before, Document after, List<BeforeAfter<TextRange>> ranges, Change change) {
     myBefore = before;
     myAfter = after;
     myRanges = ranges;
+
+    final FileStatus fs = change.getFileStatus();
+    myIsAddition = FileStatus.ADDED.equals(fs);
+    myOneSide = FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs);
+
+    if (change.getBeforeRevision() != null) {
+      myFileBefore = change.getBeforeRevision().getFile().getVirtualFile();
+      myFileTypeBefore = change.getBeforeRevision().getFile().getFileType();
+    }
+    else {
+      myFileBefore = null;
+      myFileTypeBefore = null;
+    }
+
+    if (change.getAfterRevision() != null) {
+      myFileAfter = change.getAfterRevision().getFile().getVirtualFile();
+      myFileTypeAfter = change.getAfterRevision().getFile().getFileType();
+    }
+    else {
+      myFileAfter = null;
+      myFileTypeAfter = null;
+    }
   }
 
   public Document getBefore() {
@@ -50,7 +81,7 @@
   public List<BeforeAfter<TextRange>> getRanges() {
     return myRanges;
   }
-  
+
   public int getSize() {
     return myRanges.size();
   }
@@ -59,15 +90,23 @@
     return myOneSide;
   }
 
-  public void setOneSide(boolean oneSide) {
-    myOneSide = oneSide;
-  }
-
   public boolean isAddition() {
     return myIsAddition;
   }
 
-  public void setIsAddition(boolean isAddition) {
-    myIsAddition = isAddition;
+  public VirtualFile getFileBefore() {
+    return myFileBefore;
+  }
+
+  public VirtualFile getFileAfter() {
+    return myFileAfter;
+  }
+
+  public FileType getFileTypeBefore() {
+    return myFileTypeBefore;
+  }
+
+  public FileType getFileTypeAfter() {
+    return myFileTypeAfter;
   }
 }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
index 2f3788a..77dd9b3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
@@ -81,10 +81,7 @@
     }
     List<BeforeAfter<TextRange>> ranges = calculator.getRanges();
     if (ranges == null || ranges.isEmpty()) return null;
-    FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges);
-    final FileStatus fs = change.getFileStatus();
-    fragmentedContent.setIsAddition(FileStatus.ADDED.equals(fs));
-    fragmentedContent.setOneSide(FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs));
+    FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges, change);
     VirtualFile file = filePath.getVirtualFile();
     if (file == null) {
       filePath.hardRefresh();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
index 5c8ac2a..b2eaa1f 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.vcs.changes;
 
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.newvfs.BulkFileListener;
@@ -27,6 +28,7 @@
 public class IgnoredFilesComponent {
   private final Set<IgnoredFileBean> myFilesToIgnore;
   private final Map<String, IgnoredFileBean> myFilesMap;
+  private final Set<String> myDirectoriesManuallyRemovedFromIgnored;
 
   public IgnoredFilesComponent(final Project project, final boolean registerListener) {
     myFilesToIgnore = new LinkedHashSet<IgnoredFileBean>();
@@ -40,20 +42,53 @@
         }
       });
     }
+    myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>();
   }
 
   public IgnoredFilesComponent(final IgnoredFilesComponent other) {
     myFilesToIgnore = new LinkedHashSet<IgnoredFileBean>(other.myFilesToIgnore);
     myFilesMap = new HashMap<String, IgnoredFileBean>(other.myFilesMap);
+    myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>(other.myDirectoriesManuallyRemovedFromIgnored);
   }
 
   public void add(final IgnoredFileBean... filesToIgnore) {
-    synchronized(myFilesToIgnore) {
+    synchronized (myFilesToIgnore) {
       Collections.addAll(myFilesToIgnore, filesToIgnore);
       addIgnoredFiles(filesToIgnore);
     }
   }
 
+  public Set<String> getDirectoriesManuallyRemovedFromIgnored() {
+    return Collections.unmodifiableSet(myDirectoriesManuallyRemovedFromIgnored);
+  }
+
+  public void setDirectoriesManuallyRemovedFromIgnored(Set<String> directories) {
+    myDirectoriesManuallyRemovedFromIgnored.clear();
+    myDirectoriesManuallyRemovedFromIgnored.addAll(directories);
+  }
+
+  public void addIgnoredDirectoryImplicitly(@NotNull String path, @NotNull Project project) {
+    synchronized (myFilesToIgnore) {
+      if (myDirectoriesManuallyRemovedFromIgnored.contains(path) || myDirectoriesManuallyRemovedFromIgnored.contains(path + "/")) {
+        return;
+      }
+      for (IgnoredFileBean bean : myFilesToIgnore) {
+        if (bean.getType() == IgnoreSettingsType.UNDER_DIR && FileUtil.isAncestor(bean.getPath(), path, false)) {
+          return;
+        }
+      }
+      List<IgnoredFileBean> toRemove = new ArrayList<IgnoredFileBean>();
+      for (IgnoredFileBean bean : myFilesToIgnore) {
+        if ((bean.getType() == IgnoreSettingsType.UNDER_DIR || bean.getType() == IgnoreSettingsType.FILE) &&
+            FileUtil.isAncestor(path, bean.getPath(), false)) {
+          toRemove.add(bean);
+        }
+      }
+      myFilesToIgnore.removeAll(toRemove);
+      myFilesToIgnore.add(IgnoredBeanFactory.ignoreUnderDirectory(path, project));
+    }
+  }
+
   private void addIgnoredFiles(final IgnoredFileBean... filesToIgnore) {
     for (IgnoredFileBean bean : filesToIgnore) {
       if (IgnoreSettingsType.FILE.equals(bean.getType())) {
@@ -73,6 +108,7 @@
       myFilesMap.clear();
     }
   }
+
   public boolean isEmpty() {
     synchronized (myFilesToIgnore) {
       return myFilesToIgnore.isEmpty();
@@ -80,7 +116,7 @@
   }
 
   public void set(final IgnoredFileBean... filesToIgnore) {
-    synchronized(myFilesToIgnore) {
+    synchronized (myFilesToIgnore) {
       myFilesToIgnore.clear();
       Collections.addAll(myFilesToIgnore, filesToIgnore);
       myFilesMap.clear();
@@ -89,7 +125,7 @@
   }
 
   public IgnoredFileBean[] getFilesToIgnore() {
-    synchronized(myFilesToIgnore) {
+    synchronized (myFilesToIgnore) {
       return myFilesToIgnore.toArray(new IgnoredFileBean[myFilesToIgnore.size()]);
     }
   }
@@ -103,14 +139,14 @@
   }
 
   public boolean isIgnoredFile(@NotNull VirtualFile file) {
-    synchronized(myFilesToIgnore) {
+    synchronized (myFilesToIgnore) {
       if (myFilesToIgnore.size() == 0) return false;
 
       final String path = FilePathsHelper.convertPath(file);
       final IgnoredFileBean fileBean = myFilesMap.get(path);
       if (fileBean != null && fileBean.matchesFile(file)) return true;
 
-      for(IgnoredFileBean bean: myFilesToIgnore) {
+      for (IgnoredFileBean bean : myFilesToIgnore) {
         if (bean.matchesFile(file)) return true;
       }
       return false;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
index c413cca..1d310d5 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
@@ -1,14 +1,13 @@
 package com.intellij.openapi.vcs.changes;
 
-import com.intellij.lifecycle.PeriodicalTasksCloser;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.history.VcsRevisionNumber;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.containers.OpenTHashSet;
@@ -147,12 +146,11 @@
     createReadChangesCache();
     final Collection<Change> result = new ArrayList<Change>();
     myChangesBeforeUpdate = new OpenTHashSet<Change>(myChanges);
-    final FileIndexFacade fileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
     for (Change oldBoy : myChangesBeforeUpdate) {
       final ContentRevision before = oldBoy.getBeforeRevision();
       final ContentRevision after = oldBoy.getAfterRevision();
       if (scope == null || before != null && scope.belongsTo(before.getFile()) || after != null && scope.belongsTo(after.getFile())
-        || isIgnoredChange(oldBoy, fileIndex)) {
+        || isIgnoredChange(oldBoy, project)) {
         result.add(oldBoy);
         myChanges.remove(oldBoy);
         myReadChangesCache = null;
@@ -161,18 +159,21 @@
     return result;
   }
 
-  private static boolean isIgnoredChange(final Change change, final FileIndexFacade fileIndex) {
-    boolean beforeRevIgnored = change.getBeforeRevision() == null || isIgnoredRevision(change.getBeforeRevision(), fileIndex);
-    boolean afterRevIgnored = change.getAfterRevision() == null || isIgnoredRevision(change.getAfterRevision(), fileIndex);
+  private static boolean isIgnoredChange(@NotNull Change change, @NotNull Project project) {
+    boolean beforeRevIgnored = change.getBeforeRevision() == null || isIgnoredRevision(change.getBeforeRevision(), project);
+    boolean afterRevIgnored = change.getAfterRevision() == null || isIgnoredRevision(change.getAfterRevision(), project);
     return beforeRevIgnored && afterRevIgnored;
   }
 
-  private static boolean isIgnoredRevision(final ContentRevision revision, final FileIndexFacade fileIndex) {
+  private static boolean isIgnoredRevision(final @NotNull ContentRevision revision, final @NotNull Project project) {
     return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
       @Override
       public Boolean compute() {
+        if (project.isDisposed()) {
+          return false;
+        }
         VirtualFile vFile = revision.getFile().getVirtualFile();
-        return vFile != null && fileIndex.isExcludedFile(vFile);
+        return vFile != null && ProjectLevelVcsManager.getInstance(project).isIgnored(vFile);
       }
     });
   }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
index 2c2d063..6e8a1a0 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
@@ -18,6 +18,8 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diff.DiffContent;
 import com.intellij.openapi.diff.SimpleContent;
+import com.intellij.openapi.diff.impl.DiffHighlighterFactory;
+import com.intellij.openapi.diff.impl.DiffHighlighterFactoryImpl;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.highlighter.*;
@@ -35,6 +37,7 @@
 import com.intellij.openapi.vcs.VcsConfiguration;
 import com.intellij.openapi.vcs.history.VcsRevisionNumber;
 import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.BeforeAfter;
 import com.intellij.util.Consumer;
@@ -140,6 +143,9 @@
                  fragmentedContent.getBefore(), fragmentedContent.getAfter());
         // add "artificial" empty lines
 
+        final Document document = fragmentedContent.getBefore();
+        final Document document1 = fragmentedContent.getAfter();
+
         // line starts
         BeforeAfter<Integer> lines = new BeforeAfter<Integer>(0, 0);
         for (BeforeAfter<TextRange> lineNumbers : expandedRanges) {
@@ -155,7 +161,6 @@
           oldConvertor.put(lines.getBefore(), lineNumbers.getBefore().getStartOffset());
           newConvertor.put(lines.getAfter(), lineNumbers.getAfter().getStartOffset());
 
-          final Document document = fragmentedContent.getBefore();
           if (sbOld.length() > 0) {
             sbOld.append('\n');
           }
@@ -164,7 +169,6 @@
           myBeforeFragments.add(beforeRange);
           sbOld.append(document.getText(beforeRange));
 
-          final Document document1 = fragmentedContent.getAfter();
           if (sbNew.length() > 0) {
             sbNew.append('\n');
           }
@@ -180,7 +184,23 @@
         myLineRanges.add(new BeforeAfter<Integer>(lines.getBefore() == 0 ? 0 : lines.getBefore() - 1,
                                                   lines.getAfter() == 0 ? 0 : lines.getAfter() - 1));
 
-        setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges);
+        if (!expandedRanges.isEmpty()) {
+          BeforeAfter<TextRange> last = expandedRanges.get(expandedRanges.size() - 1);
+          if (sbOld.length() > 0) {
+            if (document.getLineEndOffset(last.getBefore().getEndOffset()) != document.getTextLength()) {
+              sbOld.append('\n');
+              oldConvertor.emptyLine(lines.getBefore());
+            }
+          }
+          if (sbNew.length() > 0) {
+            if (document1.getLineEndOffset(last.getAfter().getEndOffset()) != document1.getTextLength()) {
+              sbNew.append('\n');
+              newConvertor.emptyLine(lines.getAfter());
+            }
+          }
+        }
+
+        setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges, fragmentedContent);
         setTodoHighlighting(fragmentedContent.getBefore(), fragmentedContent.getAfter());
       }
     });
@@ -323,29 +343,37 @@
   }
 
   private void setHighlighters(final Document oldDocument, final Document document,
-                               List<BeforeAfter<TextRange>> ranges) {
-    EditorHighlighterFactory editorHighlighterFactory = EditorHighlighterFactory.getInstance();
-    final SyntaxHighlighter syntaxHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(myFileType, myProject, null);
-    final EditorHighlighter highlighter =
-      editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme());
-
+                               List<BeforeAfter<TextRange>> ranges, FragmentedContent fragmentedContent) {
+    EditorHighlighter highlighter = createHighlighter(fragmentedContent.getFileTypeBefore(),
+                                                      fragmentedContent.getFileBefore(),
+                                                      fragmentedContent.getFileAfter(), myProject).createHighlighter();
     highlighter.setEditor(new LightHighlighterClient(oldDocument, myProject));
     highlighter.setText(oldDocument.getText());
     HighlighterIterator iterator = highlighter.createIterator(ranges.get(0).getBefore().getStartOffset());
-    FragmentedEditorHighlighter beforeHighlighter =
-      new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true);
+    FragmentedEditorHighlighter beforeHighlighter = new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true);
     setBeforeHighlighter(beforeHighlighter);
 
-    final EditorHighlighter highlighter1 =
-      editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme());
+    EditorHighlighter highlighter1 = createHighlighter(fragmentedContent.getFileTypeAfter(),
+                                                       fragmentedContent.getFileAfter(),
+                                                       fragmentedContent.getFileBefore(), myProject).createHighlighter();
     highlighter1.setEditor(new LightHighlighterClient(document, myProject));
     highlighter1.setText(document.getText());
     HighlighterIterator iterator1 = highlighter1.createIterator(ranges.get(0).getAfter().getStartOffset());
-    FragmentedEditorHighlighter afterHighlighter =
-      new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true);
+    FragmentedEditorHighlighter afterHighlighter = new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true);
     setAfterHighlighter(afterHighlighter);
   }
 
+  private DiffHighlighterFactory createHighlighter(FileType contentType,
+                                                   VirtualFile file,
+                                                   VirtualFile otherFile,
+                                                   Project project) {
+    VirtualFile baseFile = file;
+    if (baseFile == null) baseFile = otherFile;
+    if (contentType == null) contentType = myFileType;
+
+    return new DiffHighlighterFactoryImpl(contentType, baseFile, project);
+  }
+
   private void setTodoHighlighting(final Document oldDocument, final Document document) {
     final ContentRevisionCache cache = ProjectLevelVcsManager.getInstance(myProject).getContentRevisionCache();
     final List<Pair<TextRange,TextAttributes>> beforeTodoRanges = myBeforeNumber == null ? Collections.<Pair<TextRange,TextAttributes>>emptyList() :
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
index fdc0796..d06c8f8 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
@@ -15,16 +15,15 @@
  */
 package com.intellij.openapi.vcs.changes;
 
-import com.intellij.lifecycle.PeriodicalTasksCloser;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.FileTypeManager;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Factory;
 import com.intellij.openapi.util.Getter;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.FilePathImpl;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsKey;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.Nullable;
@@ -40,7 +39,7 @@
   private VcsDirtyScope myScope;
   private FoldersCutDownWorker myFoldersCutDownWorker;
   private final IgnoredFilesComponent myIgnoredFilesComponent;
-  private final FileIndexFacade myIndex;
+  private final ProjectLevelVcsManager myVcsManager;
   private final ChangeListManagerGate myGate;
   private Factory<JComponent> myAdditionalInfo;
 
@@ -53,7 +52,7 @@
     myDisposedGetter = disposedGetter;
     myIgnoredFilesComponent = ignoredFilesComponent;
     myGate = gate;
-    myIndex = PeriodicalTasksCloser.getInstance().safeGetService(changeListWorker.getProject(), FileIndexFacade.class);
+    myVcsManager = ProjectLevelVcsManager.getInstance(changeListWorker.getProject());
   }
 
   private void checkIfDisposed() {
@@ -117,12 +116,12 @@
     myChangeListWorker.removeRegisteredChangeFor(path);
   }
 
-  private boolean isExcluded(final VirtualFile file) {
+  private boolean isIgnoredByVcs(final VirtualFile file) {
     return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
       @Override
       public Boolean compute() {
         checkIfDisposed();
-        return myIndex.isExcludedFile(file);
+        return myVcsManager.isIgnored(file);
       }
     });
   }
@@ -133,7 +132,7 @@
     }
     if (file == null) return;
     checkIfDisposed();
-    if (isExcluded(file)) return;
+    if (isIgnoredByVcs(file)) return;
     if (myScope.belongsTo(new FilePathImpl(file))) {
       if (myIgnoredFilesComponent.isIgnoredFile(file)) {
         myComposite.getIgnoredFileHolder().addFile(file);
@@ -165,7 +164,7 @@
   public void processModifiedWithoutCheckout(final VirtualFile file) {
     if (file == null) return;
     checkIfDisposed();
-    if (isExcluded(file)) return;
+    if (isIgnoredByVcs(file)) return;
     if (myScope.belongsTo(new FilePathImpl(file))) {
       if (LOG.isDebugEnabled()) {
         LOG.debug("processModifiedWithoutCheckout " + file);
@@ -177,7 +176,7 @@
   public void processIgnoredFile(final VirtualFile file) {
     if (file == null) return;
     checkIfDisposed();
-    if (isExcluded(file)) return;
+    if (isIgnoredByVcs(file)) return;
     if (myScope.belongsTo(new FilePathImpl(file))) {
       IgnoredFilesHolder ignoredFilesHolder = myComposite.getIgnoredFileHolder();
       if (ignoredFilesHolder instanceof IgnoredFilesCompositeHolder) {
@@ -212,7 +211,7 @@
   public void processSwitchedFile(final VirtualFile file, final String branch, final boolean recursive) {
     if (file == null) return;
     checkIfDisposed();
-    if (isExcluded(file)) return;
+    if (isIgnoredByVcs(file)) return;
     if (myScope.belongsTo(new FilePathImpl(file))) {
       myChangeListWorker.addSwitched(file, branch, recursive);
     }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
index eb44d59..c8617dc 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
@@ -34,6 +34,7 @@
 import com.intellij.util.containers.MultiMap;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
@@ -75,14 +76,14 @@
         return ContainerUtil.concatIterators(iteratorList);
       }
 
-      @Nullable
+      @NotNull
       @Override
       public Iterator<FilePath> getDirtyDirectoriesIterator(final VirtualFile root) {
         final THashSet<FilePath> filePaths = myDirtyDirectoriesRecursively.get(root);
         if (filePaths != null) {
           return filePaths.iterator();
         }
-        return null;
+        return ContainerUtil.emptyIterator();
       }
 
       @Override
@@ -338,10 +339,8 @@
   }
 
   /**
-   * Add dirty file to the scope. Note that file is not added
-   * if its ancestor was added as dirty recursively or if its parent
-   * is in already in the dirty scope. Also immendiate non-directory
-   * children are removed from the set of dirty files.
+   * Add dirty file to the scope. Note that file is not added if its ancestor was added as dirty recursively or if its parent is in already
+   * in the dirty scope. Also immediate non-directory children are removed from the set of dirty files.
    *
    * @param newcomer a file or directory added to the dirty scope.
    */
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
index 00ca9f2..112caa4 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
@@ -73,7 +73,7 @@
         final boolean inContent = myVcsManager.isFileInContent(validParent);
         if (inContent) return true;
         if (filePath != null) {
-          return isFileInBaseDir(filePath, myProject.getBaseDir()) && !myExcludedFileIndex.isExcludedFile(validParent);
+          return isFileInBaseDir(filePath, myProject.getBaseDir()) && !myVcsManager.isIgnored(validParent);
         }
         return false;
       }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
index 02586bb..f70c844 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
@@ -20,6 +20,7 @@
 import com.intellij.openapi.diff.DiffRequestFactory;
 import com.intellij.openapi.diff.MergeRequest;
 import com.intellij.openapi.diff.SimpleDiffRequest;
+import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Getter;
 import com.intellij.openapi.util.io.FileUtil;
@@ -60,6 +61,7 @@
   public MyResult step(DiffChainContext context) {
     if (myChange.getAfterRevision() == null) return createErrorResult();
     final Getter<MergeTexts> mergeProvider = myChange.getMergeProvider();
+    FileType type = myChange.getVirtualFile() != null ? myChange.getVirtualFile().getFileType() : null;
     if (mergeProvider != null) {
       // guaranteed text
       final MergeTexts texts = mergeProvider.get();
@@ -67,7 +69,7 @@
         return createErrorResult();
       }
       final MergeRequest request = DiffRequestFactory.getInstance()
-        .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), myProject, null, null);
+        .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), type, myProject, null, null);
       request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl()));
       // todo titles?
       request.setVersionTitles(new String[] {myChange.getAfterRevision().getRevisionNumber().asString(),
@@ -95,7 +97,8 @@
         final MergeRequest request = DiffRequestFactory.getInstance()
           .create3WayDiffRequest(CharsetToolkit.bytesToString(mergeData.CURRENT, charset),
                                  CharsetToolkit.bytesToString(mergeData.LAST, charset),
-                                 CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset), myProject, null, null);
+                                 CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset),
+                                 type, myProject, null, null);
         request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl()));
         // todo titles?
         VcsRevisionNumber lastRevisionNumber = mergeData.LAST_REVISION_NUMBER;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
index 6b4a3fb..f7fbe4c 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
@@ -325,7 +325,7 @@
       MergeRequest request;
       if (myReadOnly) {
         request = DiffRequestFactory.getInstance()
-          .create3WayDiffRequest(leftText, rightText, originalContent, project, null, null);
+          .create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, null, null);
       } else {
         request = DiffRequestFactory.getInstance().createMergeRequest(reverse ? rightText : leftText,
                                                                       reverse ? leftText : rightText, originalContent,
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
index 05b4e95..a3ddc2b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
@@ -58,7 +58,10 @@
       return new MyResult(badDiffRequest, DiffPresentationReturnValue.useRequest);
     }
     final MergeRequest request = DiffRequestFactory.getInstance()
-      .create3WayDiffRequest(revisionTexts.getLocal().toString(), revisionTexts.getPatched(), revisionTexts.getBase().toString(), myProject, null, null);
+      .create3WayDiffRequest(revisionTexts.getLocal().toString(),
+                             revisionTexts.getPatched(),
+                             revisionTexts.getBase().toString(),
+                             filePath.getFileType(), myProject, null, null);
     request.setWindowTitle(VcsBundle.message("patch.apply.conflict.title", FileUtil.toSystemDependentName(myFile.getPresentableUrl())));
     request.setVersionTitles(new String[] {"Current Version", "Base Version", FileUtil.toSystemDependentName(myAfterTitle)});
     return new MyResult(request, DiffPresentationReturnValue.useRequest);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
index fe9c120..ee33903 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
@@ -24,13 +24,11 @@
 import java.util.List;
 
 public class FilePathChangesTreeList extends ChangesTreeList<FilePath> {
-  private final Project myProject;
 
   public FilePathChangesTreeList(@NotNull Project project, @NotNull List<FilePath> originalFiles,
                                  boolean showCheckboxes, boolean highlightProblems,
                                  @Nullable Runnable inclusionListener, @Nullable ChangeNodeDecorator nodeDecorator) {
     super(project, originalFiles, showCheckboxes, highlightProblems, inclusionListener, nodeDecorator);
-    myProject = project;
   }
 
   protected DefaultTreeModel buildTreeModel(final List<FilePath> changes, ChangeNodeDecorator changeNodeDecorator) {
@@ -43,10 +41,7 @@
 
   @Nullable
   protected FilePath getLeadSelectedObject(final ChangesBrowserNode node) {
-    final Object userObject = node.getUserObject();
-    if (userObject instanceof FilePath) {
-      return (FilePath) userObject;
-    }
-    return null;
+    Object userObject = node.getUserObject();
+    return userObject instanceof FilePath ? (FilePath)userObject : null;
   }
 }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
index 82b676a..6edfbb9 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
@@ -27,7 +27,8 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vcs.VcsBundle;
-import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
+import com.intellij.openapi.vcs.changes.IgnoreSettingsType;
 import com.intellij.openapi.vcs.changes.IgnoredFileBean;
 import com.intellij.ui.*;
 import com.intellij.ui.components.JBList;
@@ -37,13 +38,16 @@
 
 import javax.swing.*;
 import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
 
 public class IgnoredSettingsPanel implements SearchableConfigurable, Configurable.NoScroll {
   private JBList myList;
   private JPanel myPanel;
   private final Project myProject;
   private DefaultListModel myModel;
-  private final ChangeListManager myChangeListManager;
+  private final ChangeListManagerImpl myChangeListManager;
+  private final Set<String> myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>();
 
   public IgnoredSettingsPanel(Project project) {
     myList = new JBList();
@@ -51,7 +55,7 @@
     myList.getEmptyText().setText(VcsBundle.message("no.ignored.files"));
 
     myProject = project;
-    myChangeListManager = ChangeListManager.getInstance(myProject);
+    myChangeListManager = ChangeListManagerImpl.getInstanceImpl(myProject);
   }
 
   private void setItems(final IgnoredFileBean[] filesToIgnore) {
@@ -97,32 +101,30 @@
   }
 
   private void deleteItems() {
-    boolean contigiousSelection = true;
-    int minSelectionIndex = myList.getSelectionModel().getMinSelectionIndex();
-    int maxSelectionIndex = myList.getSelectionModel().getMaxSelectionIndex();
-    for (int i = minSelectionIndex; i <= maxSelectionIndex; i++) {
-      if (!myList.getSelectionModel().isSelectedIndex(i)) {
-        contigiousSelection = false;
-        break;
+    for (Object o : myList.getSelectedValues()) {
+      IgnoredFileBean bean = (IgnoredFileBean)o;
+      if (bean.getType() == IgnoreSettingsType.UNDER_DIR) {
+        myDirectoriesManuallyRemovedFromIgnored.add(bean.getPath());
       }
     }
-    if (contigiousSelection) {
-      myModel.removeRange(minSelectionIndex, maxSelectionIndex);
-    }
-    else {
-      final Object[] selection = myList.getSelectedValues();
-      for (Object item : selection) {
-        myModel.removeElement(item);
-      }
-    }
+    ListUtil.removeSelectedItems(myList);
   }
 
   public void reset() {
     setItems(myChangeListManager.getFilesToIgnore());
+    myDirectoriesManuallyRemovedFromIgnored.clear();
+    myDirectoriesManuallyRemovedFromIgnored.addAll(myChangeListManager.getIgnoredFilesComponent().getDirectoriesManuallyRemovedFromIgnored());
   }
 
   public void apply() {
-    myChangeListManager.setFilesToIgnore(getItems());
+    IgnoredFileBean[] toIgnore = getItems();
+    myChangeListManager.setFilesToIgnore(toIgnore);
+    for (IgnoredFileBean bean : toIgnore) {
+      if (bean.getType() == IgnoreSettingsType.UNDER_DIR) {
+        myDirectoriesManuallyRemovedFromIgnored.remove(bean.getPath());
+      }
+    }
+    myChangeListManager.getIgnoredFilesComponent().setDirectoriesManuallyRemovedFromIgnored(myDirectoriesManuallyRemovedFromIgnored);
   }
 
   public boolean isModified() {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
index 6f1cd15..d332d1f 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
@@ -160,11 +160,16 @@
     localShowPrevAction.copyFrom(globalShowPrevAction);
 
     final RollbackLineStatusRangeAction rollback = new RollbackLineStatusRangeAction(tracker, range, editor);
-    EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
-    group.add(rollback);
+    final ShowLineStatusRangeDiffAction showDiff = new ShowLineStatusRangeDiffAction(tracker, range, editor);
+    final CopyLineStatusRangeAction copyRange = new CopyLineStatusRangeAction(tracker, range);
 
-    group.add(new ShowLineStatusRangeDiffAction(tracker, range, editor));
-    group.add(new CopyLineStatusRangeAction(tracker, range));
+    group.add(rollback);
+    group.add(showDiff);
+    group.add(copyRange);
+
+    EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
+    EmptyAction.setupAction(showDiff, "ChangesView.Diff", editorComponent);
+    EmptyAction.setupAction(copyRange, IdeActions.ACTION_COPY, editorComponent);
 
     final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true).getComponent();
 
@@ -221,6 +226,8 @@
     HintListener closeListener = new HintListener() {
       public void hintHidden(final EventObject event) {
         actionList.remove(rollback);
+        actionList.remove(showDiff);
+        actionList.remove(copyRange);
         actionList.remove(localShowPrevAction);
         actionList.remove(localShowNextAction);
       }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
index 59697f1..6e08d90 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
@@ -13,6 +13,7 @@
 package com.intellij.openapi.vcs.ex;
 
 import com.intellij.icons.AllIcons;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.application.ApplicationManager;
@@ -32,7 +33,9 @@
 
 public class RollbackLineStatusAction extends DumbAwareAction {
   public RollbackLineStatusAction() {
-    super("Rollback", "Rollback selected changes", AllIcons.Actions.Reset);
+    super(ActionsBundle.actionText("Vcs.RollbackChangedLines"),
+          ActionsBundle.actionDescription("Vcs.RollbackChangedLines"),
+          AllIcons.Actions.Reset);
   }
 
   @Override
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java
new file mode 100644
index 0000000..8a16ba6
--- /dev/null
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+package com.intellij.openapi.vcs.history;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public abstract class BaseDiffFromHistoryHandler<T extends VcsFileRevision> implements DiffFromHistoryHandler {
+
+  private static final Logger LOG = Logger.getInstance(BaseDiffFromHistoryHandler.class);
+
+  @NotNull protected final Project myProject;
+
+  protected BaseDiffFromHistoryHandler(@NotNull Project project) {
+    myProject = project;
+  }
+
+  @Override
+  public void showDiffForOne(@NotNull AnActionEvent e,
+                             @NotNull FilePath filePath,
+                             @NotNull VcsFileRevision previousRevision,
+                             @NotNull VcsFileRevision revision) {
+    doShowDiff(filePath, previousRevision, revision, false);
+  }
+
+  @Override
+  public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
+    doShowDiff(filePath, revision1, revision2, true);
+  }
+
+  @SuppressWarnings("unchecked")
+  protected void doShowDiff(@NotNull FilePath filePath,
+                            @NotNull VcsFileRevision revision1,
+                            @NotNull VcsFileRevision revision2,
+                            boolean autoSort) {
+    if (!filePath.isDirectory()) {
+      VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
+    }
+    else if (revision1.equals(VcsFileRevision.NULL)) {
+      T right = (T)revision2;
+      showAffectedChanges(filePath, right);
+    }
+    else if (revision2 instanceof CurrentRevision) {
+      T left = (T)revision1;
+      showChangesBetweenRevisions(filePath, left, null);
+    }
+    else {
+      T left = (T)revision1;
+      T right = (T)revision2;
+      if (autoSort) {
+        Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
+        left = (T)pair.first;
+        right = (T)pair.second;
+      }
+      showChangesBetweenRevisions(filePath, left, right);
+    }
+  }
+
+  protected void showChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
+    new CollectChangesTask("Comparing revisions...") {
+
+      @NotNull
+      @Override
+      public List<Change> getChanges() throws VcsException {
+        return getChangesBetweenRevisions(path, rev1, rev2);
+      }
+
+      @NotNull
+      @Override
+      public String getDialogTitle() {
+        return getChangesBetweenRevisionsDialogTitle(path, rev1, rev2);
+      }
+    }.queue();
+  }
+
+  protected void showAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) {
+    new CollectChangesTask("Collecting affected changes...") {
+
+      @NotNull
+      @Override
+      public List<Change> getChanges() throws VcsException {
+        return getAffectedChanges(path, rev);
+      }
+
+      @NotNull
+      @Override
+      public String getDialogTitle() {
+        return getAffectedChangesDialogTitle(path, rev);
+      }
+    }.queue();
+  }
+
+  // rev2 == null -> compare rev1 with local
+  // rev2 != null -> compare rev1 with rev2
+  @NotNull
+  protected abstract List<Change> getChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2)
+    throws VcsException;
+
+  @NotNull
+  protected abstract List<Change> getAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) throws VcsException;
+
+  @NotNull
+  protected abstract String getPresentableName(@NotNull T revision);
+
+  protected void showChangesDialog(@NotNull String title, @NotNull List<Change> changes) {
+    DialogBuilder dialogBuilder = new DialogBuilder(myProject);
+
+    dialogBuilder.setTitle(title);
+    dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[]{new DialogBuilder.CloseDialogAction()});
+    final ChangesBrowser changesBrowser =
+      new ChangesBrowser(myProject, null, changes, null, false, true, null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
+    changesBrowser.setChangesToDisplay(changes);
+    dialogBuilder.setCenterPanel(changesBrowser);
+    dialogBuilder.showNotModal();
+  }
+
+  protected void showError(@NotNull VcsException e, @NotNull String logMessage) {
+    LOG.info(logMessage, e);
+    VcsBalloonProblemNotifier.showOverVersionControlView(myProject, e.getMessage(), MessageType.ERROR);
+  }
+
+  @NotNull
+  protected String getChangesBetweenRevisionsDialogTitle(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
+    String rev1Title = getPresentableName(rev1);
+
+    return rev2 != null
+           ? String.format("Difference between %s and %s in %s", rev1Title, getPresentableName(rev2), path.getName())
+           : String.format("Difference between %s and local version in %s", rev1Title, path.getName());
+  }
+
+  @NotNull
+  protected String getAffectedChangesDialogTitle(@NotNull final FilePath path, @NotNull final T rev) {
+    return String.format("Initial commit %s in %s", getPresentableName(rev), path.getName());
+  }
+
+  protected abstract class CollectChangesTask extends Task.Backgroundable {
+
+    private List<Change> myChanges;
+
+    public CollectChangesTask(@NotNull String title) {
+      super(BaseDiffFromHistoryHandler.this.myProject, title);
+    }
+
+    @Override
+    public void run(@NotNull ProgressIndicator indicator) {
+      try {
+        myChanges = getChanges();
+      }
+      catch (VcsException e) {
+        showError(e, "Error during task: " + getDialogTitle());
+      }
+    }
+
+    @NotNull
+    public abstract List<Change> getChanges() throws VcsException;
+
+    @NotNull
+    public abstract String getDialogTitle();
+
+    @Override
+    public void onSuccess() {
+      showChangesDialog(getDialogTitle(), ContainerUtil.notNullize(myChanges));
+    }
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
index a63bbdb..d406347 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
@@ -66,6 +66,11 @@
   }
 
   @Override
+  public boolean isUnderIgnored(@NotNull VirtualFile file) {
+    return false;
+  }
+
+  @Override
   public Module getModuleForFile(@NotNull VirtualFile file) {
     return null;
   }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
index 5cc3a8a..e699383 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
@@ -132,7 +132,7 @@
 
     myBackgroundableActionHandlerMap = new EnumMap<VcsBackgroundableActions, BackgroundableActionEnabledHandler>(VcsBackgroundableActions.class);
     myInitialization = new VcsInitialization(myProject);
-    myMappings = new NewMappings(myProject, myMessageBus, this, manager, excludedFileIndex);
+    myMappings = new NewMappings(myProject, myMessageBus, this, manager);
     myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
 
     if (!myProject.isDefault()) {
@@ -843,12 +843,24 @@
       @Override
       public Boolean compute() {
         return vf != null && (myExcludedIndex.isInContent(vf) || isFileInBaseDir(vf) || vf.equals(myProject.getBaseDir()) ||
-                              hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)) && !myExcludedIndex.isExcludedFile(vf);
+                              hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)
+                              || !Registry.is("ide.hide.excluded.files") && myExcludedIndex.isExcludedFile(vf))
+               && !isIgnored(vf);
       }
     });
   }
 
   @Override
+  public boolean isIgnored(VirtualFile vf) {
+    if (Registry.is("ide.hide.excluded.files")) {
+      return myExcludedIndex.isExcludedFile(vf);
+    }
+    else {
+      return myExcludedIndex.isUnderIgnored(vf);
+    }
+  }
+
+  @Override
   public boolean dvcsUsedInProject() {
     AbstractVcs[] allActiveVcss = getAllActiveVcss();
     for (AbstractVcs activeVcs : allActiveVcss) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
index 1229888..cfddcaa 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
@@ -36,14 +36,17 @@
   // folder path to files to be excluded
   private final Map<String, MyRootFilter> myOtherVcsFolders;
   private final FileIndexFacade myExcludedFileIndex;
+  private final ProjectLevelVcsManager myVcsManager;
+  private final Project myProject;
 
   public VcsRootIterator(final Project project, final AbstractVcs vcs) {
-    final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
+    myProject = project;
+    myVcsManager = ProjectLevelVcsManager.getInstance(project);
     myOtherVcsFolders = new HashMap<String, MyRootFilter>();
     myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
 
-    final VcsRoot[] allRoots = plVcsManager.getAllVcsRoots();
-    final VirtualFile[] roots = plVcsManager.getRootsUnderVcs(vcs);
+    final VcsRoot[] allRoots = myVcsManager.getAllVcsRoots();
+    final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(vcs);
     for (VirtualFile root : roots) {
       final MyRootFilter rootPresentFilter = new MyRootFilter(root, vcs.getName());
       rootPresentFilter.init(allRoots);
@@ -57,14 +60,14 @@
     if ((rootFilter != null) && (!rootFilter.accept(file))) {
       return false;
     }
-    return !isExcluded(myExcludedFileIndex, file);
+    return !isIgnoredByVcs(myVcsManager, myProject, file);
   }
 
-  private static boolean isExcluded(final FileIndexFacade indexFacade, final VirtualFile file) {
+  private static boolean isIgnoredByVcs(final ProjectLevelVcsManager vcsManager, final Project project, final VirtualFile file) {
     return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
       @Override
       public Boolean compute() {
-        return indexFacade.isExcludedFile(file);
+        return !project.isDisposed() && vcsManager.isIgnored(file);
       }
     });
   }
@@ -140,7 +143,7 @@
     @Nullable private final VirtualFileFilter myDirectoryFilter;
     private final VirtualFile myRoot;
     private final MyRootFilter myRootPresentFilter;
-    private final FileIndexFacade myExcludedFileIndex;
+    private final ProjectLevelVcsManager myVcsManager;
 
     private MyRootIterator(final Project project,
                            final VirtualFile root,
@@ -153,13 +156,12 @@
       myDirectoryFilter = directoryFilter;
       myRoot = root;
 
-      final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
-      final AbstractVcs vcs = plVcsManager.getVcsFor(root);
-      myRootPresentFilter = (vcs == null) ? null : new MyRootFilter(root, vcs.getName());
+      myVcsManager = ProjectLevelVcsManager.getInstance(project);
+      final AbstractVcs vcs = myVcsManager.getVcsFor(root);
+      myRootPresentFilter = vcs == null ? null : new MyRootFilter(root, vcs.getName());
       if (myRootPresentFilter != null) {
-        myRootPresentFilter.init(ProjectLevelVcsManager.getInstance(myProject).getAllVcsRoots());
+        myRootPresentFilter.init(myVcsManager.getAllVcsRoots());
       }
-      myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
     }
 
     public void iterate() {
@@ -174,7 +176,7 @@
         @NotNull
         @Override
         public Result visitFileEx(@NotNull VirtualFile file) {
-          if (isExcluded(myExcludedFileIndex, file)) return SKIP_CHILDREN;
+          if (isIgnoredByVcs(myVcsManager, myProject, file)) return SKIP_CHILDREN;
           if (myRootPresentFilter != null && !myRootPresentFilter.accept(file)) return SKIP_CHILDREN;
           if (myProject.isDisposed() || !process(file)) return skipTo(myRoot);
           if (myDirectoryFilter != null && file.isDirectory() && !myDirectoryFilter.shouldGoIntoDirectory(file)) return SKIP_CHILDREN;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
index 32fe920..5ff541e 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
@@ -19,7 +19,6 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.DumbAwareRunnable;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.openapi.util.Pair;
@@ -52,18 +51,18 @@
 
   private final DefaultVcsRootPolicy myDefaultVcsRootPolicy;
   private final MessageBus myMessageBus;
+  private final ProjectLevelVcsManager myVcsManager;
   private final FileStatusManager myFileStatusManager;
-  private final FileIndexFacade myFileIndexFacade;
   private final Project myProject;
 
   private boolean myActivated;
 
-  public NewMappings(final Project project, final MessageBus messageBus,
-                     final ProjectLevelVcsManagerImpl vcsManager, FileStatusManager fileStatusManager, FileIndexFacade fileIndexFacade) {
+  public NewMappings(final Project project, final MessageBus messageBus, final ProjectLevelVcsManagerImpl vcsManager,
+                     FileStatusManager fileStatusManager) {
     myProject = project;
     myMessageBus = messageBus;
+    myVcsManager = vcsManager;
     myFileStatusManager = fileStatusManager;
-    myFileIndexFacade = fileIndexFacade;
     myLock = new Object();
     myVcsToPaths = new HashMap<String, List<VcsDirectoryMapping>>();
     myFileWatchRequestsManager = new FileWatchRequestsManager(myProject, this, LocalFileSystem.getInstance());
@@ -235,7 +234,7 @@
   @Nullable
   public VcsDirectoryMapping getMappingFor(final VirtualFile file, final Object parentModule) {
     // if parentModule is not null it means that file belongs to the module so it isn't excluded
-    if (parentModule == null && myFileIndexFacade.isExcludedFile(file)) {
+    if (parentModule == null && myVcsManager.isIgnored(file)) {
       return null;
     }
 
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
index 2769b3c..bb88f3d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
@@ -16,23 +16,21 @@
 import java.util.Collection;
 import java.util.List;
 
-/**
- * @author Nadya Zabrodina
- */
 public class VcsRootErrorsFinder {
-  private final @NotNull Project myProject;
-  private final @NotNull ProjectLevelVcsManager myVcsManager;
+  @NotNull private final Project myProject;
+  @NotNull private final ProjectLevelVcsManager myVcsManager;
+  @NotNull private final VcsRootDetector myRootDetector;
 
   public VcsRootErrorsFinder(@NotNull Project project) {
     myProject = project;
     myVcsManager = ProjectLevelVcsManager.getInstance(project);
+    myRootDetector = ServiceManager.getService(myProject, VcsRootDetector.class);
   }
 
   @NotNull
   public Collection<VcsRootError> find() {
     List<VcsDirectoryMapping> mappings = myVcsManager.getDirectoryMappings();
-    Collection<VcsRoot> vcsRoots = ServiceManager.getService(myProject, VcsRootDetector.class).detect();
-
+    Collection<VcsRoot> vcsRoots = myRootDetector.detect();
     Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
     errors.addAll(findExtraMappings(mappings));
     errors.addAll(findUnregisteredRoots(mappings, vcsRoots));
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
index 1eebb80..388b9e0 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
@@ -156,9 +156,10 @@
     }
   }
 
-  protected static String run(@NotNull List<String> params, boolean ignoreNonZeroExitCode) throws ExecutionException {
+  protected static String run(@NotNull File workingDir, @NotNull List<String> params,
+                              boolean ignoreNonZeroExitCode) throws ExecutionException {
     final ProcessBuilder builder = new ProcessBuilder().command(params);
-    builder.directory(ourCurrentDir());
+    builder.directory(workingDir);
     builder.redirectErrorStream(true);
     Process clientProcess;
     try {
@@ -279,7 +280,8 @@
     return new File(ourCurrentDir, fileName);
   }
 
-  private static File ourCurrentDir() {
+  @NotNull
+  protected static File ourCurrentDir() {
     assert ourCurrentDir != null : "Current dir hasn't been initialized yet. Call cd at least once before any other command.";
     return new File(ourCurrentDir);
   }
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
new file mode 100644
index 0000000..4ec5ea4
--- /dev/null
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
@@ -0,0 +1,94 @@
+package com.intellij.openapi.vcs.changes;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.CompilerProjectExtension;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class ConvertExcludedToIgnoredTest extends PlatformTestCase {
+  private VirtualFile myContentRoot;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    myContentRoot = getVirtualFile(createTempDirectory());
+    PsiTestUtil.addContentRoot(myModule, myContentRoot);
+  }
+
+  public void testExcludedFolder() throws IOException {
+    VirtualFile excluded = createChildDirectory(myContentRoot, "exc");
+    PsiTestUtil.addExcludedRoot(myModule, excluded);
+    getChangeListManager().convertExcludedToIgnored();
+    assertFalse(getChangeListManager().isIgnoredFile(myContentRoot));
+    assertTrue(getChangeListManager().isIgnoredFile(excluded));
+    assertIgnored(excluded);
+  }
+
+  public void testModuleOutput() throws IOException {
+    VirtualFile output = createChildDirectory(myContentRoot, "out");
+    PsiTestUtil.setCompilerOutputPath(myModule, output.getUrl(), false);
+    getChangeListManager().convertExcludedToIgnored();
+    assertFalse(getChangeListManager().isIgnoredFile(myContentRoot));
+    assertTrue(getChangeListManager().isIgnoredFile(output));
+    assertIgnored(output);
+  }
+
+  public void testProjectOutput() throws IOException {
+    VirtualFile output = getVirtualFile(createTempDir("projectOutput"));
+    CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl());
+    getChangeListManager().convertExcludedToIgnored();
+    assertTrue(getChangeListManager().isIgnoredFile(output));
+    assertIgnored(output);
+  }
+
+  public void testModuleOutputUnderProjectOutput() throws IOException {
+    VirtualFile output = getVirtualFile(createTempDir("projectOutput"));
+    CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl());
+    VirtualFile moduleOutput = createChildDirectory(output, "module");
+    PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false);
+    getChangeListManager().convertExcludedToIgnored();
+    assertTrue(getChangeListManager().isIgnoredFile(output));
+    assertTrue(getChangeListManager().isIgnoredFile(moduleOutput));
+    assertIgnored(output);
+  }
+
+  public void testModuleOutputUnderExcluded() throws IOException {
+    VirtualFile excluded = createChildDirectory(myContentRoot, "target");
+    PsiTestUtil.addExcludedRoot(myModule, excluded);
+    VirtualFile moduleOutput = createChildDirectory(excluded, "classes");
+    PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false);
+    getChangeListManager().convertExcludedToIgnored();
+    assertTrue(getChangeListManager().isIgnoredFile(excluded));
+    assertTrue(getChangeListManager().isIgnoredFile(moduleOutput));
+    assertIgnored(excluded);
+  }
+
+  private void assertIgnored(VirtualFile... ignoredDirs) {
+    assertIgnoredDirectories(getProject(), ignoredDirs);
+  }
+
+  public static void assertIgnoredDirectories(final Project project, VirtualFile... ignoredDirs) {
+    List<String> expectedIgnoredPaths = new ArrayList<String>();
+    for (VirtualFile dir : ignoredDirs) {
+      expectedIgnoredPaths.add(dir.getPath() + "/");
+    }
+    List<String> actualIgnoredPaths = new ArrayList<String>();
+    for (IgnoredFileBean fileBean : ChangeListManagerImpl.getInstanceImpl(project).getFilesToIgnore()) {
+      assertEquals("Unexpected ignore: " + fileBean, IgnoreSettingsType.UNDER_DIR, fileBean.getType());
+      actualIgnoredPaths.add(fileBean.getPath());
+    }
+    assertSameElements(expectedIgnoredPaths, actualIgnoredPaths);
+  }
+
+  private ChangeListManagerImpl getChangeListManager() {
+    return ChangeListManagerImpl.getInstanceImpl(getProject());
+  }
+}
diff --git a/platform/vcs-impl/vcs-impl.iml b/platform/vcs-impl/vcs-impl.iml
index d5e5173..9492e1b 100644
--- a/platform/vcs-impl/vcs-impl.iml
+++ b/platform/vcs-impl/vcs-impl.iml
@@ -18,6 +18,7 @@
     <orderEntry type="module" module-name="lang-impl" />
     <orderEntry type="module" module-name="spellchecker" />
     <orderEntry type="library" name="JUnit4" level="project" />
+    <orderEntry type="module" module-name="testFramework" scope="TEST" />
   </component>
 </module>
 
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java b/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
index c7b7ef9..54f7ba1 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
@@ -20,7 +20,7 @@
 import java.util.List;
 
 /**
- * A {@link GraphCommit} with information about date & time when this commit was made.
+ * A typified {@link GraphCommit}.
  * <p/>
  * An instance of this object can be obtained via
  * {@link VcsLogObjectsFactory#createTimedCommit(Hash, List, long) VcsLogObjectsFactory#createTimedCommit}.
@@ -31,12 +31,4 @@
  */
 public interface TimedVcsCommit extends GraphCommit<Hash> {
 
-  /**
-   * <p>Returns the timestamp indicating the date & time when this commit was made.</p>
-   * <p>This time is displayed in the table by default;
-   *    is used for joining commits from different repositories;
-   *    is used for ordering commits in a single repository (keeping the preference of the topological ordering of course).</p>
-   */
-  long getTimestamp();
-
 }
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
index 5d4f1fb..8980594 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
@@ -29,8 +29,8 @@
    * <p>Reads the whole history, but only hashes & parents.</p>
    * <p>Also reports authors/committers of this repository to the given user registry.</p>
    */
-  @NotNull
-  List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException;
+  void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+                     @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException;
 
   /**
    * Reads those details of the given commits, which are necessary to be shown in the log table.
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
index 3069f3f..9f6cece 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
@@ -21,20 +21,9 @@
  */
 public interface VcsShortCommitDetails extends TimedVcsCommit {
 
-  @Override
-  @NotNull
-  Hash getId();
-
   @NotNull
   VirtualFile getRoot();
 
-  @Override
-  @NotNull
-  List<Hash> getParents();
-
-  @Override
-  long getTimestamp();
-
   @NotNull
   String getSubject();
 
diff --git a/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java b/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
index 6a41485..02b3378 100644
--- a/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
+++ b/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
@@ -29,6 +29,12 @@
   @NotNull
   List<CommitId> getParents();
 
+  /**
+   * <p>Returns the timestamp indicating the date & time when this commit was made.</p>
+   * <p>This time is displayed in the table by default;
+   *    it is used for joining commits from different repositories;
+   *    it is used for ordering commits in a single repository (keeping the preference of the topological ordering of course).</p>
+   */
   long getTimestamp();
 
 }
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
index 6ed592f..fc51742 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
@@ -30,9 +30,7 @@
  * @author Kirill Likhodedov
  */
 public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
-  private final static int BOUND_SAVED_LOG = 10000;
 
-  public final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
   public final static String ILLEGAL_DATA_RELOAD_ALL = "All data is illegal - request reload all";
 
   /**
@@ -100,12 +98,10 @@
       Commit commit = commits.get(lastIndex);
       if (searchHashes.size() == 0)
         return lastIndex;
-      if (lastIndex > BOUND_SAVED_LOG)
-        throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
       searchHashes.remove(commit.getId());
     }
     if (searchHashes.size() != 0)
-      throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+      throw new VcsLogRefreshNotEnoughDataException();
     return lastIndex;
   }
 
@@ -157,16 +153,13 @@
 
     private void markRealRedNode(@NotNull CommitId node) {
       if (!currentRed.remove(node))
-        throw new IllegalStateException(NOT_ENOUGH_FIRST_BLOCK);
+        throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // never happened
       allRedCommit.add(node);
     }
 
     private int getFirstSaveIndex() {
       for (int lastIndex = 0; lastIndex < savedLog.size(); lastIndex++) {
         Commit commit = savedLog.get(lastIndex);
-        if (lastIndex > BOUND_SAVED_LOG)
-          throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
-
         boolean isGreen = currentGreen.contains(commit.getId());
         if (isGreen) {
           currentRed.remove(commit.getId());
@@ -180,7 +173,7 @@
         if (currentRed.isEmpty())
           return lastIndex + 1;
       }
-      throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+      throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // see VcsLogJoinerTest#illegalStateExceptionTest
     }
 
     public Set<CommitId> getAllRedCommit() {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
index 7006408..072e0e2 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
@@ -1,36 +1,36 @@
 package com.intellij.vcs.log.data;
 
 import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.TimedVcsCommit;
+import com.intellij.vcs.log.graph.GraphCommit;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 
-public class VcsLogMultiRepoJoiner {
+public class VcsLogMultiRepoJoiner<CommitId> {
 
   @NotNull
-  public List<? extends TimedVcsCommit> join(@NotNull Collection<List<? extends TimedVcsCommit>> logsFromRepos) {
+  public List<? extends GraphCommit<CommitId>> join(@NotNull Collection<List<? extends GraphCommit<CommitId>>> logsFromRepos) {
     if (logsFromRepos.size() == 1) {
       return logsFromRepos.iterator().next();
     }
 
     int size = 0;
-    for (List<? extends TimedVcsCommit> repo : logsFromRepos) {
+    for (List<? extends GraphCommit<CommitId>> repo : logsFromRepos) {
       size += repo.size();
     }
-    List<TimedVcsCommit> result = new ArrayList<TimedVcsCommit>(size);
+    List<GraphCommit<CommitId>> result = new ArrayList<GraphCommit<CommitId>>(size);
 
-    Map<TimedVcsCommit, Iterator<? extends TimedVcsCommit>> nextCommits = ContainerUtil.newHashMap();
-    for (List<? extends TimedVcsCommit> log : logsFromRepos) {
-      Iterator<? extends TimedVcsCommit> iterator = log.iterator();
+    Map<GraphCommit<CommitId>, Iterator<? extends GraphCommit<CommitId>>> nextCommits = ContainerUtil.newHashMap();
+    for (List<? extends GraphCommit<CommitId>> log : logsFromRepos) {
+      Iterator<? extends GraphCommit<CommitId>> iterator = log.iterator();
       if (iterator.hasNext()) {
         nextCommits.put(iterator.next(), iterator);
       }
     }
 
     while (!nextCommits.isEmpty()) {
-      TimedVcsCommit lastCommit = findLatestCommit(nextCommits.keySet());
-      Iterator<? extends TimedVcsCommit> iterator = nextCommits.get(lastCommit);
+      GraphCommit<CommitId> lastCommit = findLatestCommit(nextCommits.keySet());
+      Iterator<? extends GraphCommit<CommitId>> iterator = nextCommits.get(lastCommit);
       result.add(lastCommit);
       nextCommits.remove(lastCommit);
 
@@ -43,10 +43,10 @@
   }
 
   @NotNull
-  private static TimedVcsCommit findLatestCommit(@NotNull Set<TimedVcsCommit> commits) {
+  private GraphCommit<CommitId> findLatestCommit(@NotNull Set<GraphCommit<CommitId>> commits) {
     long maxTimeStamp = Long.MIN_VALUE;
-    TimedVcsCommit lastCommit = null;
-    for (TimedVcsCommit commit : commits) {
+    GraphCommit<CommitId> lastCommit = null;
+    for (GraphCommit<CommitId> commit : commits) {
       if (commit.getTimestamp() >= maxTimeStamp) {
         maxTimeStamp = commit.getTimestamp();
         lastCommit = commit;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
new file mode 100644
index 0000000..9863be8
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package com.intellij.vcs.log.data;
+
+public class VcsLogRefreshNotEnoughDataException extends RuntimeException {
+
+  private final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
+
+  public VcsLogRefreshNotEnoughDataException() {
+    super(NOT_ENOUGH_FIRST_BLOCK);
+  }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
index 0c25d7f..12996f9 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
@@ -96,11 +96,11 @@
       Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(myProviders);
       Set<VirtualFile> roots = myProviders.keySet();
       Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareSimpleRequirements(roots, myRecentCommitCount);
-      Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
-                                                                                          myUserRegistry, myTopCommitsDetailsCache);
-      List<? extends TimedVcsCommit> compoundLog = compound(commits.values());
-      List<GraphCommit<Integer>> compactedLog = compactCommits(compoundLog, myHashMap);
-      DataPack dataPack = DataPack.build(compactedLog, new RefsModel(refs, myHashMap.asIndexGetter()),
+      Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
+                                                                                                myUserRegistry, myTopCommitsDetailsCache,
+                                                                                                myHashMap);
+      List<? extends GraphCommit<Integer>> compoundLog = compound(commits.values());
+      DataPack dataPack = DataPack.build(compoundLog, new RefsModel(refs, myHashMap.asIndexGetter()),
                                          myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, false);
       mySingleTaskController.request(RefreshRequest.RELOAD_ALL); // build/rebuild the full log in bg
       return dataPack;
@@ -152,19 +152,21 @@
   }
 
   @NotNull
-  private static Map<VirtualFile, List<? extends TimedVcsCommit>> loadRecentCommitsFromVcs(@NotNull Map<VirtualFile, VcsLogProvider> providers,
-                                                                                           @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
-                                                                                           @NotNull final VcsUserRegistryImpl userRegistry,
-                                                                                           @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache)
-    throws VcsException {
+  private static Map<VirtualFile, List<? extends GraphCommit<Integer>>> loadRecentCommitsFromVcs(
+    @NotNull Map<VirtualFile, VcsLogProvider> providers,
+    @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
+    @NotNull final VcsUserRegistryImpl userRegistry,
+    @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache,
+    @NotNull final VcsLogHashMap hashMap) throws VcsException
+  {
     final StopWatch sw = StopWatch.start("loading commits");
-    final Map<VirtualFile, List<? extends TimedVcsCommit>> commits = ContainerUtil.newHashMap();
+    final Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = ContainerUtil.newHashMap();
     new ProviderIterator() {
       @Override
       public void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
         List<? extends VcsCommitMetadata> metadatas = provider.readFirstBlock(root, requirements.get(root));
         storeUsersAndDetails(metadatas, userRegistry, topCommitsDetailsCache);
-        commits.put(root, metadatas);
+        commits.put(root, compactCommits(metadatas, hashMap));
         sw.rootCompleted(root);
       }
     }.iterate(providers);
@@ -177,9 +179,9 @@
    * Compounds logs from different repositories into a single multi-repository log.
    */
   @NotNull
-  private static List<? extends TimedVcsCommit> compound(@NotNull Collection<List<? extends TimedVcsCommit>> commits) {
+  private static List<? extends GraphCommit<Integer>> compound(@NotNull Collection<List<? extends GraphCommit<Integer>>> commits) {
     StopWatch sw = StopWatch.start("multi-repo join");
-    List<? extends TimedVcsCommit> joined = new VcsLogMultiRepoJoiner().join(commits);
+    List<? extends GraphCommit<Integer>> joined = new VcsLogMultiRepoJoiner<Integer>().join(commits);
     sw.report();
     return joined;
   }
@@ -192,8 +194,7 @@
       @NotNull
       @Override
       public GraphCommit<Integer> fun(@NotNull TimedVcsCommit commit) {
-        return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
-                                            ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+        return compactCommit(commit, hashMap);
       }
     });
     hashMap.flush();
@@ -201,6 +202,12 @@
     return map;
   }
 
+  @NotNull
+  private static GraphCommitImpl<Integer> compactCommit(@NotNull TimedVcsCommit commit, @NotNull VcsLogHashMap hashMap) {
+    return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
+                                        ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+  }
+
   private static void storeUsersAndDetails(@NotNull List<? extends VcsCommitMetadata> metadatas, @NotNull VcsUserRegistryImpl userRegistry,
                                            @NotNull Map<Hash, VcsCommitMetadata> topCommitsDetailsCache) {
     for (VcsCommitMetadata detail : metadatas) {
@@ -218,9 +225,9 @@
     private final Map<VirtualFile, LogAndRefs> myLoadedInfos = ContainerUtil.newHashMap();
 
     private class LogAndRefs {
-      List<? extends TimedVcsCommit> log;
+      List<? extends GraphCommit<Integer>> log;
       Collection<VcsRef> refs;
-      LogAndRefs(Collection<VcsRef> refs, List<? extends TimedVcsCommit> commits) {
+      LogAndRefs(Collection<VcsRef> refs, List<? extends GraphCommit<Integer>> commits) {
         this.refs = refs;
         this.log = commits;
       }
@@ -266,16 +273,16 @@
       try {
         if (permanentGraph != null) {
           loadLogAndRefs(roots, currentRefs, myRecentCommitCount);
-          List<? extends TimedVcsCommit> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
-            new Function<LogAndRefs, List<? extends TimedVcsCommit>>() {
+          List<? extends GraphCommit<Integer>> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
+            new Function<LogAndRefs, List<? extends GraphCommit<Integer>>>() {
               @Override
-              public List<? extends TimedVcsCommit> fun(LogAndRefs refs) {
+              public List<? extends GraphCommit<Integer>> fun(
+                LogAndRefs refs) {
                 return refs.log;
               }
             }));
-          List<GraphCommit<Integer>> preparedLog = compactCommits(compoundLog, myHashMap);
           Map<VirtualFile, Collection<VcsRef>> allNewRefs = getAllNewRefs(myLoadedInfos, currentRefs);
-          List<GraphCommit<Integer>> joinedFullLog = join(preparedLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
+          List<GraphCommit<Integer>> joinedFullLog = join(compoundLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
           if (joinedFullLog != null) {
             return DataPack.build(joinedFullLog, new RefsModel(allNewRefs, myHashMap.asIndexGetter()),
                                   myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, true);
@@ -310,8 +317,9 @@
       Map<VirtualFile, VcsLogProvider> providers = getProviders(roots);
       Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(providers);
       Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareRequirements(roots, commitCount, prevRefs, refs);
-      Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(providers, requirements,
-                                                                                          myUserRegistry, myTopCommitsDetailsCache);
+      Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(providers, requirements,
+                                                                                                myUserRegistry, myTopCommitsDetailsCache,
+                                                                                                myHashMap);
       for (VirtualFile root : roots) {
         myLoadedInfos.put(root, new LogAndRefs(refs.get(root), commits.get(root)));
       }
@@ -345,7 +353,7 @@
     }
 
     @Nullable
-    private List<GraphCommit<Integer>> join(@NotNull List<GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
+    private List<GraphCommit<Integer>> join(@NotNull List<? extends GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
                                             @NotNull Map<VirtualFile, Collection<VcsRef>> previousRefs,
                                             @NotNull Map<VirtualFile, Collection<VcsRef>> newRefs) {
       StopWatch sw = StopWatch.start("joining new commits");
@@ -365,18 +373,20 @@
         sw.report();
         return commits;
       }
-      catch (IllegalStateException e) {
-        LOG.info(e);
-        return null;
+      catch (VcsLogRefreshNotEnoughDataException e) {
+        LOG.error(e); // collecting information : how often this situation happens, do we need to try to load more or can safely reload all
       }
+      catch (IllegalStateException e) {
+        LOG.error(e);
+      }
+      return null;
     }
 
     @NotNull
     private Pair<PermanentGraph<Integer>, Map<VirtualFile, Collection<VcsRef>>> loadFullLog() throws VcsException {
       StopWatch sw = StopWatch.start("full log reload");
-      Collection<List<? extends TimedVcsCommit>> commits = readFullLogFromVcs();
-      List<? extends TimedVcsCommit> compoundLog = compound(commits);
-      List<GraphCommit<Integer>> graphCommits = compactCommits(compoundLog, myHashMap);
+      Collection<List<? extends GraphCommit<Integer>>> commits = readFullLogFromVcs();
+      List<? extends GraphCommit<Integer>> graphCommits = compound(commits);
       Map<VirtualFile, Collection<VcsRef>> refMap = loadRefsFromVcs(myProviders);
       PermanentGraph<Integer> permanentGraph = DataPack.buildPermanentGraph(graphCommits, new RefsModel(refMap, myHashMap.asIndexGetter()),
                                                                             myHashMap.asIndexGetter(),
@@ -386,24 +396,31 @@
     }
 
     @NotNull
-    private Collection<List<? extends TimedVcsCommit>> readFullLogFromVcs() throws VcsException {
+    private Collection<List<? extends GraphCommit<Integer>>> readFullLogFromVcs() throws VcsException {
       final StopWatch sw = StopWatch.start("read full log from VCS");
-      final Collection<List<? extends TimedVcsCommit>> commits = ContainerUtil.newArrayList();
+      final Collection<List<? extends GraphCommit<Integer>>> logs = ContainerUtil.newArrayList();
       new ProviderIterator() {
         @Override
         void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
-          commits.add(provider.readAllHashes(root, new Consumer<VcsUser>() {
+          final List<GraphCommit<Integer>> graphCommits = ContainerUtil.newArrayList();
+          provider.readAllHashes(root, new Consumer<VcsUser>() {
             @Override
             public void consume(@NotNull VcsUser user) {
               myUserRegistry.addUser(user);
             }
-          }));
+          }, new Consumer<TimedVcsCommit>() {
+            @Override
+            public void consume(TimedVcsCommit commit) {
+              graphCommits.add(compactCommit(commit, myHashMap));
+            }
+          });
+          logs.add(graphCommits);
           sw.rootCompleted(root);
         }
       }.iterate(myProviders);
       myUserRegistry.flush();
       sw.report();
-      return commits;
+      return logs;
     }
   }
 
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
index ec74038..4f0e44c 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
@@ -58,7 +58,7 @@
     if (isEmptyRefs(refs, headCommit)) {
       return DEFAULT_COLOR;
     }
-    VcsRef firstRef = ContainerUtil.sorted(refs, getRefManager(refs).getComparator()).get(0);
+    VcsRef firstRef = Collections.min(refs, getRefManager(refs).getComparator());
     // TODO dark variant
     return firstRef.getName().hashCode();
   }
@@ -67,7 +67,7 @@
     if (refs.isEmpty()) {
       if (!myErrorWasReported.containsKey(head)) {
         myErrorWasReported.put(head, head);
-        LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
+        LOG.warn("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
       }
       return true;
     }
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
deleted file mode 100644
index 63e54b9..0000000
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.Hash;
-import com.intellij.vcs.log.TimedCommitParser;
-import com.intellij.vcs.log.TimedVcsCommit;
-import com.intellij.vcs.log.impl.HashImpl;
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.List;
-
-import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Kirill Likhodedov
- */
-public class VcsLogJoinerTest {
-
-  public void runTest(List<String> initial, List<String> updateBlock, List<String> oldRefs, List<String> newRefs, String expected) {
-    List<TimedVcsCommit> savedLog = TimedCommitParser.log(ArrayUtil.toStringArray(initial));
-    List<? extends TimedVcsCommit> firstBlock = TimedCommitParser.log(ArrayUtil.toStringArray(updateBlock));
-    Collection<Hash> vcsOldRefs = ContainerUtil.map(oldRefs, new Function<String, Hash>() {
-      @Override
-      public Hash fun(String s) {
-        return HashImpl.build(s);
-      }
-    });
-    Collection<Hash> vcsNewRefs = ContainerUtil.map(newRefs, new Function<String, Hash>() {
-      @Override
-      public Hash fun(String s) {
-        return HashImpl.build(s);
-      }
-    });
-
-    List<? extends TimedVcsCommit> result = new VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(savedLog, vcsOldRefs, firstBlock, vcsNewRefs).getFirst();
-    assertEquals(expected, toStr(result));
-  }
-
-  @Test
-  public void simpleTest() {
-    runTest(
-      asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
-      asList("5|-f|-b1", "6|-e|-a2"),
-      asList("a2", "b1"),
-      asList("f", "e"),
-      "e, f, a2, b1, a1, a"
-    );
-  }
-
-  @Test
-  public void oneNodeTest() {
-    runTest(
-      asList("3|-a1|-"),
-      asList("3|-a1|-"),
-      asList("a1"),
-      asList("a1"),
-      "a1"
-    );
-  }
-
-  @Test
-  public void oneNodeResetTest() {
-    runTest(
-      asList("3|-a1|-a2", "2|-a2|-"),
-      asList("2|-a2|-"),
-      asList("a2", "a1"),
-      asList("a2"),
-      "a2"
-    );
-  }
-
-  @Test
-  public void oneNodeReset2Test() {
-    runTest(
-      asList("3|-a1|-a2", "2|-a2|-"),
-      asList("2|-a2|-"),
-      asList("a1"),
-      asList("a2"),
-      "a2"
-    );
-  }
-
-  @Test
-  public void simpleRemoveCommitsTest() {
-    runTest(
-      asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
-      asList("5|-f|-b1", "6|-e|-a1"),
-      asList("a2"),
-      asList("f", "e"),
-      "e, f, b1, a1, a"
-    );
-  }
-
-  @Test
-  public void removeCommitsTest() {
-    runTest(
-      asList("5|-a5|-a4", "4|-a4|-a2 a3", "3|-a3|-a1", "2|-a2|-a1", "1|-a1|-"),
-      asList("6|-a6|-a3"),
-      asList("a5"),
-      asList("a6"),
-      "a6, a3, a1"
-    );
-  }
-
-  @Test
-  public void removeCommitsTest2() {
-    runTest(
-      asList("2|-a2|-a1", "1|-a1|-"),
-      asList("5|-a5|-a4", "3|-a3|-a2", "4|-a4|-a3"),
-      asList("a2"),
-      asList("a5"),
-      "a5, a4, a3, a2, a1"
-    );
-  }
-
-  @Test
-  public void removeCommitsTest3() {
-    runTest(
-      asList("3|-a3|-a2", "2|-a2|-a1", "1|-a1|-"),
-      asList("2|-a2|-a1"),
-      asList("a3"),
-      asList("a2"),
-      "a2, a1"
-    );
-  }
-
-  private static String toStr(List<? extends TimedVcsCommit> commits) {
-    StringBuilder s = new StringBuilder();
-    for (TimedVcsCommit commit : commits) {
-      if (s.length() != 0) {
-        s.append(", ");
-      }
-      s.append(commit.getId().asString());
-    }
-    return s.toString();
-  }
-}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
new file mode 100644
index 0000000..ed42184
--- /dev/null
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
@@ -0,0 +1,468 @@
+/*
+ * 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.
+ */
+package com.intellij.vcs.log.data
+
+import org.junit.Test
+import java.util.ArrayList
+import com.intellij.vcs.log.TimedCommitParser
+import com.intellij.util.ArrayUtil
+import com.intellij.vcs.log.impl.HashImpl
+import com.intellij.vcs.log.TimedVcsCommit
+import com.intellij.vcs.log.Hash
+import org.junit.Assert.*
+
+
+class VcsLogJoinerTest {
+
+  class StringArrayBuilder() {
+    val result = ArrayList<String>()
+
+    fun String.plus() = result.add(this)
+
+    fun Collection<String>.plus() = result.addAll(this)
+  }
+
+  class TestRunner() {
+    private var fullLog: List<String>? = null
+    private var recentCommits: List<String>? = null
+    private var oldRefs: List<String>? = null
+    private var newRefs: List<String>? = null
+    private var expected: String? = null
+
+    private fun build(f: StringArrayBuilder.() -> Unit): List<String> {
+      val stringArrayBuilder = StringArrayBuilder()
+      stringArrayBuilder.f()
+      return stringArrayBuilder.result
+    }
+
+    fun fullLog(f: StringArrayBuilder.() -> Unit) {fullLog = build(f)}
+
+    fun recentCommits(f: StringArrayBuilder.() -> Unit) {recentCommits = build(f)}
+
+    fun oldRefs(f: StringArrayBuilder.() -> Unit) {oldRefs = build(f)}
+
+    fun newRefs(f: StringArrayBuilder.() -> Unit) {newRefs = build(f)}
+
+    fun expected(f: StringArrayBuilder.() -> Unit) {expected = build(f).join(separator = "\n")}
+
+    fun run() {
+      val vcsFullLog = TimedCommitParser.log(fullLog!!)
+      val vcsRecentCommits = TimedCommitParser.log(recentCommits!!)
+      val vcsOldRefs = oldRefs!!.map { HashImpl.build(it) }
+      val vcsNewRefs = newRefs!!.map { HashImpl.build(it) }
+
+      val result = VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(vcsFullLog, vcsOldRefs, vcsRecentCommits, vcsNewRefs).getFirst()!!
+      val actual = result.map { it.getId().asString() }.join(separator = "\n")
+      assertEquals(expected, actual)
+    }
+  }
+
+  fun runTest(f: TestRunner.() -> Unit) {
+    val testRunner = TestRunner()
+    testRunner.f()
+    testRunner.run()
+  }
+
+  val BIG_TIME = 100000000
+
+  Test fun simple() {
+    runTest {
+      fullLog {
+        +"4|-a2|-a1"
+        +"3|-b1|-a"
+        +"2|-a1|-a"
+        +"1|-a|-"
+      }
+      recentCommits {
+        +"5|-f|-b1"
+        +"6|-e|-a2"
+      }
+      oldRefs {
+        +"a2"
+        +"b1"
+      }
+      newRefs {
+        +"f"
+        +"e"
+      }
+      expected {
+        +"e"
+        +"f"
+        +"a2"
+        +"b1"
+        +"a1"
+        +"a"
+      }
+    }
+  }
+
+  Test fun oneNode() {
+    runTest {
+      fullLog {
+        +"3|-a1|-"
+      }
+      recentCommits {
+        +"3|-a1|-"
+      }
+      oldRefs {
+        +"a1"
+      }
+      newRefs {
+        +"a1"
+      }
+      expected {
+        +"a1"
+      }
+    }
+  }
+
+  Test fun oneNodeReset() {
+    runTest {
+      fullLog {
+        +"3|-a1|-a2"
+        +"2|-a2|-"
+      }
+      recentCommits {
+        +"2|-a2|-"
+      }
+      oldRefs {
+        +"a2"
+        +"a1"
+      }
+      newRefs {
+        +"a2"
+      }
+      expected {
+        +"a2"
+      }
+    }
+  }
+
+  Test fun oneNodeReset2() {
+    runTest {
+      fullLog {
+        +"3|-a1|-a2"
+        +"2|-a2|-"
+      }
+      recentCommits {
+        +"2|-a2|-"
+      }
+      oldRefs {
+        +"a1"
+      }
+      newRefs {
+        +"a2"
+      }
+      expected {
+        +"a2"
+      }
+    }
+  }
+
+  Test fun simpleRemoveCommits() {
+    runTest {
+      fullLog {
+        +"4|-a2|-a1"
+        +"3|-b1|-a"
+        +"2|-a1|-a"
+        +"1|-a|-"
+      }
+      recentCommits {
+        +"5|-f|-b1"
+        +"6|-e|-a1"
+      }
+      oldRefs {
+        +"a2"
+      }
+      newRefs {
+        +"f"
+        +"e"
+      }
+      expected {
+        +"e"
+        +"f"
+        +"b1"
+        +"a1"
+        +"a"
+      }
+    }
+  }
+
+  Test fun removeCommits() {
+    runTest {
+      fullLog {
+        +"5|-a5|-a4"
+        +"4|-a4|-a2 a3"
+        +"3|-a3|-a1"
+        +"2|-a2|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"6|-a6|-a3"
+      }
+      oldRefs {
+        +"a5"
+      }
+      newRefs {
+        +"a6"
+      }
+      expected {
+        +"a6"
+        +"a3"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun removeCommits2() {
+    runTest {
+      fullLog {
+        +"2|-a2|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"5|-a5|-a4"
+        +"3|-a3|-a2"
+        +"4|-a4|-a3"
+      }
+      oldRefs {
+        +"a2"
+      }
+      newRefs {
+        +"a5"
+      }
+      expected {
+        +"a5"
+        +"a4"
+        +"a3"
+        +"a2"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun removeCommits3() {
+    runTest {
+      fullLog {
+        +"3|-a3|-a2"
+        +"2|-a2|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"2|-a2|-a1"
+      }
+      oldRefs {
+        +"a3"
+      }
+      newRefs {
+        +"a2"
+      }
+      expected {
+        +"a2"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun removeOldBranch() {
+    runTest {
+      fullLog {
+        +"100|-e1|-e10"
+        +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+        +"5|-e100001|-a1"
+        +"4|-b2|-b1"
+        +"3|-b1|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"100|-e1|-e10"
+      }
+      oldRefs {
+        +"e1"
+        +"b2"
+      }
+      newRefs {
+        "e1"
+      }
+      expected {
+        +"e1"
+        +(10..100000).map { "e$it" }
+        +"e100001"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun addToOldBranch() {
+    runTest {
+      fullLog {
+        +"100|-e1|-e10"
+        +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+        +"5|-e100001|-a1"
+        +"4|-b2|-b1"
+        +"3|-b1|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"50|-b4|-b3"
+        +"49|-b3|-b2"
+      }
+      oldRefs {
+        +"e1"
+        +"b2"
+      }
+      newRefs {
+        +"e1"
+        +"b4"
+      }
+      expected {
+        +"e1"
+        +(10..100000).map { "e$it" }
+        +"b4"
+        +"b3"
+        +"e100001"
+        +"b2"
+        +"b1"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun removeLongBranch() {
+    runTest {
+      fullLog {
+        +"100|-e1|-e10"
+        +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+        +"5|-e100001|-a1"
+        +"4|-b2|-b1"
+        +"3|-b1|-a1"
+        +"1|-a1|-"
+      }
+      recentCommits {
+        +"50|-b4|-b3"
+        +"49|-b3|-b2"
+      }
+      oldRefs {
+        +"e1"
+        +"b2"
+      }
+      newRefs {
+        +"b4"
+      }
+      expected {
+        +"b4"
+        +"b3"
+        +"b2"
+        +"b1"
+        +"a1"
+      }
+    }
+  }
+
+  Test fun notEnoughDataExceptionTest() {
+    try {
+      runTest {
+        fullLog {
+          +"1|-a1|-"
+        }
+        recentCommits {
+          +"3|-a3|-a2"
+        }
+        oldRefs {
+          +"a1"
+        }
+        newRefs {
+          +"a3"
+        }
+      }
+    } catch (e: VcsLogRefreshNotEnoughDataException) {
+      return
+    }
+    fail()
+  }
+
+  Test fun illegalStateExceptionTest() {
+    try {
+      runTest {
+        fullLog {
+          +"1|-a1|-"
+        }
+        recentCommits {
+          +"1|-a1|-"
+        }
+        oldRefs {
+          +"a1"
+          +"a2"
+        }
+        newRefs {
+          +"a1"
+        }
+      }
+    } catch (e: IllegalStateException) {
+      return
+    }
+    fail()
+  }
+
+  Test fun removeParallelBranch() {
+    runTest {
+      fullLog {
+        +"4|-a4|-a1"
+        +"3|-a3|-a2"
+        +"2|-a2|-"
+        +"1|-a1|-"
+      }
+      recentCommits {
+
+      }
+      oldRefs {
+        +"a4"
+        +"a3"
+      }
+      newRefs {
+        +"a3"
+      }
+      expected {
+        +"a3"
+        +"a2"
+      }
+    }
+  }
+
+  Test fun removeAll() {
+    runTest {
+      fullLog {
+        +"4|-a4|-a1"
+        +"3|-a3|-a2"
+        +"2|-a2|-"
+        +"1|-a1|-"
+      }
+      recentCommits {
+
+      }
+      oldRefs {
+        +"a4"
+        +"a3"
+      }
+      newRefs {
+
+      }
+      expected {
+
+      }
+    }
+  }
+}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
index d3709b2..850478b 100644
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
@@ -93,9 +93,9 @@
     return ContainerUtil.map(myCommits.subList(0, requirements.getCommitCount()), myCommitToMetadataConvertor);
   }
 
-  @NotNull
   @Override
-  public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
+  public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+                            @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
     try {
       myFullLogSemaphore.acquire();
     }
@@ -103,7 +103,9 @@
       throw new RuntimeException(e);
     }
     assertRoot(root);
-    return myCommits;
+    for (TimedVcsCommit commit : myCommits) {
+      commitConsumer.consume(commit);
+    }
   }
 
   private void assertRoot(@NotNull VirtualFile root) {
diff --git a/platform/vcs-log/impl/vcs-log-impl.iml b/platform/vcs-log/impl/vcs-log-impl.iml
index 5668888..304affc 100644
--- a/platform/vcs-log/impl/vcs-log-impl.iml
+++ b/platform/vcs-log/impl/vcs-log-impl.iml
@@ -21,6 +21,7 @@
     <orderEntry type="module" module-name="spellchecker" />
     <orderEntry type="module" module-name="vcs-log-graph-api" />
     <orderEntry type="module" module-name="testFramework" scope="TEST" />
+    <orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
   </component>
 </module>
 
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
index 098501a..6109e9a 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
@@ -164,8 +164,10 @@
     return text;
   }
 
+  @Deprecated
   /**
    * @return delay before showing value tooltip (in ms)
+   * @deprecated Since IDEA 14 it is a platform setting
    */
   public int getValuePopupDelay() {
     return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay();
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java
new file mode 100644
index 0000000..6cc25bd
--- /dev/null
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package com.intellij.xdebugger.settings;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.options.Configurable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public abstract class DebuggerConfigurableProvider {
+  public static final ExtensionPointName<DebuggerConfigurableProvider> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.configurableProvider");
+
+  @NotNull
+  public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+    return Collections.emptyList();
+  }
+
+  /**
+   * General settings of category were applied
+   */
+  public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+  }
+
+  public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java
new file mode 100644
index 0000000..fab630f
--- /dev/null
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java
@@ -0,0 +1,6 @@
+package com.intellij.xdebugger.settings;
+
+public enum DebuggerSettingsCategory {
+  ROOT /* will be placed under root "Debugger" node, use it with care */,
+  GENERAL, DATA_VIEWS, STEPPING, HOTSWAP
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
index 52049f7..367601d 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
@@ -23,6 +23,9 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * Implement this class to provide settings page for debugger. Settings page will be placed under 'Debugger' node in the 'Settings' dialog.
  * An implementation should be registered in plugin.xml:
@@ -34,10 +37,6 @@
  * @author nik
  */
 public abstract class XDebuggerSettings<T> implements PersistentStateComponent<T> {
-  public enum Category {
-    ROOT, DATA_VIEWS, STEPPING
-  }
-
   public static final ExtensionPointName<XDebuggerSettings> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.settings");
 
   private final String myId;
@@ -55,15 +54,23 @@
   }
 
   @Nullable
+  @Deprecated
+  /**
+   * @deprecated Please use {@link #createConfigurables(DebuggerSettingsCategory)}
+   */
   public Configurable createConfigurable() {
     return null;
   }
 
-  @Nullable
-  public Configurable createConfigurable(@NotNull Category category) {
-    return null;
+  @NotNull
+  public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+    return Collections.emptyList();
   }
 
-  public void generalApplied(@NotNull Category category) {
+  public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+  }
+
+  public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+    return false;
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
index 840163b..b09c738 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
@@ -36,6 +36,7 @@
 public abstract class DebuggerSupport {
   private static final ExtensionPointName<DebuggerSupport> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.debuggerSupport");
 
+  @SuppressWarnings("deprecation")
   private static final DebuggerSettingsPanelProvider EMPTY_SETTINGS_PANEL_PROVIDER = new DebuggerSettingsPanelProvider() {
   };
 
@@ -60,6 +61,11 @@
   @NotNull
   public abstract BreakpointPanelProvider<?> getBreakpointPanelProvider();
 
+  /**
+   * @deprecated Use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider}
+   */
+  @Deprecated
+  @SuppressWarnings("deprecation")
   @NotNull
   public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
     return EMPTY_SETTINGS_PANEL_PROVIDER;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
index 9ab13ba..7628555 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
@@ -46,7 +46,6 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.ui.AppUIUtil;
@@ -91,7 +90,7 @@
   private XDebugProcess myDebugProcess;
   private final Map<XBreakpoint<?>, CustomizedBreakpointPresentation> myRegisteredBreakpoints =
     new THashMap<XBreakpoint<?>, CustomizedBreakpointPresentation>();
-  private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = new SmartHashSet<XBreakpoint<?>>();
+  private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = Collections.synchronizedSet(new SmartHashSet<XBreakpoint<?>>());
   private boolean myBreakpointsDisabled;
   private final XDebuggerManagerImpl myDebuggerManager;
   private MyBreakpointListener myBreakpointListener;
@@ -103,7 +102,7 @@
   private MyDependentBreakpointListener myDependentBreakpointListener;
   private XValueMarkers<?, ?> myValueMarkers;
   private final String mySessionName;
-  private XDebugSessionTab mySessionTab;
+  private @Nullable XDebugSessionTab mySessionTab;
   private XDebugSessionData mySessionData;
   private XBreakpoint<?> myActiveNonLineBreakpoint;
   private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
@@ -289,6 +288,7 @@
 
   @Override
   public void initBreakpoints() {
+    ApplicationManager.getApplication().assertReadAccessAllowed();
     LOG.assertTrue(!breakpointsInitialized);
     breakpointsInitialized = true;
 
@@ -308,12 +308,14 @@
     return myConsoleView;
   }
 
+  @Nullable
   public XDebugSessionTab getSessionTab() {
     return mySessionTab;
   }
 
   @Override
   public RunnerLayoutUi getUI() {
+    assertSessionTabInitialized();
     return mySessionTab.getUi();
   }
 
@@ -368,12 +370,7 @@
   private <B extends XBreakpoint<?>> void processBreakpoints(final XBreakpointHandler<B> handler,
                                                              boolean register,
                                                              final boolean temporary) {
-    Collection<? extends B> breakpoints = ApplicationManager.getApplication().runReadAction(new Computable<Collection<? extends B>>() {
-      @Override
-      public Collection<? extends B> compute() {
-        return myDebuggerManager.getBreakpointManager().getBreakpoints(handler.getBreakpointTypeClass());
-      }
-    });
+    Collection<? extends B> breakpoints = myDebuggerManager.getBreakpointManager().getBreakpoints(handler.getBreakpointTypeClass());
     for (B b : breakpoints) {
       handleBreakpoint(handler, b, register, temporary);
     }
@@ -422,8 +419,9 @@
     }
   }
 
-  private boolean isBreakpointActive(final XBreakpoint<?> b) {
-    return !areBreakpointsMuted() && b.isEnabled() && !myInactiveSlaveBreakpoints.contains(b);
+  public boolean isBreakpointActive(final XBreakpoint<?> b) {
+    ApplicationManager.getApplication().assertReadAccessAllowed();
+    return !areBreakpointsMuted() && b.isEnabled() && !isInactiveSlaveBreakpoint(b);
   }
 
   @Override
@@ -448,6 +446,7 @@
 
   @Override
   public void setBreakpointMuted(boolean muted) {
+    ApplicationManager.getApplication().assertReadAccessAllowed();
     if (areBreakpointsMuted() == muted) return;
     mySessionData.setBreakpointsMuted(muted);
     processAllBreakpoints(!muted, muted);
@@ -714,8 +713,10 @@
     UIUtil.invokeLaterIfNeeded(new Runnable() {
       @Override
       public void run() {
-        mySessionTab.toFront();
-        mySessionTab.getUi().attractBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION);
+        if (mySessionTab != null) {
+          mySessionTab.toFront(true);
+          mySessionTab.getUi().attractBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION);
+        }
       }
     });
 
@@ -847,7 +848,9 @@
     if (myStopped) return;
 
     myDebugProcess.stop();
-    myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess);
+    if (!myProject.isDisposed()) {
+      myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess);
+    }
     myCurrentPosition = null;
     myCurrentExecutionStack = null;
     myCurrentStackFrame = null;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
index fbfe184..7f8eda2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -26,8 +26,6 @@
 import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
 import com.intellij.xdebugger.impl.evaluate.quick.XQuickEvaluateHandler;
 import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
-import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
-import com.intellij.xdebugger.impl.settings.XDebuggerSettingsPanelProviderImpl;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -49,7 +47,6 @@
   private final XDebuggerSuspendedActionHandler myShowExecutionPointHandler;
   private final XDebuggerEvaluateActionHandler myEvaluateHandler;
   private final XQuickEvaluateHandler myQuickEvaluateHandler;
-  private final XDebuggerSettingsPanelProviderImpl mySettingsPanelProvider;
 
   private final XAddToWatchesFromEditorActionHandler myAddToWatchesActionHandler;
   private final DebuggerActionHandler myEvaluateInConsoleActionHandler = new XEvaluateInConsoleFromEditorActionHandler();
@@ -118,7 +115,6 @@
     myMuteBreakpointsHandler = new XDebuggerMuteBreakpointsHandler();
     myEvaluateHandler = new XDebuggerEvaluateActionHandler();
     myQuickEvaluateHandler = new XQuickEvaluateHandler();
-    mySettingsPanelProvider = new XDebuggerSettingsPanelProviderImpl();
     myMarkObjectActionHandler = new XMarkObjectActionHandler();
     myEditBreakpointActionHandler = new XDebuggerEditBreakpointActionHandler();
   }
@@ -253,10 +249,4 @@
   public EditBreakpointActionHandler getEditBreakpointAction() {
     return myEditBreakpointActionHandler;
   }
-
-  @Override
-  @NotNull
-  public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
-    return mySettingsPanelProvider;
-  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
index e7c9cae..e5620e2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
@@ -15,13 +15,14 @@
  */
 package com.intellij.xdebugger.impl.actions;
 
-import org.jetbrains.annotations.NotNull;
 import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
 public class ForceStepIntoAction extends XDebuggerActionBase {
+  @Override
   @NotNull
   protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
     return debuggerSupport.getForceStepIntoHandler();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
index 364353c..8631b8f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
@@ -156,11 +156,11 @@
   }
 
   public boolean isLogExpressionEnabled() {
-    return myLogExpression != null && !myLogExpression.myDisabled;
+    return myLogExpression == null || !myLogExpression.myDisabled;
   }
 
   public boolean isConditionEnabled() {
-    return myCondition != null && !myCondition.myDisabled;
+    return myCondition == null || !myCondition.myDisabled;
   }
 
   @Property(surroundWithTag = false)
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
index ddf673f..4ee505a 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
@@ -62,9 +62,9 @@
   private final XBreakpointManagerImpl myBreakpointManager;
   private Icon myIcon;
   private CustomizedBreakpointPresentation myCustomizedPresentation;
-  private boolean myConditionEnabled;
+  private boolean myConditionEnabled = true;
   private XExpression myCondition;
-  private boolean myLogExpressionEnabled;
+  private boolean myLogExpressionEnabled = true;
   private XExpression myLogExpression;
 
   public XBreakpointBase(final XBreakpointType<Self, P> type, XBreakpointManagerImpl breakpointManager, final @Nullable P properties, final S state) {
@@ -192,7 +192,6 @@
 
   @Override
   public void setLogExpression(@Nullable final String expression) {
-    setLogExpressionEnabled(true);
     if (!Comparing.equal(getLogExpression(), expression)) {
       myLogExpression = XExpressionImpl.fromText(expression);
       fireBreakpointChanged();
@@ -211,7 +210,6 @@
 
   @Override
   public void setLogExpressionObject(@Nullable XExpression expression) {
-    setLogExpressionEnabled(true);
     if (!Comparing.equal(myLogExpression, expression)) {
       myLogExpression = expression;
       fireBreakpointChanged();
@@ -226,7 +224,6 @@
 
   @Override
   public void setCondition(@Nullable final String condition) {
-    setConditionEnabled(true);
     if (!Comparing.equal(condition, getCondition())) {
       myCondition = XExpressionImpl.fromText(condition);
       fireBreakpointChanged();
@@ -245,7 +242,6 @@
 
   @Override
   public void setConditionExpression(@Nullable XExpression condition) {
-    setConditionEnabled(true);
     if (!Comparing.equal(condition, myCondition)) {
       myCondition = condition;
       fireBreakpointChanged();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
index 6ee8ead..36584d1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
@@ -116,7 +116,7 @@
     if (myLogExpressionComboBox != null) {
       XExpression expression = myLogExpressionComboBox.getExpression();
       XExpression logExpression = !XDebuggerUtilImpl.isEmptyExpression(expression) ? expression : null;
-      myBreakpoint.setLogExpressionEnabled(myLogExpressionCheckBox.isSelected() && logExpression != null);
+      myBreakpoint.setLogExpressionEnabled(logExpression == null || myLogExpressionCheckBox.isSelected());
       myBreakpoint.setLogExpressionObject(logExpression);
       myLogExpressionComboBox.saveTextInHistory();
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
index 64239d3..4ce06a6 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
@@ -83,7 +83,7 @@
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
-          <font size="11" style="1"/>
+          <font style="1"/>
           <text value="Enabled"/>
         </properties>
       </component>
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
index 0e847d7..75cbb56 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
@@ -208,7 +208,7 @@
     if (myConditionComboBox != null) {
       XExpression expression = myConditionComboBox.getExpression();
       XExpression condition = !XDebuggerUtilImpl.isEmptyExpression(expression) ? expression : null;
-      myBreakpoint.setConditionEnabled(myConditionEnabledCheckbox.isSelected() && condition != null);
+      myBreakpoint.setConditionEnabled(condition == null || myConditionEnabledCheckbox.isSelected());
       myBreakpoint.setConditionExpression(condition);
       myConditionComboBox.saveTextInHistory();
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
index b0b5998..994e51f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
@@ -62,6 +62,6 @@
   @Nullable
   @Override
   public Icon getIcon() {
-    return AllIcons.FileTypes.Text;
+    return AllIcons.Actions.GroupByFile;
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
index 2273ab6..bee9b3d 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
@@ -33,6 +33,7 @@
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
 import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
+import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
 import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
@@ -138,7 +139,11 @@
           // add to watches
           XExpression expression = myInputComponent.getInputEditor().getExpression();
           if (!XDebuggerUtilImpl.isEmptyExpression(expression)) {
-            ((XDebugSessionImpl)mySession).getSessionTab().getWatchesView().addWatchExpression(expression, -1, false);
+            XDebugSessionTab tab = ((XDebugSessionImpl)mySession).getSessionTab();
+            if (tab != null) {
+              tab.getWatchesView().addWatchExpression(expression, -1, true);
+              requestFocusInEditor();
+            }
           }
         }
       }
@@ -195,7 +200,11 @@
 
     setTitle(myInputComponent.getTitle());
     mySwitchModeAction.putValue(Action.NAME, getSwitchButtonText(mode));
-    final JComponent preferredFocusedComponent = myInputComponent.getInputEditor().getPreferredFocusedComponent();
+    requestFocusInEditor();
+  }
+
+  private void requestFocusInEditor() {
+    JComponent preferredFocusedComponent = myInputComponent.getInputEditor().getPreferredFocusedComponent();
     if (preferredFocusedComponent != null) {
       IdeFocusManager.getInstance(mySession.getProject()).requestFocus(preferredFocusedComponent, true);
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
index bf3e001..0ccd488 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
@@ -100,14 +100,7 @@
   }
 
   @Override
-  public int getValueLookupDelay(final Project project) {
-    XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
-    if (session != null) {
-      XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
-      if (evaluator != null) {
-        return evaluator.getValuePopupDelay();
-      }
-    }
+  public int getValueLookupDelay(Project project) {
     return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay();
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
index cdfcad2..ca78932 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
@@ -104,6 +104,7 @@
       public void evaluated(@NotNull final XValue result) {
         result.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() {
           private XFullValueEvaluator myFullValueEvaluator;
+          private boolean myShown = false;
 
           @Override
           public void applyPresentation(@Nullable Icon icon,
@@ -131,7 +132,7 @@
               }
               showHint(component);
             }
-            else if (getType() == ValueHintType.MOUSE_CLICK_HINT) {
+            else if (getType() == ValueHintType.MOUSE_CLICK_HINT && !myShown) {
               showTree(result);
             }
             else {
@@ -143,6 +144,7 @@
               });
               showHint(component);
             }
+            myShown = true;
           }
 
           @Override
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
index 5183877..6216c13 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
@@ -15,6 +15,8 @@
  */
 package com.intellij.xdebugger.impl.frame;
 
+import com.intellij.debugger.ui.DebuggerContentInfo;
+import com.intellij.execution.ui.layout.impl.RunnerContentUi;
 import com.intellij.ide.DataManager;
 import com.intellij.ide.dnd.DnDEvent;
 import com.intellij.ide.dnd.DnDManager;
@@ -22,6 +24,7 @@
 import com.intellij.openapi.CompositeDisposable;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.EmptyRunnable;
 import com.intellij.openapi.util.SystemInfo;
@@ -36,6 +39,7 @@
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
+import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
@@ -68,6 +72,7 @@
   @NotNull private final XDebugSessionImpl mySession;
   private final JPanel myDecoratedPanel;
   private final CompositeDisposable myDisposables = new CompositeDisposable();
+  private boolean myRebuildNeeded;
 
   public XWatchesViewImpl(@NotNull final XDebugSessionImpl session) {
     mySession = session;
@@ -216,10 +221,40 @@
   public void addWatchExpression(@NotNull XExpression expression, int index, final boolean navigateToWatchNode) {
     myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode);
     updateSessionData();
+    if (navigateToWatchNode) {
+      showWatchesTab();
+    }
+  }
+
+  private void showWatchesTab() {
+    XDebugSessionTab tab = mySession.getSessionTab();
+    if (tab != null) {
+      tab.toFront(false);
+      // restore watches tab if minimized
+      JComponent component = tab.getUi().getComponent();
+      if (component instanceof DataProvider) {
+        RunnerContentUi ui = RunnerContentUi.KEY.getData(((DataProvider)component));
+        if (ui != null) {
+          ui.restoreContent(DebuggerContentInfo.WATCHES_CONTENT);
+        }
+      }
+    }
+  }
+
+  public boolean rebuildNeeded() {
+    return myRebuildNeeded;
   }
 
   @Override
   public void processSessionEvent(@NotNull final SessionEvent event) {
+    if (getMainPanel().isShowing() || ApplicationManager.getApplication().isUnitTestMode()) {
+      myRebuildNeeded = false;
+    }
+    else {
+      myRebuildNeeded = true;
+      return;
+    }
+
     XStackFrame stackFrame = mySession.getCurrentStackFrame();
     XDebuggerTree tree = myTreePanel.getTree();
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
index d140a74..6ee307c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
@@ -17,7 +17,7 @@
 
 import com.intellij.openapi.options.Configurable;
 import com.intellij.xdebugger.XDebuggerBundle;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
 
@@ -41,8 +41,8 @@
 
   @NotNull
   @Override
-  protected XDebuggerSettings.Category getCategory() {
-    return XDebuggerSettings.Category.DATA_VIEWS;
+  protected DebuggerSettingsCategory getCategory() {
+    return DebuggerSettingsCategory.DATA_VIEWS;
   }
 
   @NotNull
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
index a3f4e84..58896a8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
@@ -20,26 +20,23 @@
 import com.intellij.openapi.options.SearchableConfigurable;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.xdebugger.XDebuggerBundle;
 import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.Nls;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
 
-/**
- * @author Eugene Belyaev & Eugene Zhuravlev
- */
 public class DebuggerConfigurable implements SearchableConfigurable.Parent {
   public static final String DISPLAY_NAME = XDebuggerBundle.message("debugger.configurable.display.name");
 
   static final Configurable[] EMPTY_CONFIGURABLES = new Configurable[0];
+  private static final DebuggerSettingsCategory[] MERGED_CATEGORIES = {DebuggerSettingsCategory.STEPPING, DebuggerSettingsCategory.HOTSWAP};
 
   private Configurable myRootConfigurable;
   private Configurable[] myChildren;
@@ -71,89 +68,84 @@
       return;
     }
 
-    List<DebuggerSettingsPanelProvider> providers = DebuggerConfigurableProvider.getSortedProviders();
-
     List<Configurable> configurables = new SmartList<Configurable>();
     configurables.add(new DataViewsConfigurable());
 
-    List<Configurable> steppingConfigurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.STEPPING, providers);
-    if (!steppingConfigurables.isEmpty()) {
-      configurables.add(new SteppingConfigurable(steppingConfigurables));
-    }
+    DebuggerConfigurableProvider[] providers = DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions();
+    computeMergedConfigurables(providers, configurables);
 
-    Configurable rootConfigurable = computeRootConfigurable(providers, configurables);
-
-    if (configurables.isEmpty() && rootConfigurable == null) {
-      myChildren = EMPTY_CONFIGURABLES;
-    }
-    else if (rootConfigurable == null && configurables.size() == 1) {
-      myRootConfigurable = configurables.get(0);
-      myChildren = EMPTY_CONFIGURABLES;
-    }
-    else {
-      myChildren = configurables.toArray(new Configurable[configurables.size()]);
-      myRootConfigurable = rootConfigurable;
-    }
-  }
-
-  @Nullable
-  private static Configurable computeRootConfigurable(@NotNull List<DebuggerSettingsPanelProvider> providers, @NotNull List<Configurable> configurables) {
-    Configurable deprecatedRootConfigurable = null;
-    for (DebuggerSettingsPanelProvider provider : providers) {
+    //noinspection deprecation
+    for (DebuggerSettingsPanelProvider provider : getSortedProviders()) {
       configurables.addAll(provider.getConfigurables());
       @SuppressWarnings("deprecation")
       Configurable providerRootConfigurable = provider.getRootConfigurable();
       if (providerRootConfigurable != null) {
-        if (deprecatedRootConfigurable == null) {
-          deprecatedRootConfigurable = providerRootConfigurable;
-        }
-        else {
-          configurables.add(providerRootConfigurable);
-        }
+        configurables.add(providerRootConfigurable);
       }
     }
 
-    List<Configurable> rootConfigurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.ROOT, providers);
-    if (rootConfigurables.isEmpty()) {
-      return deprecatedRootConfigurable;
+    for (DebuggerConfigurableProvider provider : providers) {
+      configurables.addAll(provider.getConfigurables(DebuggerSettingsCategory.ROOT));
+    }
+
+    MergedCompositeConfigurable mergedGeneralConfigurable = computeGeneralConfigurables(providers);
+    if (configurables.isEmpty() && mergedGeneralConfigurable == null) {
+      myRootConfigurable = null;
+      myChildren = EMPTY_CONFIGURABLES;
+    }
+    else if (configurables.size() == 1) {
+      Configurable firstConfigurable = configurables.get(0);
+      if (mergedGeneralConfigurable == null) {
+        myRootConfigurable = firstConfigurable;
+        myChildren = EMPTY_CONFIGURABLES;
+      }
+      else {
+        Configurable[] generalConfigurables = mergedGeneralConfigurable.children;
+        Configurable[] mergedArray = new Configurable[generalConfigurables.length + 1];
+        System.arraycopy(generalConfigurables, 0, mergedArray, 0, generalConfigurables.length);
+        mergedArray[generalConfigurables.length] = firstConfigurable;
+        myRootConfigurable = new MergedCompositeConfigurable("", "", mergedArray);
+        myChildren = firstConfigurable instanceof SearchableConfigurable.Parent ? ((Parent)firstConfigurable).getConfigurables() : EMPTY_CONFIGURABLES;
+      }
     }
     else {
-      Configurable[] mergedRootConfigurables = new Configurable[rootConfigurables.size() + (deprecatedRootConfigurable == null ? 0 : 1)];
-      rootConfigurables.toArray(mergedRootConfigurables);
-      if (deprecatedRootConfigurable != null) {
-        mergedRootConfigurables[rootConfigurables.size()] = deprecatedRootConfigurable;
-      }
-
-      // move unnamed to top
-      Arrays.sort(mergedRootConfigurables, new Comparator<Configurable>() {
-        @Override
-        public int compare(Configurable o1, Configurable o2) {
-          boolean c1e = StringUtil.isEmpty(o1.getDisplayName());
-          return c1e == StringUtil.isEmpty(o2.getDisplayName()) ? 0 : (c1e ? -1 : 1);
-        }
-      });
-
-      return new MergedCompositeConfigurable(mergedRootConfigurables) {
-        @NotNull
-        @Override
-        public String getId() {
-          throw new UnsupportedOperationException();
-        }
-
-        @Nls
-        @Override
-        public String getDisplayName() {
-          throw new UnsupportedOperationException();
-        }
-      };
+      myChildren = configurables.toArray(new Configurable[configurables.size()]);
+      myRootConfigurable = mergedGeneralConfigurable;
     }
   }
 
+  private static void computeMergedConfigurables(@NotNull DebuggerConfigurableProvider[] providers, @NotNull List<Configurable> result) {
+    for (DebuggerSettingsCategory category : MERGED_CATEGORIES) {
+      List<Configurable> configurables = getConfigurables(category, providers);
+      if (!configurables.isEmpty()) {
+        String id = category.name().toLowerCase(Locale.ENGLISH);
+        result.add(new MergedCompositeConfigurable("debugger." + id, XDebuggerBundle.message("debugger." + id + ".display.name"),
+                                                   configurables.toArray(new Configurable[configurables.size()])));
+      }
+    }
+  }
+
+  @Nullable
+  private static MergedCompositeConfigurable computeGeneralConfigurables(@NotNull DebuggerConfigurableProvider[] providers) {
+    List<Configurable> rootConfigurables = getConfigurables(DebuggerSettingsCategory.GENERAL, providers);
+    if (rootConfigurables.isEmpty()) {
+      return null;
+    }
+
+    Configurable[] mergedRootConfigurables = rootConfigurables.toArray(new Configurable[rootConfigurables.size()]);
+    // move unnamed to top
+    Arrays.sort(mergedRootConfigurables, new Comparator<Configurable>() {
+      @Override
+      public int compare(@NotNull Configurable o1, @NotNull Configurable o2) {
+        boolean c1e = StringUtil.isEmpty(o1.getDisplayName());
+        return c1e == StringUtil.isEmpty(o2.getDisplayName()) ? 0 : (c1e ? -1 : 1);
+      }
+    });
+    return new MergedCompositeConfigurable("", "", mergedRootConfigurables);
+  }
+
   @Override
   public void apply() throws ConfigurationException {
-    for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
-      support.getSettingsPanelProvider().apply();
-    }
     if (myRootConfigurable != null) {
       myRootConfigurable.apply();
     }
@@ -206,4 +198,51 @@
   public String getId() {
     return "project.propDebugger";
   }
+
+  @SuppressWarnings("deprecation")
+  @NotNull
+  private static List<DebuggerSettingsPanelProvider> getSortedProviders() {
+    List<DebuggerSettingsPanelProvider> providers = null;
+    for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
+      DebuggerSettingsPanelProvider provider = support.getSettingsPanelProvider();
+      if (providers == null) {
+        providers = new SmartList<DebuggerSettingsPanelProvider>();
+      }
+      providers.add(provider);
+    }
+
+    if (ContainerUtil.isEmpty(providers)) {
+      return Collections.emptyList();
+    }
+
+    if (providers.size() > 1) {
+      Collections.sort(providers, new Comparator<DebuggerSettingsPanelProvider>() {
+        @Override
+        public int compare(@NotNull DebuggerSettingsPanelProvider o1, @NotNull DebuggerSettingsPanelProvider o2) {
+          return o2.getPriority() - o1.getPriority();
+        }
+      });
+    }
+    return providers;
+  }
+
+  @NotNull
+  static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+    return getConfigurables(category, DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions());
+  }
+
+  @NotNull
+  private static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category, @NotNull DebuggerConfigurableProvider[] providers) {
+    List<Configurable> configurables = null;
+    for (DebuggerConfigurableProvider provider : providers) {
+      Collection<? extends Configurable> providerConfigurables = provider.getConfigurables(category);
+      if (!providerConfigurables.isEmpty()) {
+        if (configurables == null) {
+          configurables = new SmartList<Configurable>();
+        }
+        configurables.addAll(providerConfigurables);
+      }
+    }
+    return ContainerUtil.notNullize(configurables);
+  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
deleted file mode 100644
index 80651ca..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2000-2010 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.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurableProvider;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class DebuggerConfigurableProvider extends ConfigurableProvider {
-  @NotNull
-  static List<DebuggerSettingsPanelProvider> getSortedProviders() {
-    List<DebuggerSettingsPanelProvider> providers = null;
-    for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
-      DebuggerSettingsPanelProvider provider = support.getSettingsPanelProvider();
-      if (providers == null) {
-        providers = new SmartList<DebuggerSettingsPanelProvider>();
-      }
-      providers.add(provider);
-    }
-
-    if (ContainerUtil.isEmpty(providers)) {
-      return Collections.emptyList();
-    }
-
-    if (providers.size() > 1) {
-      Collections.sort(providers, new Comparator<DebuggerSettingsPanelProvider>() {
-        @Override
-        public int compare(DebuggerSettingsPanelProvider o1, DebuggerSettingsPanelProvider o2) {
-          return o2.getPriority() - o1.getPriority();
-        }
-      });
-    }
-    return providers;
-  }
-
-  @Override
-  public Configurable createConfigurable() {
-    return new DebuggerConfigurable();
-  }
-
-  @NotNull
-  static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category) {
-    List<DebuggerSettingsPanelProvider> providers = getSortedProviders();
-    return providers.isEmpty() ? Collections.<Configurable>emptyList() : getConfigurables(category, providers);
-  }
-
-  @NotNull
-  static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category, @NotNull List<DebuggerSettingsPanelProvider> providers) {
-    List<Configurable> configurables = null;
-    for (DebuggerSettingsPanelProvider provider : providers) {
-      Collection<? extends Configurable> providerConfigurables = provider.getConfigurable(category);
-      if (!providerConfigurables.isEmpty()) {
-        if (configurables == null) {
-          configurables = new SmartList<Configurable>();
-        }
-        configurables.addAll(providerConfigurables);
-      }
-    }
-    return ContainerUtil.notNullize(configurables);
-  }
-}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
index 68e6de0..5b0dde6 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
@@ -16,15 +16,15 @@
 package com.intellij.xdebugger.impl.settings;
 
 import com.intellij.openapi.options.Configurable;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.Collections;
 
+@Deprecated
 /**
- * @author nik
+ * @deprecated Use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider}
  */
 public abstract class DebuggerSettingsPanelProvider {
   public int getPriority() {
@@ -36,23 +36,20 @@
     return Collections.emptyList();
   }
 
+  @Deprecated
+  /**
+   * @deprecated Please use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider#generalApplied(com.intellij.xdebugger.settings.DebuggerSettingsCategory)}
+   */
   public void apply() {
   }
 
   @Nullable
   @Deprecated
+  /**
+   * @deprecated Please use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider#getConfigurables(com.intellij.xdebugger.settings.DebuggerSettingsCategory)} and
+   * check {@link com.intellij.xdebugger.settings.DebuggerSettingsCategory#GENERAL}
+   */
   public Configurable getRootConfigurable() {
     return null;
   }
-
-  @NotNull
-  public Collection<? extends Configurable> getConfigurable(@NotNull XDebuggerSettings.Category category) {
-    return Collections.emptyList();
-  }
-
-  /**
-   * General settings of category were applied
-   */
-  public void generalApplied(@NotNull XDebuggerSettings.Category category) {
-  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java
deleted file mode 100644
index 466279b..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.ConfigurableBase;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-class GeneralConfigurable extends ConfigurableBase<GeneralConfigurableUi, XDebuggerGeneralSettings> {
-  @Override
-  protected XDebuggerGeneralSettings getSettings() {
-    return XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings();
-  }
-
-  @Override
-  protected GeneralConfigurableUi createUi() {
-    return new GeneralConfigurableUi();
-  }
-
-  @NotNull
-  @Override
-  public String getId() {
-    return "debugger.general";
-  }
-
-  @Nls
-  @Override
-  public String getDisplayName() {
-    return "";
-  }
-
-  @Nullable
-  @Override
-  public String getHelpTopic() {
-    return null;
-  }
-}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
index be0bdbf..ccfc270 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
@@ -7,6 +7,8 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.ui.TitledSeparator;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -14,18 +16,34 @@
 import javax.swing.border.EmptyBorder;
 import java.awt.*;
 
-abstract class MergedCompositeConfigurable implements SearchableConfigurable {
+class MergedCompositeConfigurable implements SearchableConfigurable {
   static final EmptyBorder BOTTOM_INSETS = new EmptyBorder(0, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
 
+  private static final Insets FIRST_COMPONENT_INSETS = new Insets(0, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
+  private static final Insets N_COMPONENT_INSETS = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
+
   protected final Configurable[] children;
   protected JComponent rootComponent;
 
-  protected MergedCompositeConfigurable(@NotNull Configurable[] children) {
+  private final String id;
+  private final String displayName;
+
+  public MergedCompositeConfigurable(@NotNull String id, @NotNull String displayName, @NotNull Configurable[] children) {
     this.children = children;
+    this.id = id;
+    this.displayName = displayName;
   }
 
-  protected boolean isUseTitledBorder() {
-    return true;
+  @NotNull
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  @Nls
+  @Override
+  public String getDisplayName() {
+    return displayName;
   }
 
   @Nullable
@@ -40,26 +58,47 @@
     return children.length == 1 ? children[0].getHelpTopic() : null;
   }
 
+  /**
+   * false by default.
+   *
+   * If Ruby general settings will be without titled border in RubyMine, user could think that all other debugger categories also about Ruby.
+   */
+  protected boolean isUseTargetedProductPolicyIfSeveralChildren() {
+    return false;
+  }
+
   @Nullable
   @Override
   public JComponent createComponent() {
     if (rootComponent == null) {
+      Configurable firstConfigurable = children[0];
       if (children.length == 1) {
-        rootComponent = children[0].createComponent();
+        rootComponent = firstConfigurable.createComponent();
+        String rootComponentDisplayName = firstConfigurable.getDisplayName();
+        if (!StringUtil.isEmpty(rootComponentDisplayName) && !isTargetedToProduct(firstConfigurable)) {
+          rootComponent.setBorder(IdeBorderFactory.createTitledBorder(rootComponentDisplayName, false, FIRST_COMPONENT_INSETS));
+        }
       }
       else {
-        JPanel panel = createPanel(isUseTitledBorder());
-        for (Configurable child : children) {
-          JComponent component = child.createComponent();
+        boolean isFirstNamed = true;
+        JPanel panel = createPanel(true);
+        for (Configurable configurable : children) {
+          JComponent component = configurable.createComponent();
           assert component != null;
-          if (isUseTitledBorder()) {
-            String displayName = child.getDisplayName();
-            if (StringUtil.isEmpty(displayName)) {
-              component.setBorder(BOTTOM_INSETS);
+          String displayName = configurable.getDisplayName();
+          if (StringUtil.isEmpty(displayName)) {
+            component.setBorder(BOTTOM_INSETS);
+          }
+          else {
+            boolean addBorder = true;
+            if (isUseTargetedProductPolicyIfSeveralChildren() && isFirstNamed) {
+              isFirstNamed = false;
+              if (isTargetedToProduct(configurable)) {
+                addBorder = false;
+              }
             }
-            else {
-              Insets insets = new Insets(children[0] == child ? 0 : IdeBorderFactory.TITLED_BORDER_TOP_INSET, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
-              component.setBorder(IdeBorderFactory.createTitledBorder(displayName, false, insets));
+            if (addBorder) {
+              component.setBorder(IdeBorderFactory.createTitledBorder(displayName, false, firstConfigurable == configurable ? FIRST_COMPONENT_INSETS : N_COMPONENT_INSETS));
             }
           }
           panel.add(component);
@@ -70,6 +109,15 @@
     return rootComponent;
   }
 
+  static boolean isTargetedToProduct(@NotNull Configurable configurable) {
+    for (DebuggerConfigurableProvider provider : DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions()) {
+      if (provider.isTargetedToProduct(configurable)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   @NotNull
   static JPanel createPanel(boolean isUseTitledBorder) {
     int verticalGap = TitledSeparator.TOP_INSET;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java
deleted file mode 100644
index 5f16424..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.xdebugger.XDebuggerBundle;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-class SteppingConfigurable extends MergedCompositeConfigurable {
-  public SteppingConfigurable(@NotNull List<Configurable> configurables) {
-    super(configurables.toArray(new Configurable[configurables.size()]));
-  }
-
-  @NotNull
-  @Override
-  public String getId() {
-    return "debugger.stepping";
-  }
-
-  @Nls
-  @Override
-  public String getDisplayName() {
-    return XDebuggerBundle.message("debugger.stepping.display.name");
-  }
-}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
index 489e4bd..f06b6bc 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
@@ -20,8 +20,8 @@
 import com.intellij.openapi.options.SearchableConfigurable;
 import com.intellij.openapi.ui.VerticalFlowLayout;
 import com.intellij.ui.IdeBorderFactory;
-import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -77,7 +77,7 @@
   protected abstract DataViewsConfigurableUi createRootUi();
 
   @NotNull
-  protected abstract XDebuggerSettings.Category getCategory();
+  protected abstract DebuggerSettingsCategory getCategory();
 
   private boolean isChildrenMerged() {
     return children != null && children.length == 1;
@@ -86,7 +86,7 @@
   @Override
   public final Configurable[] getConfigurables() {
     if (children == null) {
-      List<Configurable> configurables = DebuggerConfigurableProvider.getConfigurables(getCategory());
+      List<Configurable> configurables = DebuggerConfigurable.getConfigurables(getCategory());
       children = configurables.toArray(new Configurable[configurables.size()]);
     }
     return isChildrenMerged() ? DebuggerConfigurable.EMPTY_CONFIGURABLES : children;
@@ -115,10 +115,12 @@
             c.setBorder(MergedCompositeConfigurable.BOTTOM_INSETS);
             panel.add(c);
           }
-          for (Configurable child : children) {
-            JComponent component = child.createComponent();
+          for (Configurable configurable : children) {
+            JComponent component = configurable.createComponent();
             if (component != null) {
-              component.setBorder(IdeBorderFactory.createTitledBorder(child.getDisplayName(), false));
+              if (children[0] != configurable || !MergedCompositeConfigurable.isTargetedToProduct(configurable)) {
+                component.setBorder(IdeBorderFactory.createTitledBorder(configurable.getDisplayName(), false));
+              }
               panel.add(component);
             }
           }
@@ -164,8 +166,8 @@
   public final void apply() throws ConfigurationException {
     if (root != null) {
       root.apply(getSettings());
-      for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
-        support.getSettingsPanelProvider().generalApplied(getCategory());
+      for (DebuggerConfigurableProvider provider : DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions()) {
+        provider.generalApplied(getCategory());
       }
     }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java
new file mode 100644
index 0000000..2a7f636
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java
@@ -0,0 +1,74 @@
+package com.intellij.xdebugger.impl.settings;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
+import com.intellij.xdebugger.settings.XDebuggerSettings;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.List;
+
+class XDebuggerConfigurableProvider extends DebuggerConfigurableProvider {
+  @NotNull
+  @Override
+  public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+    List<Configurable> list;
+    if (category == DebuggerSettingsCategory.GENERAL) {
+      list = new SmartList<Configurable>(SimpleConfigurable.create("debugger.general", "", GeneralConfigurableUi.class, new Getter<XDebuggerGeneralSettings>() {
+        @Override
+        public XDebuggerGeneralSettings get() {
+          return XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings();
+        }
+      }));
+    }
+    else {
+      list = null;
+    }
+
+    for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+      Collection<? extends Configurable> configurables = settings.createConfigurables(category);
+      if (!configurables.isEmpty()) {
+        if (list == null) {
+          list = new SmartList<Configurable>();
+        }
+        list.addAll(configurables);
+      }
+    }
+
+    if (category == DebuggerSettingsCategory.ROOT) {
+      for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+        @SuppressWarnings("deprecation")
+        Configurable configurable = settings.createConfigurable();
+        if (configurable != null) {
+          if (list == null) {
+            list = new SmartList<Configurable>();
+          }
+          list.add(configurable);
+        }
+      }
+    }
+    return ContainerUtil.notNullize(list);
+  }
+
+  @Override
+  public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+    for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+      settings.generalApplied(category);
+    }
+  }
+
+  @Override
+  public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+    for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+      if (settings.isTargetedToProduct(configurable)) {
+        return true;
+      }
+    }
+    return super.isTargetedToProduct(configurable);
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java
deleted file mode 100644
index 2e20230..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-package com.intellij.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class XDebuggerSettingsPanelProviderImpl extends DebuggerSettingsPanelProvider {
-  @NotNull
-  @Override
-  public Collection<? extends Configurable> getConfigurables() {
-    List<Configurable> list = new SmartList<Configurable>();
-    for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
-      ContainerUtil.addIfNotNull(list, settings.createConfigurable());
-    }
-    return list;
-  }
-
-  @NotNull
-  @Override
-  public Collection<? extends Configurable> getConfigurable(@NotNull XDebuggerSettings.Category category) {
-    List<Configurable> list;
-    if (category == XDebuggerSettings.Category.ROOT) {
-      list = new SmartList<Configurable>(new GeneralConfigurable());
-    }
-    else {
-      list = null;
-    }
-
-    for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
-      Configurable configurable = settings.createConfigurable(category);
-      if (configurable != null) {
-        if (list == null) {
-          list = new SmartList<Configurable>();
-        }
-        list.add(configurable);
-      }
-    }
-    return ContainerUtil.notNullize(list);
-  }
-
-  @Override
-  public void generalApplied(@NotNull XDebuggerSettings.Category category) {
-    for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
-      settings.generalApplied(category);
-    }
-  }
-}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
index 57b2e9d..2134c0c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
@@ -151,19 +151,21 @@
     return environment != null ? environment.getRunProfile() : null;
   }
 
-  public void toFront() {
+  public void toFront(boolean focus) {
     if (!ApplicationManager.getApplication().isUnitTestMode()) {
       ExecutionManager.getInstance(getProject()).getContentManager().toFrontRunContent(DefaultDebugExecutor.getDebugExecutorInstance(), myRunContentDescriptor);
-      ApplicationManager.getApplication().invokeLater(new Runnable() {
-        @Override
-        public void run() {
-          boolean focusWnd = Registry.is("debugger.mayBringFrameToFrontOnBreakpoint");
-          ProjectUtil.focusProjectWindow(getProject(), focusWnd);
-          if (!focusWnd) {
-            AppIcon.getInstance().requestAttention(getProject(), true);
+      if (focus) {
+        ApplicationManager.getApplication().invokeLater(new Runnable() {
+          @Override
+          public void run() {
+            boolean focusWnd = Registry.is("debugger.mayBringFrameToFrontOnBreakpoint");
+            ProjectUtil.focusProjectWindow(getProject(), focusWnd);
+            if (!focusWnd) {
+              AppIcon.getInstance().requestAttention(getProject(), true);
+            }
           }
-        }
-      });
+        });
+      }
     }
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
index 2e5f8a3..4b6bea2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
@@ -27,6 +27,7 @@
 import com.intellij.execution.ui.RunContentDescriptor;
 import com.intellij.execution.ui.actions.CloseAction;
 import com.intellij.execution.ui.layout.PlaceInGrid;
+import com.intellij.execution.ui.layout.impl.ViewImpl;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.actions.ContextHelpAction;
 import com.intellij.idea.ActionsBundle;
@@ -37,6 +38,8 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.ui.AppUIUtil;
 import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentManagerAdapter;
+import com.intellij.ui.content.ContentManagerEvent;
 import com.intellij.ui.content.tabs.PinToolwindowTabAction;
 import com.intellij.xdebugger.XDebugProcess;
 import com.intellij.xdebugger.XDebugSession;
@@ -242,6 +245,18 @@
     focus.add(ActionManager.getInstance().getAction(XDebuggerActions.FOCUS_ON_BREAKPOINT));
     myUi.getOptions().setAdditionalFocusActions(focus);
 
+    myUi.addListener(new ContentManagerAdapter() {
+      @Override
+      public void selectionChanged(ContentManagerEvent event) {
+        Content content = event.getContent();
+        if (content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(content.getUserData(ViewImpl.ID))) {
+          if (myWatchesView.rebuildNeeded()) {
+            myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED);
+          }
+        }
+      }
+    }, this);
+
     rebuildViews();
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
index d097b09..fe32920 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
@@ -35,10 +35,7 @@
 import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.frame.XValueMarkers;
-import com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.RestorableStateNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XValueContainerNode;
+import com.intellij.xdebugger.impl.ui.tree.nodes.*;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -254,6 +251,12 @@
     if (XDEBUGGER_TREE_KEY.is(dataId)) {
       return this;
     }
+    if (PlatformDataKeys.PREDEFINED_TEXT.is(dataId)) {
+      XValueNodeImpl[] selectedNodes = getSelectedNodes(XValueNodeImpl.class, null);
+      if (selectedNodes.length == 1 && selectedNodes[0].getFullValueEvaluator() == null) {
+        return selectedNodes[0].getRawValue();
+      }
+    }
     return null;
   }
 
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
index a4b7431..942e734 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
@@ -15,7 +15,6 @@
  */
 package com.intellij.xdebugger;
 
-import com.intellij.openapi.options.Configurable;
 import com.intellij.testFramework.PlatformLiteFixture;
 import com.intellij.util.xmlb.XmlSerializer;
 import com.intellij.util.xmlb.annotations.Attribute;
@@ -23,7 +22,6 @@
 import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
 import com.intellij.xdebugger.settings.XDebuggerSettings;
 import org.jdom.Element;
-import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
@@ -79,11 +77,5 @@
     public void loadState(final MyDebuggerSettings state) {
       myOption = state.myOption;
     }
-
-    @Override
-    @NotNull
-    public Configurable createConfigurable() {
-      throw new UnsupportedOperationException("'createConfigurable' not implemented in " + getClass().getName());
-    }
   }
 }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index 164c690..5581810 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -1209,6 +1209,10 @@
                      key="field.has.setter.but.no.getter.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.javabeans.issues" enabledByDefault="false" level="WARNING"
                      implementationClass="com.siyeh.ig.javabeans.FieldHasSetterButNoGetterInspection"/>
+    <localInspection language="JAVA" shortName="PropertyValueSetToItself" bundle="com.siyeh.InspectionGadgetsBundle"
+                     key="property.value.set.to.itself.display.name" groupBundle="messages.InspectionsBundle"
+                     groupKey="group.names.javabeans.issues" enabledByDefault="false" level="WARNING"
+                     implementationClass="com.siyeh.ig.javabeans.PropertyValueSetToItselfInspection"/>
 
     <!--group.names.javadoc.issues-->
     <localInspection language="JAVA" shortName="HtmlTagCanBeJavadocTag" bundle="com.siyeh.InspectionGadgetsBundle"
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index f92925b..715bf89 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1841,8 +1841,9 @@
 double.literal.may.be.float.literal.quickfix=Replace with ''{0}''
 multiple.declaration.option=Ignore 'for' loop declarations
 simplifiable.annotation.display.name=Simplifiable annotation
-simplifiable.annotation.problem.descriptor=Annotation <code>#ref</code> can be simplified #loc
-simplifiable.annotation.quickfix=Replace with ''{0}''
+simplifiable.annotation.problem.descriptor=Unnecessary <code>#ref</code> in annotation #loc
+simplifiable.annotation.whitespace.problem.descriptor=Unnecessary whitespace in annotation #loc
+simplifiable.annotation.quickfix=Simplify annotation
 overloaded.methods.with.same.number.parameters.option=<html>Ignore overloaded methods whose parameter types are definitely incompatible</html>
 string.concatenation.in.format.call.display.name=String concatenation as argument to 'format()' call
 string.concatenation.in.format.call.problem.descriptor=<code>#ref()</code> call has a String concatenation argument #loc
@@ -2098,3 +2099,4 @@
 assignment.to.lambda.parameter.problem.descriptor=Assignment to lambda parameter <code>#ref</code> #loc
 class.with.only.private.constructors.display.name=Class with only 'private' constructors should be declared 'final'
 class.with.only.private.constructors.problem.descriptor=Class <code>#ref</code> with only 'private' constructors should be declared 'final'
+property.value.set.to.itself.display.name=Property value set to itself
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
index 1ba34a6..d792a1a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -191,8 +191,13 @@
     holder.registerProblem(location, description, highlightType, fixes);
   }
 
-  protected final void registerErrorAtOffset(@NotNull PsiElement location,
-                                             int offset, int length, Object... infos) {
+  protected final void registerErrorAtOffset(@NotNull PsiElement location, int offset, int length, Object... infos) {
+    registerErrorAtOffset(location, offset, length, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, infos);
+  }
+
+  protected final void registerErrorAtOffset(@NotNull PsiElement location, int offset, int length,
+                                             ProblemHighlightType highlightType,
+                                             Object... infos) {
     if (location.getTextLength() == 0 || length == 0) {
       return;
     }
@@ -202,7 +207,7 @@
     }
     final String description = inspection.buildErrorString(infos);
     final TextRange range = new TextRange(offset, offset + length);
-    holder.registerProblem(location, range, description, fixes);
+    holder.registerProblem(location, description, highlightType, range, fixes);
   }
 
   @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
index 8db2598..7f5012f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
@@ -284,8 +284,10 @@
       weaklingList.remove(objectClass);
       if (weaklingList.isEmpty()) {
         final String typeText = type.getCanonicalText();
-        final String interfaceText =
-          CollectionUtils.getInterfaceForClass(typeText);
+        final String interfaceText = CollectionUtils.getInterfaceForClass(typeText);
+        if (interfaceText == null) {
+          return;
+        }
         registerError(nameElement, interfaceText);
       }
       else {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
index 41b3911..17f7a83 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
@@ -72,8 +72,7 @@
     return new MismatchedArrayReadWriteVisitor();
   }
 
-  private static class MismatchedArrayReadWriteVisitor
-    extends BaseInspectionVisitor {
+  private static class MismatchedArrayReadWriteVisitor extends BaseInspectionVisitor {
 
     @Override
     public void visitField(@NotNull PsiField field) {
@@ -88,8 +87,7 @@
       if (!checkVariable(field, containingClass)) {
         return;
       }
-      final boolean written =
-        arrayContentsAreWritten(field, containingClass);
+      final boolean written = arrayContentsAreWritten(field, containingClass);
       final boolean read = arrayContentsAreRead(field, containingClass);
       if (written == read) {
         return;
@@ -98,16 +96,13 @@
     }
 
     @Override
-    public void visitLocalVariable(
-      @NotNull PsiLocalVariable variable) {
+    public void visitLocalVariable(@NotNull PsiLocalVariable variable) {
       super.visitLocalVariable(variable);
-      final PsiCodeBlock codeBlock =
-        PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+      final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
       if (!checkVariable(variable, codeBlock)) {
         return;
       }
-      final boolean written =
-        arrayContentsAreWritten(variable, codeBlock);
+      final boolean written = arrayContentsAreWritten(variable, codeBlock);
       final boolean read = arrayContentsAreRead(variable, codeBlock);
       if (written == read) {
         return;
@@ -133,8 +128,7 @@
       if (VariableAccessUtils.variableIsReturned(variable, context)) {
         return false;
       }
-      return !VariableAccessUtils.variableIsUsedInArrayInitializer(
-        variable, context);
+      return !VariableAccessUtils.variableIsUsedInArrayInitializer(variable, context);
     }
 
     private static boolean arrayContentsAreWritten(PsiVariable variable,
@@ -187,26 +181,20 @@
         return true;
       }
       if (initializer instanceof PsiNewExpression) {
-        final PsiNewExpression newExpression =
-          (PsiNewExpression)initializer;
-        final PsiArrayInitializerExpression arrayInitializer =
-          newExpression.getArrayInitializer();
-        return arrayInitializer == null ||
-               isDefaultArrayInitializer(arrayInitializer);
+        final PsiNewExpression newExpression = (PsiNewExpression)initializer;
+        final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer();
+        return arrayInitializer == null || isDefaultArrayInitializer(arrayInitializer);
       }
       else if (initializer instanceof PsiArrayInitializerExpression) {
-        final PsiArrayInitializerExpression arrayInitializerExpression =
-          (PsiArrayInitializerExpression)initializer;
-        final PsiExpression[] initializers =
-          arrayInitializerExpression.getInitializers();
+        final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression)initializer;
+        final PsiExpression[] initializers = arrayInitializerExpression.getInitializers();
         return initializers.length == 0;
       }
       return false;
     }
 
     public static boolean variableIsWritten(@NotNull PsiVariable variable, @NotNull PsiElement context) {
-      final VariableReadWriteVisitor visitor =
-        new VariableReadWriteVisitor(variable, true);
+      final VariableReadWriteVisitor visitor = new VariableReadWriteVisitor(variable, true);
       context.accept(visitor);
       return visitor.isPassed();
     }
@@ -272,8 +260,7 @@
         final PsiExpression[] arguments = argumentList.getExpressions();
         for (int i = 0; i < arguments.length; i++) {
           final PsiExpression argument = arguments[i];
-          if (VariableAccessUtils.mayEvaluateToVariable(argument,
-                                                        variable)) {
+          if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
             if (write && i == 0 && isCallToSystemArraycopy(call)) {
               return;
             }
@@ -285,49 +272,50 @@
         }
       }
 
-      private static boolean isCallToSystemArraycopy(
-        PsiMethodCallExpression call) {
-        final PsiReferenceExpression methodExpression =
-          call.getMethodExpression();
-        @NonNls final String name =
-          methodExpression.getReferenceName();
+      private static boolean isCallToSystemArraycopy(PsiMethodCallExpression call) {
+        final PsiReferenceExpression methodExpression = call.getMethodExpression();
+        @NonNls final String name = methodExpression.getReferenceName();
         if (!"arraycopy".equals(name)) {
           return false;
         }
-        final PsiExpression qualifier =
-          methodExpression.getQualifierExpression();
+        final PsiExpression qualifier = methodExpression.getQualifierExpression();
         if (!(qualifier instanceof PsiReferenceExpression)) {
           return false;
         }
-        final PsiReferenceExpression referenceExpression =
-          (PsiReferenceExpression)qualifier;
-        final PsiElement element =
-          referenceExpression.resolve();
+        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
+        final PsiElement element = referenceExpression.resolve();
         if (!(element instanceof PsiClass)) {
           return false;
         }
-        final PsiClass aClass = (PsiClass)element;
-        final String qualifiedName =
-          aClass.getQualifiedName();
-        return "java.lang.System".equals(qualifiedName);
+        return "java.lang.System".equals(((PsiClass)element).getQualifiedName());
       }
 
       @Override
-      public void visitNewExpression(
-        @NotNull PsiNewExpression newExpression) {
+      public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
         if (passed) {
           return;
         }
         super.visitNewExpression(newExpression);
-        final PsiExpressionList argumentList =
-          newExpression.getArgumentList();
+        visitPsiCall(newExpression);
+      }
+
+      @Override
+      public void visitEnumConstant(PsiEnumConstant enumConstant) {
+        if (passed) {
+          return;
+        }
+        super.visitEnumConstant(enumConstant);
+        visitPsiCall(enumConstant);
+      }
+
+      private void visitPsiCall(PsiCall newExpression) {
+        final PsiExpressionList argumentList = newExpression.getArgumentList();
         if (argumentList == null) {
           return;
         }
         final PsiExpression[] arguments = argumentList.getExpressions();
         for (final PsiExpression argument : arguments) {
-          if (VariableAccessUtils.mayEvaluateToVariable(argument,
-                                                        variable)) {
+          if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
             passed = true;
           }
         }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java
new file mode 100644
index 0000000..e4ee7c5
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package com.siyeh.ig.javabeans;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.PropertyUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class PropertyValueSetToItselfInspection extends BaseInspection {
+
+  @Nls
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name");
+  }
+
+  @NotNull
+  @Override
+  protected String buildErrorString(Object... infos) {
+    return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name");
+  }
+
+  @Override
+  public BaseInspectionVisitor buildVisitor() {
+    return new PropertyValueSetToItselfVisitor();
+  }
+
+  private static class PropertyValueSetToItselfVisitor extends BaseInspectionVisitor {
+
+    @Override
+    public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+      super.visitMethodCallExpression(expression);
+      final PsiExpressionList argumentList1 = expression.getArgumentList();
+      final PsiExpression[] arguments1 = argumentList1.getExpressions();
+      if (arguments1.length != 1) {
+        return;
+      }
+      final PsiExpression argument = arguments1[0];
+      if (!(argument instanceof PsiMethodCallExpression)) {
+        return;
+      }
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)argument;
+      final PsiExpressionList argumentList2 = methodCallExpression.getArgumentList();
+      final PsiExpression[] arguments2 = argumentList2.getExpressions();
+      if (arguments2.length != 0) {
+        return;
+      }
+      final PsiReferenceExpression methodExpression1 = expression.getMethodExpression();
+      final PsiExpression qualifierExpression1 = ParenthesesUtils.stripParentheses(methodExpression1.getQualifierExpression());
+      final PsiReferenceExpression methodExpression2 = methodCallExpression.getMethodExpression();
+      final PsiExpression qualifierExpression2 = ParenthesesUtils.stripParentheses(methodExpression2.getQualifierExpression());
+      if (qualifierExpression1 instanceof PsiReferenceExpression && qualifierExpression2 instanceof PsiReferenceExpression) {
+        if (!EquivalenceChecker.expressionsAreEquivalent(qualifierExpression1, qualifierExpression2)) {
+          return;
+        }
+      }
+      else if((qualifierExpression1 != null &&
+              !(qualifierExpression1 instanceof PsiThisExpression) &&
+              !(qualifierExpression1 instanceof PsiSuperExpression))
+              ||
+              qualifierExpression2 != null &&
+              !(qualifierExpression2 instanceof PsiThisExpression) &&
+              !(qualifierExpression2 instanceof PsiSuperExpression)) {
+        return;
+      }
+      final PsiMethod method1 = expression.resolveMethod();
+      final PsiField fieldOfSetter = PropertyUtil.getFieldOfSetter(method1);
+      if (fieldOfSetter == null) {
+        return;
+      }
+      final PsiMethod method2 = methodCallExpression.resolveMethod();
+      final PsiField fieldOfGetter = PropertyUtil.getFieldOfGetter(method2);
+      if (!fieldOfSetter.equals(fieldOfGetter)) {
+        return;
+      }
+      registerMethodCallError(expression);
+    }
+  }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
index 5b4c0c9..adfff48 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
@@ -515,7 +515,10 @@
     super.readSettings(node);
     for (Element child : node.getChildren("option")) {
       if (Comparing.strEqual(child.getAttributeValue("name"), ONLY_SAFE)) {
-        onlySuggestNullSafe = Boolean.parseBoolean(child.getAttributeValue("value"));
+        final String value = child.getAttributeValue("value");
+        if (value != null) {
+          onlySuggestNullSafe = Boolean.parseBoolean(value);
+        }
         break;
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
index 375e0f6..9b4a3a8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
@@ -416,7 +416,7 @@
     final List<PsiImportStaticStatement> imports = getMatchingImports(importList, qualifiedName);
     final int onDemandCount = JavaCodeStyleSettingsFacade.getInstance(project).getNamesCountToUseImportOnDemand();
     final PsiElementFactory elementFactory = psiFacade.getElementFactory();
-    if (imports.size() < onDemandCount) {
+    if (imports.size() + 1 < onDemandCount) {
       importList.add(elementFactory.createImportStaticStatement(aClass, memberName));
     }
     else {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
index 702d84d..fdbc531 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
@@ -117,6 +117,9 @@
             inElse = true;
           }
           checkExpression(operand);
+          if (agreeingInstanceof) {
+            return;
+          }
         }
         if (inElse && conflictingInstanceof != null) {
           agreeingInstanceof = false;
@@ -215,6 +218,7 @@
         (PsiInstanceOfExpression)expression;
       if (isAgreeing(instanceOfExpression)) {
         agreeingInstanceof = true;
+        conflictingInstanceof = null;
       }
       else if (isConflicting(instanceOfExpression)) {
         conflictingInstanceof = instanceOfExpression;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
index 1440c58..aade5a5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
@@ -132,7 +132,7 @@
       else if (referenceParent instanceof PsiVariable) {
         final PsiVariable variable = (PsiVariable)referenceParent;
         final PsiType type = variable.getType();
-        if (!checkType(type, weakestTypeClasses)) {
+        if (!type.isAssignableFrom(variableOrMethodType) || !checkType(type, weakestTypeClasses)) {
           return Collections.emptyList();
         }
       }
@@ -251,7 +251,7 @@
     if (!hasUsages) {
       return Collections.emptyList();
     }
-    weakestTypeClasses = filterAccessibleClasses(weakestTypeClasses, variableOrMethod);
+    weakestTypeClasses = filterAccessibleClasses(weakestTypeClasses, variableOrMethodClass, variableOrMethod);
     return weakestTypeClasses;
   }
 
@@ -442,22 +442,23 @@
     }
     final PsiExpression lhs = assignmentExpression.getLExpression();
     final PsiExpression rhs = assignmentExpression.getRExpression();
+    if (rhs == null) {
+      return false;
+    }
     final PsiType lhsType = lhs.getType();
+    final PsiType rhsType = rhs.getType();
+    if (lhsType == null || rhsType == null || !lhsType.isAssignableFrom(rhsType)) {
+      return false;
+    }
     if (referenceElement.equals(rhs)) {
       if (!checkType(lhsType, weakestTypeClasses)) {
         return false;
       }
     }
-    else if (useRighthandTypeAsWeakestTypeInAssignments) {
-      if (rhs == null) {
-        return false;
-      }
-      if (!(rhs instanceof PsiNewExpression) || !(rhs instanceof PsiTypeCastExpression)) {
-        final PsiType rhsType = rhs.getType();
-        if (lhsType == null || lhsType.equals(rhsType)) {
-          return false;
-        }
-      }
+    else if (useRighthandTypeAsWeakestTypeInAssignments &&
+             (!(rhs instanceof PsiNewExpression) || !(rhs instanceof PsiTypeCastExpression)) &&
+             lhsType.equals(rhsType)) {
+      return false;
     }
     return true;
   }
@@ -546,14 +547,14 @@
     return true;
   }
 
-  public static Set<PsiClass> filterAccessibleClasses(Set<PsiClass> weakestTypeClasses, PsiElement context) {
+  public static Set<PsiClass> filterAccessibleClasses(Set<PsiClass> weakestTypeClasses, PsiClass upperBound, PsiElement context) {
     final Set<PsiClass> result = new HashSet<PsiClass>();
     for (PsiClass weakestTypeClass : weakestTypeClasses) {
-      if (PsiUtil.isAccessible(weakestTypeClass, context, null)) {
+      if (PsiUtil.isAccessible(weakestTypeClass, context, null) && !weakestTypeClass.isDeprecated()) {
         result.add(weakestTypeClass);
         continue;
       }
-      final PsiClass visibleInheritor = getVisibleInheritor(weakestTypeClass, context);
+      final PsiClass visibleInheritor = getVisibleInheritor(weakestTypeClass, upperBound, context);
       if (visibleInheritor != null) {
         result.add(visibleInheritor);
       }
@@ -562,16 +563,16 @@
   }
 
   @Nullable
-  private static PsiClass getVisibleInheritor(@NotNull PsiClass superClass, PsiElement context) {
+  private static PsiClass getVisibleInheritor(@NotNull PsiClass superClass, PsiClass upperBound, PsiElement context) {
     final Query<PsiClass> search = DirectClassInheritorsSearch.search(superClass, context.getResolveScope());
     final Project project = superClass.getProject();
     for (PsiClass aClass : search) {
-      if (superClass.isInheritor(aClass, true)) {
+      if (aClass.isInheritor(superClass, true) && upperBound.isInheritor(aClass, true)) {
         if (PsiUtil.isAccessible(project, aClass, context, null)) {
           return aClass;
         }
         else {
-          return getVisibleInheritor(aClass, context);
+          return getVisibleInheritor(aClass, upperBound, context);
         }
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
index 794716b..e45f06c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
@@ -16,9 +16,10 @@
 package com.siyeh.ig.style;
 
 import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.util.IncorrectOperationException;
@@ -46,30 +47,30 @@
   @NotNull
   @Override
   protected String buildErrorString(Object... infos) {
-    return InspectionGadgetsBundle.message("simplifiable.annotation.problem.descriptor");
+    if (((Boolean)infos[0]).booleanValue()) {
+      return InspectionGadgetsBundle.message("simplifiable.annotation.whitespace.problem.descriptor");
+    }
+    else {
+      return InspectionGadgetsBundle.message("simplifiable.annotation.problem.descriptor");
+    }
   }
 
   @Override
   protected InspectionGadgetsFix buildFix(Object... infos) {
-    final PsiAnnotation annotation = (PsiAnnotation)infos[0];
-    return new SimplifiableAnnotationFix(annotation);
+    return new SimplifiableAnnotationFix();
   }
 
   private static class SimplifiableAnnotationFix extends InspectionGadgetsFix {
 
-    private final String replacement;
-
-    public SimplifiableAnnotationFix(PsiAnnotation annotation) {
-      this.replacement = buildAnnotationText(annotation, new StringBuilder()).toString();
-    }
+    public SimplifiableAnnotationFix() {}
 
     @Override
     @NotNull
     public String getName() {
-      return InspectionGadgetsBundle.message("simplifiable.annotation.quickfix",
-                                             StringUtil.shortenTextWithEllipsis(replacement, 50, 0, true));
+      return InspectionGadgetsBundle.message("simplifiable.annotation.quickfix");
     }
-     @Override
+
+    @Override
     @NotNull
     public String getFamilyName() {
       return getName();
@@ -78,23 +79,25 @@
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
-      if (!(element instanceof PsiAnnotation)) {
+      final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class);
+      if (annotation == null) {
         return;
       }
       final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
-      final PsiAnnotation annotation = factory.createAnnotationFromText(replacement, element);
-      element.replace(annotation);
+      final String annotationText = buildAnnotationText(annotation);
+      final PsiAnnotation newAnnotation = factory.createAnnotationFromText(annotationText, element);
+      annotation.replace(newAnnotation);
     }
 
-    private static StringBuilder buildAnnotationText(PsiAnnotation annotation, StringBuilder out) {
-      out.append('@');
+    private static String buildAnnotationText(PsiAnnotation annotation) {
+      final StringBuilder out = new StringBuilder("@");
       final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
       assert nameReferenceElement != null;
       out.append(nameReferenceElement.getText());
       final PsiAnnotationParameterList parameterList = annotation.getParameterList();
       final PsiNameValuePair[] attributes = parameterList.getAttributes();
       if (attributes.length == 0) {
-        return out;
+        return out.toString();
       }
       out.append('(');
       if (attributes.length == 1) {
@@ -116,7 +119,7 @@
         }
       }
       out.append(')');
-      return out;
+      return out.toString();
     }
 
     private static StringBuilder buildAttributeValueText(PsiAnnotationMemberValue value, StringBuilder out) {
@@ -128,7 +131,7 @@
         }
       }
       else if (value instanceof PsiAnnotation) {
-        return buildAnnotationText((PsiAnnotation)value, out);
+        return out.append(buildAnnotationText((PsiAnnotation)value));
       }
       return out.append(value.getText());
     }
@@ -151,36 +154,36 @@
       }
       final PsiNameValuePair[] attributes = parameterList.getAttributes();
       final PsiElement[] annotationChildren = annotation.getChildren();
-      if (annotationChildren.length >= 2 && annotationChildren[1] instanceof PsiWhiteSpace) {
-        if (!containsError(annotation)) {
-          registerError(annotation, annotation);
-        }
+      if (annotationChildren.length >= 2 && annotationChildren[1] instanceof PsiWhiteSpace && !containsError(annotation)) {
+        registerError(annotationChildren[1], Boolean.TRUE);
       }
-      else if (attributes.length == 0) {
-        final PsiElement[] children = parameterList.getChildren();
-        if (children.length <= 0) {
-          return;
-        }
-        if (!containsError(annotation)) {
-          registerError(annotation, annotation);
+      if (attributes.length == 0) {
+        if (parameterList.getChildren().length > 0 && !containsError(annotation)) {
+          registerError(parameterList, ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
         }
       }
       else if (attributes.length == 1) {
         final PsiNameValuePair attribute = attributes[0];
-        @NonNls final String name = attribute.getName();
+        final PsiIdentifier identifier = attribute.getNameIdentifier();
         final PsiAnnotationMemberValue attributeValue = attribute.getValue();
-        if (!PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name)) {
-          if (!(attributeValue instanceof PsiArrayInitializerMemberValue)) {
-            return;
-          }
-          final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)attributeValue;
-          final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
-          if (initializers.length != 1) {
-            return;
+        if (identifier != null && attributeValue != null) {
+          @NonNls final String name = attribute.getName();
+          if (PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name) && !containsError(annotation)) {
+            registerErrorAtOffset(attribute, 0, attributeValue.getStartOffsetInParent(), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+                                  Boolean.FALSE);
           }
         }
+        if (!(attributeValue instanceof PsiArrayInitializerMemberValue)) {
+          return;
+        }
+        final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)attributeValue;
+        final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
+        if (initializers.length != 1) {
+          return;
+        }
         if (!containsError(annotation)) {
-          registerError(annotation, annotation);
+          registerError(arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
+          registerError(arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
         }
       }
       else if (attributes.length > 1) {
@@ -189,15 +192,15 @@
           if (!(value instanceof PsiArrayInitializerMemberValue)) {
             continue;
           }
-          final PsiArrayInitializerMemberValue arrayInitializerMemberValue = (PsiArrayInitializerMemberValue)value;
-          final PsiAnnotationMemberValue[] initializers = arrayInitializerMemberValue.getInitializers();
+          final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)value;
+          final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
           if (initializers.length != 1) {
             continue;
           }
           if (!containsError(annotation)) {
-            registerError(annotation, annotation);
+            registerError(arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
+            registerError(arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
           }
-          return;
         }
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
index 4747e74..70b620f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
@@ -20,7 +20,6 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.ContainerUtil;
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
@@ -86,7 +85,7 @@
     }
 
     @Override
-    protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+    protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
       final PsiElement parent = element.getParent();
       if (!(parent instanceof PsiVariable)) {
@@ -290,6 +289,9 @@
           methodCallExpression = (PsiMethodCallExpression)grandParent;
           parent = methodCallExpression.getParent();
           grandParent = parent.getParent();
+          if ("toString".equals(methodCallExpression.getMethodExpression().getReferenceName())) {
+            break;
+          }
         }
         if (buildStringExpression(methodCallExpression, myBuilder) == null) {
           myProblem = true;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
index 2aa72fa..7d8d955 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 import com.intellij.codeInspection.CleanupLocalInspectionTool;
 import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.util.IncorrectOperationException;
@@ -112,7 +113,7 @@
       for (final PsiElement child : children) {
         final String text = child.getText();
         if (PsiModifier.STATIC.equals(text)) {
-          registerError(child, child, aClass);
+          registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, child, aClass);
         }
       }
     }
@@ -131,7 +132,7 @@
       for (final PsiElement child : children) {
         final String text = child.getText();
         if (PsiModifier.PRIVATE.equals(text)) {
-          registerError(child, child, method);
+          registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, child, method);
         }
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
index 310cc20..a0718c0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 import com.intellij.codeInspection.CleanupLocalInspectionTool;
 import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiUtil;
@@ -214,7 +215,7 @@
       }
       for (PsiElement child : children) {
         if (modifiers.contains(child.getText())) {
-          registerError(child, redundantModifiers.toString(), list);
+          registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, redundantModifiers.toString(), list);
         }
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
index c1a7588..36f5af9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 import com.intellij.codeInspection.CleanupLocalInspectionTool;
 import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
@@ -111,7 +112,7 @@
     private void findTopLevelSemicolons(PsiElement element) {
       for (PsiElement sibling = element.getFirstChild(); sibling != null; sibling = skipForwardWhiteSpacesAndComments(sibling)) {
         if (PsiUtil.isJavaToken(sibling, JavaTokenType.SEMICOLON)) {
-          registerError(sibling);
+          registerError(sibling, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
         }
       }
     }
@@ -149,7 +150,7 @@
       if (next == null || !next.equals(aClass.getRBrace())) {
         return;
       }
-      registerError(element);
+      registerError(element, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
     }
 
     private void findUnnecessarySemicolonsAfterEnumConstants(
@@ -171,11 +172,11 @@
                 if (!JavaTokenType.COMMA.equals(prevTokenType)
                     && !JavaTokenType.LBRACE.equals(
                   prevTokenType)) {
-                  registerError(child);
+                  registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
                 }
               }
               else {
-                registerError(child);
+                registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
               }
             }
           }
@@ -207,7 +208,7 @@
         if (semicolon == null) {
           return;
         }
-        registerError(semicolon);
+        registerError(semicolon, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
       }
     }
 
@@ -218,7 +219,7 @@
       if (last instanceof PsiJavaToken && ((PsiJavaToken)last).getTokenType() == JavaTokenType.RPARENTH) {
         final PsiElement prev = skipBackwardWhiteSpacesAndComments(last);
         if (prev instanceof PsiJavaToken && ((PsiJavaToken)prev).getTokenType() == JavaTokenType.SEMICOLON) {
-          registerError(prev);
+          registerError(prev, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
         }
       }
     }
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
index 1894986..6444ff8 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
@@ -34,6 +34,7 @@
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.wm.StatusBar;
 import com.intellij.openapi.wm.WindowManager;
@@ -41,6 +42,7 @@
 import com.intellij.psi.PsiNameIdentifierOwner;
 import com.intellij.psi.PsiReference;
 import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.containers.ContainerUtil;
 import com.siyeh.InspectionGadgetsBundle;
 import org.jetbrains.annotations.NotNull;
 
@@ -68,7 +70,12 @@
         final PsiElement[] elements =
           PsiUtilCore.toPsiElementArray(elementCollection);
         final PsiElement firstElement = elements[0];
-        if (!firstElement.isValid()) {
+        if (ContainerUtil.exists(elements, new Condition<PsiElement>() {
+          @Override
+          public boolean value(PsiElement element) {
+            return !element.isValid();
+          }
+        })) {
           return;
         }
         final Project project = firstElement.getProject();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
index 47344f5..28c947e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
@@ -16,13 +16,13 @@
 package com.siyeh.ig.ui;
 
 import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.util.ReflectionUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
-import java.lang.reflect.Field;
 
 public class TextField extends JTextField {
 
@@ -36,35 +36,13 @@
 
   private static String getPropertyValue(InspectionProfileEntry owner,
                                          String property) {
-    try {
-      final Class<? extends InspectionProfileEntry> aClass =
-        owner.getClass();
-      final Field field = aClass.getField(property);
-      return (String)field.get(owner);
-    }
-    catch (IllegalAccessException ignore) {
-      return null;
-    }
-    catch (NoSuchFieldException ignore) {
-      return null;
-    }
+    return ReflectionUtil.getField(owner.getClass(), owner, String.class, property);
   }
 
   private static void setPropertyValue(InspectionProfileEntry owner,
                                        String property,
                                        String value) {
-    try {
-      final Class<? extends InspectionProfileEntry> aClass =
-        owner.getClass();
-      final Field field = aClass.getField(property);
-      field.set(owner, value);
-    }
-    catch (IllegalAccessException ignore) {
-      // do nothing
-    }
-    catch (NoSuchFieldException ignore) {
-      // do nothing
-    }
+    ReflectionUtil.setField(owner.getClass(), owner, String.class, property, value);
   }
 
   private class TextFieldDocumentListener implements DocumentListener {
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
index b22ad37..b0f698b 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
@@ -12,8 +12,8 @@
 <b>class</b> Y {
   <b>void</b> foo(String s) {
     <b>new</b> X() {{
-      System.out.println(s); // problem indicated here
-    }}
+      System.out.println(s); // here the field is accessed not the parameter
+    }};
   }
 }
 </code></pre>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html
new file mode 100644
index 0000000..c72e160
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+Reports calls on a setter with the value of same objects getter.
+For example: <code>bean.setPayerId(bean.getPayerId());</code>
+In regular circumstances this code is a no-op and probably not what was intented..
+<!-- tooltip end -->
+<p>
+  <small>New in 14</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
index 70255c1..c36afbc 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
@@ -3,14 +3,14 @@
 Reports return statements with <b>null</b> values.
 While occasionally useful, this construct may make the code more prone
 to failing with a <b>NullPointerException</b>, and often indicates that the
-developer doesn't really understand the classes intended semantics.
+developer doesn't really understand the class's intended semantics.
 <!-- tooltip end -->
 <p>
-Use the first control below to let this inspection ignore private methods.
+Use the first checkbox below to let this inspection ignore private methods.
 <p>
-Use bottom three controls to specify whether this inspection should report
+Use the bottom three checkboxes to specify whether
 <b>null</b> values on array returns, collection
-object returns, plain object returns, or a combination of the three.
+object returns, plain object returns, or a combination of the three should be reported.
 <p>
 
 </body>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java
new file mode 100644
index 0000000..4ced8b8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java
@@ -0,0 +1,5 @@
+public class MethodCallOnString {
+  public static void main(String... args) {
+      int length = "ABC".length();
+  }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java
new file mode 100644
index 0000000..2ff0203
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java
@@ -0,0 +1,6 @@
+public class MethodCallOnString {
+  public static void main(String... args) {
+    StringBuilder theBuilder<caret> = new StringBuilder("ABC");
+    int length = theBuilder.toString().length();
+  }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
index e5c1199..f21cc08 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
@@ -60,4 +60,14 @@
     <warning descr="Declaration of 'HashSet' should probably be weakened to 'java.util.Set'">HashSet</warning><String> set = new HashSet<>();
     set.add("foo");
   }
+
+  public static Properties stringToProperties(String propertiesAsString) { return null; }
+  public static Properties stringToProperties2(String propertiesAsString) { return null; }
+  public static Properties stringToProperties3(String propertiesAsString) { return null; }
+
+  void m() {
+    stringToProperties("");
+    <error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">String s = stringToProperties2("");</error>
+    <error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">s = stringToProperties3("")</error>;
+  }
 }
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
index 3d9b0a2..7c96abd 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
@@ -31,13 +31,13 @@
     public static class Bar extends Foo {}
 
     public static void test() {
-        try (Bar bar = new Bar()) {
+        try (Bar <warning descr="Type of variable 'bar' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.AutoClosableTest2.Foo'">bar</warning> = new Bar()) {
             bar.go();
         }
     }
 
     void dodo() throws java.io.IOException {
-        try (java.io.Reader  reader = new java.io.FileReader("/home/steve/foo.txt")) {
+        try (java.io.Reader  <warning descr="Type of variable 'reader' may be weakened to 'java.io.Closeable'">reader</warning> = new java.io.FileReader("/home/steve/foo.txt")) {
             System.out.println(reader);
         }
     }
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
index 0a00977..4b35471 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
@@ -1,6 +1,6 @@
-package com.siyeh.igtest.abstraction.weaken_type;
+package weaken_type;
 
-import com.siyeh.igtest.abstraction.weaken_type.sub.NumberAdderExtension;
+import weaken_type.sub.NumberAdderExtension;
 
 
 public class NumberAdderDemo {
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
index aeb2e1a..370aba5 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
@@ -52,7 +52,7 @@
         foo(new WeakBoolean());
     }
 
-    void foo(WeakBoolean b) {
+    void foo(WeakBoolean <warning descr="Type of parameter 'b' may be weakened to 'java.lang.Object'">b</warning>) {
         System.out.println("b: " + b);
     }
 
@@ -65,7 +65,7 @@
             FileInputStream fis=new FileInputStream("/etc/modules");
         }
         catch(FileNotFoundException fnfex) {
-            IllegalArgumentException iaex=new IllegalArgumentException("Exception Message");
+            IllegalArgumentException <warning descr="Type of variable 'iaex' may be weakened to 'java.lang.RuntimeException'">iaex</warning>=new IllegalArgumentException("Exception Message");
             iaex.initCause(fnfex);
             throw iaex;
         }
@@ -82,7 +82,7 @@
         void foo() { Test f = new Test(); f.x++; }
     }
 
-    void listy(ArrayList list) {
+    void listy(ArrayList <warning descr="Type of parameter 'list' may be weakened to 'java.lang.Iterable'">list</warning>) {
         for (Object o : list) {
 
         }
@@ -130,7 +130,7 @@
 
   public MyClass(java.util.Date date, String[] classNames) {}
 
-  static MyClass readMyClass(final ObjectInputStream objectInput) {
+  static MyClass readMyClass(final ObjectInputStream <warning descr="Type of parameter 'objectInput' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.DataInput'">objectInput</warning>) {
     final long time = objectInput.readLong();
     final int size = objectInput.readInt();
     final String[] classNames = new String[size];
@@ -150,4 +150,16 @@
   public String readUTF() {
     return null;
   }
-}
\ No newline at end of file
+}
+class Test implements Foo2 {
+  void test(Test <warning descr="Type of parameter 't' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.Foo2'">t</warning>) {
+    t.bar();
+  }
+  public void bar() {
+  }
+}
+@Deprecated
+interface Foo {
+  void bar();
+}
+interface Foo2 extends Foo {}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java
deleted file mode 100644
index 8f15c78..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-/**
- * Created by IntelliJ IDEA. User: HONOURK Date: 21-Aug-2008 Time: 12:15:41 To change this template
- * use File | Settings | File Templates.
- */
-public interface NumberAdder  {
-	int doSomething();
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java
deleted file mode 100644
index 21bdf29..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-/**
- * Created by IntelliJ IDEA. User: HONOURK Date: 21-Aug-2008 Time: 12:15:41 To change this template
- * use File | Settings | File Templates.
- */
-public class NumberAdderExtension extends NumberAdderImpl {
-	@Override
-	public int getNumberOne() {
-		return super.getNumberOne();
-	}
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java
deleted file mode 100644
index 669373d..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-public class NumberAdderImpl implements NumberAdder {
-
-	public int doSomething() {
-		return getNumberOne() + 1;
-	}
-
-	protected int getNumberOne() {
-		return 1;
-	}
-}
-
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java
new file mode 100644
index 0000000..228fe5c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java
@@ -0,0 +1,30 @@
+package com.siyeh.igtest.bugs.castConflictingInstanceof.andAnd;
+
+class Test {
+
+  public void test(Object o)
+  {
+
+    if (!(o instanceof Number) ||
+        ((Number)o).intValue() == 0 ||
+        !(o instanceof Integer) ||
+        ((Integer) o).byteValue() == 9) {
+      System.out.println();
+    }
+
+    if (!(o instanceof Number) ||
+        ((Number)o).intValue() == 0 ||
+        !(o instanceof Integer) ||
+        !(o instanceof Number) ||
+        ((Integer) o).byteValue() == 9) {
+      System.out.println();
+    }
+
+    if (!(o instanceof Integer) ||
+         ((Number)o).intValue() == 0 ||
+        !(o instanceof Number) ||
+        ((Integer) o).byteValue() == 9) {
+      System.out.println();
+    }
+  }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml
new file mode 100644
index 0000000..e8f00e8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+
+</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
index beed034..33683aa 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
@@ -183,4 +183,17 @@
   private static final java.io.ObjectStreamField[] serialPersistentFields = {
     new java.io.ObjectStreamField("b", String.class)
   };
+}
+
+class TestIDEA128098 {
+  private static final String[] CONSTANT_ARRAY = new String[]{""}; // warning is on this constant
+
+
+  enum SomeEnum {
+    ITEM( CONSTANT_ARRAY);
+    private final String[] myPatterns;
+    SomeEnum(String... patterns) {
+      myPatterns = patterns;
+    }
+  }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
index b402895..1fe15e0 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
@@ -2,8 +2,8 @@
 
 public class SimplifiableAnnotation {
 
-    <warning descr="Annotation '@ SuppressWarnings(value = \\"blabla\\")' can be simplified">@ SuppressWarnings(value = "blabla")</warning>
-    <warning descr="Annotation '@ Deprecated()' can be simplified">@ Deprecated()</warning>
+    @<warning descr="Unnecessary whitespace in annotation"> </warning>SuppressWarnings(<warning descr="Unnecessary 'value =' in annotation">value = </warning>"blabla")
+    @<warning descr="Unnecessary whitespace in annotation"> </warning>Deprecated<warning descr="Unnecessary '()' in annotation">()</warning>
     Object foo() {
         return null;
     }
@@ -14,8 +14,8 @@
 @interface ArrayAnnotation {
   String[] array();
 }
-<warning descr="Annotation '@ValueAnnotation({\\"the value\\"})' can be simplified">@ValueAnnotation({"the value"})</warning>
-<warning descr="Annotation '@ArrayAnnotation(array = {\\"first\\"})' can be simplified">@ArrayAnnotation(array = {"first"})</warning>
+@ValueAnnotation(<warning descr="Unnecessary '{' in annotation">{</warning>"the value"<warning descr="Unnecessary '}' in annotation">}</warning>)
+@ArrayAnnotation(array = <warning descr="Unnecessary '{' in annotation">{</warning>"first"<warning descr="Unnecessary '}' in annotation">}</warning>)
 class MyClass {
 
   @ <error descr="'value' missing though required">ValueAnnotation</error>
@@ -23,7 +23,7 @@
     return -1;
   }
 
-  <warning descr="Annotation '@Two(i={1}, j = 2)' can be simplified">@Two(i={1}, j = 2)</warning>
+  @Two(i=<warning descr="Unnecessary '{' in annotation">{</warning>1<warning descr="Unnecessary '}' in annotation">}</warning>, j = 2)
   String s;
 }
 @interface Two {
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
index fec9113..df0048a 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
@@ -1,24 +1,48 @@
 package com.siyeh.ig.abstraction;
 
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.pom.java.LanguageLevel;
-import com.siyeh.ig.IGInspectionTestCase;
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
 
-public class TypeMayBeWeakenedInspectionTest extends IGInspectionTestCase {
+public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase {
 
-  public void test() throws Exception {
-    final TypeMayBeWeakenedInspection inspection =
-      new TypeMayBeWeakenedInspection();
+  public void testTypeMayBeWeakened() { doTest(); }
+  public void testNumberAdderDemo() { doTest(); }
+  public void testAutoClosableTest() { doTest(); }
+
+  @Override
+  protected String[] getEnvironmentClasses() {
+    return new String[] {
+      "package weaken_type.sub;\n" +
+      "public class NumberAdderImpl implements NumberAdder {\n" +
+      "  public int doSomething() {\n" +
+      "    return getNumberOne() + 1;\n" +
+      "  }\n" +
+      "  protected int getNumberOne() {\n" +
+      "    return 1;\n" +
+      "  }\n" +
+      "}",
+      "package weaken_type.sub;\n" +
+      "public class NumberAdderExtension extends NumberAdderImpl {\n" +
+      "  @Override\n" +
+      "  public int getNumberOne() {\n" +
+      "    return super.getNumberOne();\n" +
+      "  }\n" +
+      "}"
+    };
+  }
+
+  @Override
+  protected String getBasePath() {
+    return "/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type";
+  }
+
+  @Nullable
+  @Override
+  protected InspectionProfileEntry getInspection() {
+    final TypeMayBeWeakenedInspection inspection = new TypeMayBeWeakenedInspection();
     inspection.doNotWeakenToJavaLangObject = false;
     inspection.onlyWeakentoInterface = false;
-    final LanguageLevelProjectExtension levelProjectExtension = LanguageLevelProjectExtension.getInstance(getProject());
-    final LanguageLevel level = levelProjectExtension.getLanguageLevel();
-    try {
-      levelProjectExtension.setLanguageLevel(LanguageLevel.JDK_1_7);
-      doTest("com/siyeh/igtest/abstraction/weaken_type", inspection);
-    }
-    finally {
-      levelProjectExtension.setLanguageLevel(level);
-    }
+    return inspection;
   }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
index ff6d488..079bda6 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
@@ -43,6 +43,10 @@
     doTest();
   }
 
+  public void testOrInstanceofOrInstanceof() throws Exception {
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest("com/siyeh/igtest/bugs/castConflictingInstanceof/" + getTestName(true), new CastConflictsWithInstanceofInspection());
   }
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
index f49e16b..8c7920b 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
@@ -32,4 +32,5 @@
   public void testCharLiteral() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
   public void testEscape() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
   public void testUnescape() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
+  public void testMethodCallOnString() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
 }
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
index 99c6a24..a2b334c 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
@@ -31,7 +31,7 @@
   protected String[] getEnvironmentClasses() {
     return new String[] {
       "package java.util;" +
-      "public class LinkedHashMap<K, V> {" +
+      "public class LinkedHashMap<K, V> extends HashMap<K,V> implements Map<K,V>{" +
       "  protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {\n" +
       "    return false;\n" +
       "  }" +
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java
new file mode 100644
index 0000000..d173871
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package com.siyeh.ig.javabeans;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
+
+public class PropertyValueSetToItselfInspectionTest extends LightInspectionTestCase {
+
+  public void testSimple() {
+    doTest("class Bean {\n" +
+           "  private String x;\n" +
+           "  public void setX(String x) {\n" +
+           "    this.x = x;\n" +
+           "  }\n" +
+           "  public String getX() { return x; }\n" +
+           "  void m(Bean b) {\n" +
+           "    (b)./*Property value set to itself*/setX/**/(b.getX());\n" +
+           "    this./*Property value set to itself*/setX/**/(getX());\n" +
+           "  }\n" +
+           "}");
+  }
+
+  public void testNoWarn() {
+    doTest("class Bean {\n" +
+           "  private String x;\n" +
+           "  public void setX(String x) {\n" +
+           "    this.x = x;\n" +
+           "  }\n" +
+           "  public String getX() { return x; }\n" +
+           "  void m(Bean b, Bean c) {\n" +
+           "    (b).setX(c.getX());\n" +
+           "  }\n" +
+           "}");
+  }
+
+  @Nullable
+  @Override
+  protected InspectionProfileEntry getInspection() {
+    return new PropertyValueSetToItselfInspection();
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntelliLang/java-support/resources/javaInjections.xml b/plugins/IntelliLang/java-support/resources/javaInjections.xml
index 4b66c8b..97ba2e6 100644
--- a/plugins/IntelliLang/java-support/resources/javaInjections.xml
+++ b/plugins/IntelliLang/java-support/resources/javaInjections.xml
@@ -130,6 +130,13 @@
     <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("PrintStream").withParameters("java.lang.String", "java.lang.String").definedInClass("java.io.PrintStream"))]]></place>
     <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("encode").withParameters("java.lang.String", "java.lang.String").definedInClass("java.net.URLEncoder"))]]></place>
     <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("decode").withParameters("java.lang.String", "java.lang.String").definedInClass("java.net.URLDecoder"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(0, psiMethod().withName("setCharacterEncoding").withParameters("java.lang.String").definedInClass("javax.servlet.ServletResponse"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.nio.channels.ReadableByteChannel", "java.lang.String").definedInClass("java.nio.channels.Channels"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.nio.channels.WritableByteChannel", "java.lang.String").definedInClass("java.nio.channels.Channels"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLEventReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLStreamReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLEventWriter").withParameters("java.io.OutputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLStreamWriter").withParameters("java.io.OutputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
   </injection>
 
 </component>
diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml
index 8f8806a..4caafeb 100644
--- a/plugins/IntelliLang/src/META-INF/plugin.xml
+++ b/plugins/IntelliLang/src/META-INF/plugin.xml
@@ -20,7 +20,6 @@
   <depends optional="true" config-file="intellilang-xpath-support.xml">XPathView</depends>
   <depends optional="true" config-file="intellilang-java-support.xml">com.intellij.modules.java</depends>
   <depends optional="true" config-file="intellilang-xml-support.xml">com.intellij.modules.xml</depends>
-  <depends optional="true" config-file="intellilang-python-support.xml">com.intellij.modules.python</depends>
 
   <extensionPoints>
     <extensionPoint name="languageSupport" interface="org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport"/>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
index 48ee3b5..1b4e43e 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
@@ -226,7 +226,7 @@
   }
 
   @Nullable
-  public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref<PsiElement> causeRef) {
+  public static BaseInjection findCommentInjection(@NotNull PsiElement context, @NotNull String supportId, @Nullable Ref<PsiElement> causeRef) {
     PsiElement target = CompletionUtil.getOriginalOrSelf(context);
     PsiFile file = target.getContainingFile();
     TreeMap<TextRange, BaseInjection> map = getInjectionMap(file);
@@ -247,17 +247,17 @@
     // make sure comment is close enough and ...
     int off1 = r0.getEndOffset();
     int off2 = e2.getTextRange().getStartOffset();
-    if (off2 - off1 > 120) return null;
-    if (off2 - off1 > 2) {
-      // ... there's nothing in between on the top level and ...
-      for (PsiElement e = e1; e != e2; e = e.getNextSibling()) {
-        if (!isWhitespaceCommentOrBlank(e)) return null;
-      }
-      // ... there's no non-empty host in the left (comment) subtree
-      Producer<PsiElement> producer = prevWalker(PsiTreeUtil.getDeepestLast(e1), e1);
+    if (off2 - off1 > 120) {
+      return null;
+    }
+    else if (off2 - off1 > 2) {
+      // ... there's no non-empty valid host in between comment and e2
+      Producer<PsiElement> producer = prevWalker(e2, commonParent);
       PsiElement e;
       while ( (e = producer.produce()) != null && e != psiComment) {
-        if (e instanceof PsiLanguageInjectionHost && !StringUtil.isEmptyOrSpaces(e.getText())) {
+        if (e instanceof PsiLanguageInjectionHost &&
+            ((PsiLanguageInjectionHost)e).isValidHost() &&
+            !StringUtil.isEmptyOrSpaces(e.getText())) {
           return null;
         }
       }
@@ -268,12 +268,9 @@
     return new BaseInjection(supportId).copyFrom(entry.getValue());
   }
 
-  protected static boolean isWhitespaceCommentOrBlank(PsiElement e) {
-    return e instanceof PsiWhiteSpace || e instanceof PsiComment ||
-           e instanceof PsiLanguageInjectionHost && StringUtil.isEmptyOrSpaces(e.getText());
-  }
-
-  protected static TreeMap<TextRange, BaseInjection> getInjectionMap(final PsiFile file) {
+  @Nullable
+  private static TreeMap<TextRange, BaseInjection> getInjectionMap(@Nullable final PsiFile file) {
+    if (file == null) return null; //  e.g. null for synthetic groovy variables
     return CachedValuesManager.getCachedValue(file, new CachedValueProvider<TreeMap<TextRange, BaseInjection>>() {
       @Nullable
       @Override
@@ -293,8 +290,6 @@
     CharSequence contents = file.getViewProvider().getContents();
     final char[] contentsArray = CharArrayUtil.fromSequenceWithoutCopying(contents);
 
-    //long time = System.currentTimeMillis();
-
     int s0 = 0, s1 = contents.length();
     for (int idx = searcher.scan(contents, contentsArray, s0, s1);
          idx != -1;
@@ -309,30 +304,6 @@
         }
       }
     }
-
-    //VirtualFile virtualFile = file.getVirtualFile();
-    //Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
-    //EditorHighlighter highlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document);
-    //
-    //ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(file.getLanguage());
-    //TokenSet commentTokens = definition.getCommentTokens();
-    //HighlighterIterator it = highlighter != null && PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(contents, highlighter) ?
-    //                         highlighter.createIterator(0) : null;
-    //
-    //do {
-    //  if (it != null) {
-    //    while (!it.atEnd() && !commentTokens.contains(it.getTokenType())) it.advance();
-    //    if (it.atEnd()) break;
-    //  }
-    //  int s0 = it == null ? 0 : it.getStart();
-    //  int s1 = it == null ? contents.length() : it.getEnd();
-    //
-    //  for () { .. }
-    //
-    //  if (it != null && !it.atEnd()) it.advance();
-    //} while (it != null && !it.atEnd());
-
-    //System.out.println(Thread.currentThread().getName() + ": " + file.getName() + "@" + file.hashCode() + " indexed: " + (System.currentTimeMillis() - time));
     return injectionMap;
   }
 
@@ -373,18 +344,11 @@
         if (e == null || e == scope) return null;
         PsiElement prev = e.getPrevSibling();
         if (prev != null) {
-          e = prev;
-          while (true) {
-            PsiElement lastChild = e.getLastChild();
-            if (lastChild == null) break;
-            e = lastChild;
-          }
-          return e;
+          return e = PsiTreeUtil.getDeepestLast(prev);
         }
         else {
           PsiElement parent = e.getParent();
-          e = parent == scope || parent instanceof PsiFile ? null : parent;
-          return e;
+          return e = parent == scope || parent instanceof PsiFile ? null : parent;
         }
       }
     };
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
index dc1b4c6..30e6492 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
+++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
@@ -145,7 +145,7 @@
 if.to.assertion.intention.family.name=Replace If with Assert Statement
 if.to.assertion.intention.name=Replace 'if' with 'assert' statement
 expand.to.normal.annotation.intention.family.name=Expand Annotation to Normal Form
-expand.to.normal.annotation.name=Expand to ''{0}''
+expand.to.normal.annotation.intention.name=Add 'value=' to annotation attribute
 annotate.overridden.methods.intention.family.name=Annotate overriding methods and their parameters
 annotate.overridden.methods.intention.method.name=Annotate overriding methods as ''@{0}''
 annotate.overridden.methods.intention.parameters.name=Annotate same parameter of overriding methods as ''@{0}''
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
index e9cd879..a1563b8 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
@@ -15,25 +15,12 @@
  */
 package com.siyeh.ipp.annotation;
 
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.base.MutablyNamedIntention;
+import com.siyeh.ipp.base.Intention;
 import com.siyeh.ipp.base.PsiElementPredicate;
 import org.jetbrains.annotations.NotNull;
 
-public class ExpandToNormalAnnotationIntention extends MutablyNamedIntention {
-
-  @Override
-  protected String getTextForElement(PsiElement element) {
-    final PsiNameValuePair annotation = (PsiNameValuePair)element;
-    final String text = buildReplacementText(annotation);
-    return IntentionPowerPackBundle.message(
-      "expand.to.normal.annotation.name", text);
-  }
+public class ExpandToNormalAnnotationIntention extends Intention {
 
   @NotNull
   @Override
@@ -41,38 +28,28 @@
     return new ExpandToNormalAnnotationPredicate();
   }
 
-  public static String buildReplacementText(PsiNameValuePair attribute) {
+  public static String buildReplacementText(PsiAnnotationParameterList annotationParameterList) {
     final StringBuilder text = new StringBuilder();
-    final PsiAnnotationMemberValue value = attribute.getValue();
-    text.append("value = ");
-    if (value != null) {
-      text.append(value.getText());
+    for (PsiNameValuePair nameValuePair : annotationParameterList.getAttributes()) {
+      if (text.length() != 0) {
+        text.append(',');
+      }
+      final String name = nameValuePair.getName();
+      text.append(name != null ? name : "value").append('=');
+      final PsiAnnotationMemberValue value = nameValuePair.getValue();
+      if (value != null) {
+        text.append(value.getText());
+      }
     }
     return text.toString();
   }
 
   @Override
   protected void processIntention(@NotNull PsiElement element) {
-    final PsiNameValuePair attribute = (PsiNameValuePair)element;
-    final int textOffset = attribute.getTextOffset();
-    final Project project = attribute.getProject();
-    final String text = buildReplacementText(attribute);
-    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
-    final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@A(" + text +" )", attribute);
-    final PsiAnnotationParameterList parent = (PsiAnnotationParameterList)attribute.getParent();
-    for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
-      if (child instanceof PsiErrorElement) {
-        child.delete();
-        break;
-      }
-    }
-    attribute.replace(newAnnotation.getParameterList().getAttributes()[0]);
-    final FileEditorManager editorManager = FileEditorManager.getInstance(project);
-    final Editor editor = editorManager.getSelectedTextEditor();
-    if (editor == null) {
-      return;
-    }
-    final CaretModel caretModel = editor.getCaretModel();
-    caretModel.moveToOffset(textOffset + text.length() - 1);
+    final PsiAnnotationParameterList annotationParameterList = (PsiAnnotationParameterList)element.getParent();
+    final String text = buildReplacementText(annotationParameterList);
+    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(annotationParameterList.getProject());
+    final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@A(" + text +" )", element);
+    annotationParameterList.replace(newAnnotation.getParameterList());
   }
 }
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
index 10caec2..e361771 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.ClassUtils;
 import com.siyeh.ig.psiutils.ParenthesesUtils;
 import com.siyeh.ig.psiutils.VariableAccessUtils;
 import com.siyeh.ipp.base.Intention;
@@ -58,6 +59,9 @@
       annotation.delete();
     } else {
       final PsiStatement referenceStatement = PsiTreeUtil.getParentOfType(referenceExpression, PsiStatement.class);
+      if (referenceStatement == null) {
+        return;
+      }
       final PsiElement parent = referenceStatement.getParent();
       if (!(parent instanceof PsiCodeBlock)) {
         return;
@@ -103,6 +107,9 @@
         return false;
       }
       final PsiVariable variable = (PsiVariable)target;
+      if (ClassUtils.findClass("java.util.Objects", element) == null) {
+        return false;
+      }
       if (NullableNotNullManager.isNotNull(variable)) {
         return true;
       }
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
index dea52b1..31a5b06 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,9 @@
 
 import com.siyeh.ipp.IPPTestCase;
 
+/**
+ * @see ExpandToNormalAnnotationIntention
+ */
 public class ExpandToNormalAnnotationIntentionTest extends IPPTestCase {
   public void testOneAttr() throws Exception {
     doTest();
@@ -32,7 +35,7 @@
 
   @Override
   protected String getIntentionName() {
-    return "Expand to 'value = \"foo\"'";
+    return "Add 'value=' to annotation attribute";
   }
 
   @Override
diff --git a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
index 426604f..baff663 100644
--- a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
+++ b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.application.ex.PathManagerEx;
 import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderTestCase;
 import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
@@ -26,6 +27,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Map;
 
 import static com.intellij.util.io.TestFileSystemBuilder.fs;
@@ -61,8 +63,9 @@
     return PathManagerEx.findFileUnderProjectHome("plugins/ant/jps-plugin/testData", getClass()).getAbsolutePath();
   }
 
+  @NotNull
   @Override
-  protected void addPathVariables(Map<String, String> pathVariables) {
-    pathVariables.put("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(myArtifactsOutput.getAbsolutePath()));
+  protected Map<String, String> getAdditionalPathVariables() {
+    return Collections.singletonMap("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(myArtifactsOutput.getAbsolutePath()));
   }
 }
diff --git a/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java b/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
index 234a734..ef0fa80 100644
--- a/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
+++ b/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,12 +17,12 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.util.Alarm;
+import com.intellij.util.ReflectionUtil;
 import org.apache.tools.ant.IntrospectionHelper;
 import org.apache.tools.ant.TaskContainer;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.Nullable;
 
-import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.*;
@@ -231,8 +231,7 @@
     catch (Throwable e) {
       try {
         // assume it is older version of ant
-        final Field helpersField = helperClass.getDeclaredField("helpers");
-        final Map helpersCollection = (Map)helpersField.get(null);
+        Map helpersCollection = ReflectionUtil.getField(helperClass, null, null, "helpers");
         helpersCollection.clear();
       }
       catch (Throwable _e) {
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
index 6f2fb85..3af6d25 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
@@ -25,6 +25,8 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.problems.Problem;
+import com.intellij.problems.WolfTheProblemSolver;
 import com.intellij.rt.ant.execution.IdeaAntLogger2;
 import com.intellij.util.text.StringTokenizer;
 import org.jetbrains.annotations.NonNls;
@@ -32,6 +34,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class OutputParser{
@@ -193,7 +196,7 @@
     return -1;
   }
 
-  private static void processJavacMessages(final List<String> javacMessages, final AntBuildMessageView messageView, Project project) {
+  private static void processJavacMessages(final List<String> javacMessages, final AntBuildMessageView messageView, final Project project) {
     if (javacMessages == null) {
       return;
     }
@@ -241,6 +244,12 @@
           public void run() {
             VirtualFile file = url == null ? null : VirtualFileManager.getInstance().findFileByUrl(url);
             messageView.outputJavacMessage(convertCategory(category), strings, file, url, lineNum, columnNum);
+
+            if (file != null && category == CompilerMessageCategory.ERROR) {
+              final WolfTheProblemSolver wolf = WolfTheProblemSolver.getInstance(project);
+              final Problem problem = wolf.convertToProblem(file, lineNum, columnNum, strings);
+              wolf.weHaveGotNonIgnorableProblems(file, Collections.singletonList(problem));
+            }
           }
         });
       }
diff --git a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
index 479211e..c327d76 100644
--- a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
+++ b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
@@ -25,7 +25,7 @@
 import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.roots.ProjectRootManager;
@@ -223,7 +223,7 @@
   }
 
   public void showCoverageInformation(final CoverageSuitesBundle suite) {
-    if (myEditor == null) return;
+    if (myEditor == null || myFile == null) return;
     final MarkupModel markupModel = DocumentMarkupModel.forDocument(myDocument, myProject, true);
     final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
     final ProjectData data = suite.getCoverageData();
@@ -278,7 +278,7 @@
       @Nullable
       @Override
       public Module compute() {
-        return ModuleUtil.findModuleForPsiElement(myFile);
+        return ModuleUtilCore.findModuleForPsiElement(myFile);
       }
     });
     if (module != null) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
index e76f2f0..80efbd4 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -58,13 +58,13 @@
 
       final VcsContext context = CvsContextWrapper.createCachedInstance(e);
       final VirtualFile[] files = context.getSelectedFiles();
-      if (files == null || files.length == 0) return;
+      if (files.length == 0) return;
+      final Project project = context.getProject();
       final ReadonlyStatusHandler.OperationStatus operationStatus =
-        ReadonlyStatusHandler.getInstance(context.getProject()).ensureFilesWritable(files);
+        ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
       if (operationStatus.hasReadonlyFiles()) {
         return;
       }
-      final Project project = context.getProject();
       AbstractVcsHelper.getInstance(project).showMergeDialog(Arrays.asList(files), new CvsMergeProvider());
     }
     catch (Exception e1) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
index a2e055b..a652289 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
@@ -33,13 +33,8 @@
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.ObjectsConvertor;
-import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.*;
 import com.intellij.openapi.vcs.actions.VcsContextFactory;
 import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vcs.history.VcsRevisionNumber;
@@ -63,13 +58,13 @@
 
   private final CvsVcs2 myVcs;
   private final CvsEntriesManager myEntriesManager;
-  private final ProjectFileIndex myFileIndex;
+  private final ProjectLevelVcsManager myVcsManager;
   private final ChangeListManager myChangeListManager;
 
   public CvsChangeProvider(final CvsVcs2 vcs, CvsEntriesManager entriesManager) {
     myVcs = vcs;
     myEntriesManager = entriesManager;
-    myFileIndex = ProjectRootManager.getInstance(vcs.getProject()).getFileIndex();
+    myVcsManager = ProjectLevelVcsManager.getInstance(vcs.getProject());
     myChangeListManager = ChangeListManager.getInstance(vcs.getProject());
   }
 
@@ -169,7 +164,7 @@
         for (VirtualFile file : children) {
           progress.checkCanceled();
           if (file.isDirectory()) {
-            final boolean isIgnored = myFileIndex.isExcluded(file);
+            final boolean isIgnored = myVcsManager.isIgnored(file);
             if (!isIgnored) {
               processEntriesIn(file, scope, builder, true, progress);
             }
@@ -284,7 +279,7 @@
 
   private void checkSwitchedDir(final VirtualFile dir, final ChangelistBuilder builder, final VcsDirtyScope scope) {
     final VirtualFile parentDir = dir.getParent();
-    if (parentDir == null || !myFileIndex.isInContent(parentDir)) {
+    if (parentDir == null || !myVcsManager.isFileInContent(parentDir)) {
       return;
     }
     final CvsInfo info = myEntriesManager.getCvsInfoFor(dir);
@@ -317,7 +312,7 @@
 
   private void checkSwitchedFile(final FilePath filePath, final ChangelistBuilder builder, final VirtualFile dir, final Entry entry) {
     // if content root itself is switched, ignore
-    if (!myFileIndex.isInContent(dir)) {
+    if (!myVcsManager.isFileInContent(dir)) {
       return;
     }
     final String dirTag = myEntriesManager.getCvsInfoFor(dir).getStickyTag();
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
index 3877a78..eb30dd7 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
@@ -30,9 +30,8 @@
 import com.intellij.openapi.fileChooser.FileSystemTree;
 import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -150,12 +149,11 @@
     if (myProject == null) {
       return;
     }
-    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-    if (!fileIndex.isExcluded(selectedFile)) {
+    if (!isIgnoredByVcs(selectedFile)) {
       return;
     }
     final VirtualFile parent = selectedFile.getParent();
-    if (parent != null && fileIndex.isExcluded(parent)) {
+    if (parent != null && isIgnoredByVcs(parent)) {
       return;
     }
     for (final VirtualFile excludedFile : myExcludedFiles) {
@@ -182,12 +180,11 @@
       if (myProject == null) {
         continue;
       }
-      final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-      if (!fileIndex.isExcluded(selectedFile)) {
+      if (!isIgnoredByVcs(selectedFile)) {
         continue;
       }
       final VirtualFile parent = selectedFile.getParent();
-      if (parent == null || fileIndex.isExcluded(parent) || myExcludedFiles.contains(parent)) {
+      if (parent == null || isIgnoredByVcs(parent) || myExcludedFiles.contains(parent)) {
         continue;
       }
       if (!myIncludedFiles.contains(selectedFile)) {
@@ -211,7 +208,7 @@
         return true;
       }
     }
-    if (myProject == null || !ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(file)) {
+    if (myProject == null || !isIgnoredByVcs(file)) {
       return false;
     }
     for (VirtualFile includedFile : myIncludedFiles) {
@@ -242,7 +239,7 @@
         if (FileTypeManager.getInstance().isFileIgnored(abstractFileObject.getName())) return true;
         if (myProject != null && !includedFiles.contains(file)) {
           final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
-          if (vFile != null && ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(vFile)) {
+          if (vFile != null && isIgnoredByVcs(vFile)) {
             return true;
           }
         }
@@ -257,4 +254,8 @@
       }
     };
   }
+
+  private boolean isIgnoredByVcs(VirtualFile vFile) {
+    return myProject != null && ProjectLevelVcsManager.getInstance(myProject).isIgnored(vFile);
+  }
 }
diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml
index 9bb838c..0a9501e 100644
--- a/plugins/devkit/resources/META-INF/plugin.xml
+++ b/plugins/devkit/resources/META-INF/plugin.xml
@@ -12,7 +12,7 @@
 
   <depends>com.intellij.properties</depends>
 
-  <resource-bundle>DevKitBundle</resource-bundle>
+  <resource-bundle>org.jetbrains.idea.devkit.DevKitBundle</resource-bundle>
 
   <extensions defaultExtensionNs="com.intellij">
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
@@ -56,52 +56,44 @@
                                 implementationClass="org.jetbrains.idea.devkit.references.extensions.ExtensionPointDocumentationProvider"/>
 
     <localInspection language="XML" shortName="PluginXmlValidity" displayName="Plugin.xml Validity"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name" enabledByDefault="true" level="ERROR"
                      implementationClass="org.jetbrains.idea.devkit.inspections.PluginXmlDomInspection"/>
-    <localInspection language="JAVA" shortName="ComponentNotRegistered" bundle="DevKitBundle"
+    <localInspection language="JAVA" shortName="ComponentNotRegistered"
                      key="inspections.component.not.registered.name" groupKey="inspections.group.name" enabledByDefault="true"
                      level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection"/>
     <localInspection language="JAVA" shortName="InspectionDescriptionNotFoundInspection" displayName="Inspection Description Checker"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection"/>
     <localInspection language="JAVA" shortName="InspectionUsingGrayColors" displayName="Using new Color(a,a,a)"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.UseGrayInspection"/>
     <localInspection language="JAVA" shortName="IntentionDescriptionNotFoundInspection" displayName="Intention Description Checker"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection"/>
     <localInspection language="JAVA"
                      key="inspections.component.postfix.template.not.found.description.name"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true"
                      level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection"/>
     <localInspection shortName="ComponentRegistrationProblems"
-                     bundle="DevKitBundle" key="inspections.registration.problems.name"
+                      key="inspections.registration.problems.name"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="ERROR"
                      implementationClass="org.jetbrains.idea.devkit.inspections.RegistrationProblemsInspection"/>
     <localInspection language="JAVA" shortName="DialogTitleCapitalization"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      displayName="Incorrect dialog title capitalization"
                      enabledByDefault="true"
                      level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.TitleCapitalizationInspection"/>
     <localInspection language="XML" shortName="InspectionMappingConsistency"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      displayName="&lt;inspection&gt; tag consistency"
                      enabledByDefault="true"
                      level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.InspectionMappingConsistencyInspection"/>
     <localInspection language="XML" shortName="ExtensionPointBeanClass"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      displayName="&lt;extensionPoint&gt; beanClass specification"
                      enabledByDefault="true"
@@ -109,42 +101,34 @@
                      implementationClass="org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection"/>
 
     <localInspection language="JAVA" shortName="UndesirableClassUsage" displayName="Undesirable class usage"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UndesirableClassUsageInspection"/>
     <localInspection language="JAVA" shortName="FileEqualsUsage" displayName="File.equals() usage"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.FileEqualsUsageInspection"/>
     <localInspection language="JAVA" shortName="GtkPreferredJComboBoxRenderer" displayName="Preferred JComboBox renderer"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.GtkPreferredJComboBoxRendererInspection"/>
     <localInspection language="JAVA" shortName="UnsafeVfsRecursion" displayName="Unsafe VFS recursion"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UnsafeVfsRecursionInspection"/>
     <localInspection language="JAVA" shortName="UseJBColor" displayName="Use Darcula aware JBColor"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseJBColorInspection"/>
     <localInspection language="JAVA" shortName="UseCouple" displayName="Use Couple instead of Pair"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="false" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseCoupleInspection"/>
     <localInspection language="JAVA" shortName="DontUsePairConstructor" displayName="Don't use constructor of Pair class"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.DontUseNewPairInspection"/>
     <localInspection language="JAVA" shortName="UseVirtualFileEquals" displayName="Use VirtualFile.equals"
-                     bundle="DevKitBundle"
                      groupKey="inspections.group.name"
                      enabledByDefault="true" level="WARNING"
                      implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseVirtualFileEqualsInspection"/>
diff --git a/plugins/devkit/resources/DevKitBundle.properties b/plugins/devkit/resources/org/jetbrains/idea/devkit/DevKitBundle.properties
similarity index 100%
rename from plugins/devkit/resources/DevKitBundle.properties
rename to plugins/devkit/resources/org/jetbrains/idea/devkit/DevKitBundle.properties
diff --git a/plugins/devkit/src/DevKitBundle.java b/plugins/devkit/src/DevKitBundle.java
index 013fd2f..d5460ad 100644
--- a/plugins/devkit/src/DevKitBundle.java
+++ b/plugins/devkit/src/DevKitBundle.java
@@ -26,7 +26,7 @@
     return ourInstance.getMessage(key, params);
   }
 
-  @NonNls private static final String BUNDLE = "DevKitBundle";
+  @NonNls private static final String BUNDLE = "org.jetbrains.idea.devkit.DevKitBundle";
   private static final DevKitBundle ourInstance = new DevKitBundle();
 
   private DevKitBundle() {
diff --git a/plugins/devkit/src/actions/ShowSerializedXmlAction.java b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
index 8880424..e718eb7 100644
--- a/plugins/devkit/src/actions/ShowSerializedXmlAction.java
+++ b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
@@ -41,6 +41,7 @@
 import com.intellij.util.containers.FList;
 import com.intellij.util.lang.UrlClassLoader;
 import com.intellij.util.xmlb.Accessor;
+import com.intellij.util.xmlb.XmlSerializationException;
 import com.intellij.util.xmlb.XmlSerializer;
 import com.intellij.util.xmlb.XmlSerializerUtil;
 import org.jdom.Element;
@@ -121,7 +122,16 @@
       return;
     }
 
-    final Element element = XmlSerializer.serialize(o);
+    final Element element;
+    try {
+      element = XmlSerializer.serialize(o);
+    }
+    catch (XmlSerializationException e) {
+      LOG.info(e);
+      Throwable cause = e.getCause();
+      Messages.showErrorDialog(project, e.getMessage() + (cause != null ? ": " + cause.getMessage() : ""), CommonBundle.getErrorTitle());
+      return;
+    }
     final String text = JDOMUtil.writeElement(element, "\n");
     Messages.showIdeaMessageDialog(project, text, "Serialized XML for '" + className + "'",
                                    new String[]{CommonBundle.getOkButtonText()}, 0, Messages.getInformationIcon(), null);
diff --git a/plugins/devkit/src/build/PrepareToDeployAction.java b/plugins/devkit/src/build/PrepareToDeployAction.java
index b501331..37bedb4 100644
--- a/plugins/devkit/src/build/PrepareToDeployAction.java
+++ b/plugins/devkit/src/build/PrepareToDeployAction.java
@@ -164,6 +164,7 @@
           else {
             FileUtil.copy(jarFile, dstFile);
           }
+          LocalFileSystem.getInstance().refreshIoFiles(Collections.singleton(dstFile), true, false, null);
           successMessages.add(DevKitBundle.message("saved.message", isZip ? 1 : 2, pluginName, dstPath));
         }
         catch (final IOException e) {
diff --git a/plugins/devkit/src/dom/DependencyConfigFileConverter.java b/plugins/devkit/src/dom/DependencyConfigFileConverter.java
index 214d21e..b9cb283 100644
--- a/plugins/devkit/src/dom/DependencyConfigFileConverter.java
+++ b/plugins/devkit/src/dom/DependencyConfigFileConverter.java
@@ -93,12 +93,12 @@
         public Collection<PsiFileSystemItem> computeDefaultContexts() {
           final PsiFile containingFile = getContainingFile();
           if (containingFile == null) {
-            return super.getDefaultContexts();
+            return Collections.emptyList();
           }
 
           final Module module = ModuleUtilCore.findModuleForPsiElement(getElement());
           if (module == null) {
-            return super.getDefaultContexts();
+            return Collections.emptyList();
           }
 
           final Set<VirtualFile> roots = new HashSet<VirtualFile>();
diff --git a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
index 80a3aab..b3d7fda 100644
--- a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
+++ b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -21,16 +21,20 @@
 import com.intellij.lang.annotation.HighlightSeverity;
 import com.intellij.openapi.util.Iconable;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
 import com.intellij.util.xml.DomElement;
 import com.intellij.util.xml.DomFileDescription;
 import com.intellij.util.xml.DomUtil;
 import com.intellij.util.xml.GenericAttributeValue;
 import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
 import com.intellij.util.xml.highlighting.DomElementsAnnotator;
+import com.intellij.util.xml.reflect.DomAttributeChildDescription;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.devkit.dom.*;
 
 import javax.swing.*;
+import java.util.List;
 
 /**
  * @author mike
@@ -73,12 +77,29 @@
       final ExtensionPoint extensionPoint = extension.getExtensionPoint();
       if (extensionPoint == null) return;
       final GenericAttributeValue<PsiClass> interfaceAttribute = extensionPoint.getInterface();
-      if (!DomUtil.hasXml(interfaceAttribute)) return;
+      if (DomUtil.hasXml(interfaceAttribute)) {
+        final PsiClass value = interfaceAttribute.getValue();
+        if (value != null && value.isDeprecated()) {
+          final Annotation annotation = holder.createAnnotation(extension, HighlightSeverity.WARNING, "Deprecated EP");
+          annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+          return;
+        }
+      }
 
-      final PsiClass value = interfaceAttribute.getValue();
-      if (value != null && value.isDeprecated()) {
-        final Annotation annotation = holder.createAnnotation(extension, HighlightSeverity.WARNING, "Deprecated EP");
-        annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+      final List<? extends DomAttributeChildDescription> descriptions = extension.getGenericInfo().getAttributeChildrenDescriptions();
+      for (DomAttributeChildDescription attributeDescription : descriptions) {
+        final GenericAttributeValue attributeValue = attributeDescription.getDomAttributeValue(extension);
+        if (attributeValue == null || !DomUtil.hasXml(attributeValue)) continue;
+
+        final PsiElement declaration = attributeDescription.getDeclaration(extension.getManager().getProject());
+        if (declaration instanceof PsiField) {
+          PsiField psiField = (PsiField)declaration;
+          if (psiField.isDeprecated()) {
+            final Annotation annotation = holder.createAnnotation(attributeValue, HighlightSeverity.WARNING,
+                                                                  "Deprecated attribute '" + attributeDescription.getName() + "'");
+            annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+          }
+        }
       }
     }
 
diff --git a/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml b/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
index 6ea4867..5466b7e 100644
--- a/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
+++ b/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
@@ -6,7 +6,7 @@
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij.myPlugin">
-    <myExt <warning descr="'myOld' is deprecated">old</warning>="java.lang.Runnable" attr="value"/>
+    <myExt <warning descr="Deprecated attribute 'old'">old="java.lang.Runnable"</warning> attr="value"/>
   </extensions>
 
 </idea-plugin>
\ No newline at end of file
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
index 874360a..9846393 100644
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
@@ -16,6 +16,7 @@
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.remoteServer.agent.util.CloudGitApplication;
+import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
 import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
@@ -348,6 +349,11 @@
     };
   }
 
+  @Override
+  protected CloudLoggingHandler getLoggingHandler() {
+    return super.getLoggingHandler();
+  }
+
   protected void addGitRemote(CloudGitApplication application) throws ServerRuntimeException {
     doGitRemote(getRemoteName(), application, "add", CloudBundle.getText("failed.add.remote", getRemoteName()));
   }
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index 32d254f..dc12d0e 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -92,12 +92,13 @@
       <separator/>
     </group>
 
-    <action id="Git.CherryPick" class="git4idea.cherrypick.GitCherryPickAction" text="Cherry-Pick" icon="Git4ideaIcons.CherryPick"/>
+    <action id="Git.CherryPick" class="git4idea.cherrypick.GitCherryPickAction" icon="Git4ideaIcons.CherryPick"/>
     <action class="git4idea.actions.GitCheckoutRevisionAction" id="Git.CheckoutRevision" text="Checkout Revision"/>
-    <action class="git4idea.actions.GitCreateNewBranchAction" id="Git.CreateNewBranch" text="New Branch"
+    <action class="git4idea.actions.GitCreateNewBranchAction" id="Git.CreateNewBranch" text="New Branch..."
             description="Create new branch starting from the selected commit"/>
-    <action class="git4idea.actions.GitCreateTagAction" id="Git.CreateNewTag" text="New Tag"
+    <action class="git4idea.actions.GitCreateTagAction" id="Git.CreateNewTag" text="New Tag..."
             description="Create new tag pointing to this commit"/>
+    <action id="Git.Reset.In.Log" class="git4idea.reset.GitResetAction" text="Reset Current Branch to Here..." />
 
     <group id="Git.Log.ContextMenu">
       <separator/>
@@ -105,6 +106,8 @@
       <reference id="Git.CheckoutRevision"/>
       <reference id="Git.CreateNewBranch" />
       <reference id="Git.CreateNewTag" />
+      <separator/>
+      <reference id="Git.Reset.In.Log" />
       <add-to-group group-id="Vcs.Log.ContextMenu" />
     </group>
 
@@ -121,7 +124,9 @@
 
   <project-components>
     <component>
+      <interface-class>git4idea.repo.GitRepositoryManager</interface-class>
       <implementation-class>git4idea.repo.GitRepositoryManager</implementation-class>
+      <headless-implementation-class>git4idea.test.GitTestRepositoryManager</headless-implementation-class>
     </component>
   </project-components>
 
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index 5f56de5..4ff61fb 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -37,7 +37,6 @@
 import com.intellij.openapi.vcs.changes.Change;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vcs.changes.ChangeListManagerEx;
-import com.intellij.openapi.vcs.changes.FilePathsHelper;
 import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
 import com.intellij.openapi.vcs.vfs.AbstractVcsVirtualFile;
 import com.intellij.openapi.vfs.LocalFileSystem;
@@ -778,6 +777,8 @@
   /**
    * Returns absolute paths which have changed remotely comparing to the current branch, i.e. performs
    * <code>git diff --name-only master..origin/master</code>
+   * <p/>
+   * Paths are absolute, Git-formatted (i.e. with forward slashes).
    */
   @NotNull
   public static Collection<String> getPathsDiffBetweenRefs(@NotNull Git git, @NotNull GitRepository repository,
@@ -797,7 +798,7 @@
         continue;
       }
       final String path = repository.getRoot().getPath() + "/" + unescapePath(relative);
-      remoteChanges.add(FilePathsHelper.convertPath(path));
+      remoteChanges.add(path);
     }
     return remoteChanges;
   }
@@ -1024,4 +1025,14 @@
     ApplicationManager.getApplication().getMessageBus().syncPublisher(BatchFileChangeListener.TOPIC).batchChangeCompleted(project);
   }
 
+  @NotNull
+  public static String cleanupErrorPrefixes(@NotNull String msg) {
+    final String[] PREFIXES = { "fatal:", "error:" };
+    for (String prefix : PREFIXES) {
+      if (msg.startsWith(prefix)) {
+        return msg.substring(prefix.length()).trim();
+      }
+    }
+    return msg;
+  }
 }
diff --git a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
index 39cfb2a..83512de 100644
--- a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
+++ b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
@@ -15,77 +15,21 @@
  */
 package git4idea.actions;
 
-import com.intellij.dvcs.DvcsUtil;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
 import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogDataKeys;
-import git4idea.GitVcs;
+import com.intellij.openapi.vfs.VirtualFile;
 import git4idea.repo.GitRepository;
 import git4idea.repo.GitRepositoryManager;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
-import java.util.List;
-
-/**
- * @author Kirill Likhodedov
- */
-public abstract class GitLogSingleCommitAction extends DumbAwareAction {
-
-  private static final Logger LOG = Logger.getInstance(GitLogSingleCommitAction.class);
-
-  protected abstract void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit);
+public abstract class GitLogSingleCommitAction extends VcsLogSingleCommitAction<GitRepository> {
 
   @Override
-  public void actionPerformed(AnActionEvent e) {
-    Data data = Data.collect(e);
-    if (!data.isValid()) {
-      return;
-    }
-
-    List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
-    if (details.size() != 1) {
-      return;
-    }
-    VcsFullCommitDetails commit = details.get(0);
-
-    GitRepositoryManager repositoryManager = ServiceManager.getService(data.project, GitRepositoryManager.class);
-    final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
-    if (repository == null) {
-      DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, GitVcs.getInstance(data.project));
-      return;
-    }
-
-    actionPerformed(repository, commit);
-  }
-
-  @Override
-  public void update(AnActionEvent e) {
-    Data data = Data.collect(e);
-    boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1;
-    e.getPresentation().setVisible(data.isValid());
-    e.getPresentation().setEnabled(enabled);
-  }
-
-  private static class Data {
-    Project project;
-    VcsLog log;
-
-    static Data collect(AnActionEvent e) {
-      Data data = new Data();
-      data.project = e.getData(CommonDataKeys.PROJECT);
-      data.log = e.getData(VcsLogDataKeys.VSC_LOG);
-      return data;
-    }
-
-    boolean isValid() {
-      return project != null && log != null && DvcsUtil.logHasRootForVcs(log, GitVcs.getKey());
-    }
+  @Nullable
+  protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+    return ServiceManager.getService(project, GitRepositoryManager.class).getRepositoryForRoot(root);
   }
 
 }
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
index 7c2f77e..9147054 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
@@ -15,6 +15,7 @@
  */
 package git4idea.branch;
 
+import com.intellij.dvcs.repo.RepositoryUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
@@ -25,6 +26,9 @@
 import com.intellij.openapi.vcs.changes.Change;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import git4idea.GitLocalBranch;
 import git4idea.GitPlatformFacade;
 import git4idea.GitUtil;
 import git4idea.commands.Git;
@@ -32,6 +36,7 @@
 import git4idea.config.GitVcsSettings;
 import git4idea.repo.GitRepository;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
 
@@ -50,7 +55,7 @@
   @NotNull protected final Git myGit;
   @NotNull protected final GitBranchUiHandler myUiHandler;
   @NotNull private final Collection<GitRepository> myRepositories;
-  @NotNull protected final String myCurrentBranchOrRev;
+  @NotNull protected final Map<GitRepository, String> myCurrentHeads;
   private final GitVcsSettings mySettings;
 
   @NotNull private final Collection<GitRepository> mySuccessfulRepositories;
@@ -63,7 +68,13 @@
     myGit = git;
     myUiHandler = uiHandler;
     myRepositories = repositories;
-    myCurrentBranchOrRev = GitBranchUtil.getCurrentBranchOrRev(repositories);
+    myCurrentHeads = ContainerUtil.map2Map(repositories, new Function<GitRepository, Pair<GitRepository, String>>() {
+      @Override
+      public Pair<GitRepository, String> fun(GitRepository repository) {
+        GitLocalBranch currentBranch = repository.getCurrentBranch();
+        return Pair.create(repository, currentBranch == null ? repository.getCurrentRevision() : currentBranch.getName());
+      }
+    });
     mySuccessfulRepositories = new ArrayList<GitRepository>();
     myRemainingRepositories = new ArrayList<GitRepository>(myRepositories);
     mySettings = myFacade.getSettings(myProject);
@@ -220,13 +231,30 @@
   protected void updateRecentBranch() {
     if (getRepositories().size() == 1) {
       GitRepository repository = myRepositories.iterator().next();
-      mySettings.setRecentBranchOfRepository(repository.getRoot().getPath(), myCurrentBranchOrRev);
+      mySettings.setRecentBranchOfRepository(repository.getRoot().getPath(), myCurrentHeads.get(repository));
     }
     else {
-      mySettings.setRecentCommonBranch(myCurrentBranchOrRev);
+      String recentCommonBranch = getRecentCommonBranch();
+      if (recentCommonBranch != null) {
+        mySettings.setRecentCommonBranch(recentCommonBranch);
+      }
     }
   }
 
+  @Nullable
+  private String getRecentCommonBranch() {
+    String recentCommonBranch = null;
+    for (String branch : myCurrentHeads.values()) {
+      if (recentCommonBranch == null) {
+        recentCommonBranch = branch;
+      }
+      else if (!recentCommonBranch.equals(branch)) {
+        return null;
+      }
+    }
+    return recentCommonBranch;
+  }
+
   private void showUnmergedFilesDialogWithRollback() {
     boolean ok = myUiHandler.showUnmergedFilesMessageWithRollback(getOperationName(), getRollbackProposal());
     if (ok) {
@@ -340,4 +368,35 @@
 
     return Pair.create(allConflictingRepositories, affectedChanges);
   }
+
+  @NotNull
+  protected static String stringifyBranchesByRepos(@NotNull Map<GitRepository, String> heads) {
+    MultiMap<String, VirtualFile> grouped = groupByBranches(heads);
+    if (grouped.size() == 1) {
+      return grouped.keySet().iterator().next();
+    }
+    return StringUtil.join(grouped.entrySet(), new Function<Map.Entry<String, Collection<VirtualFile>>, String>() {
+      @Override
+      public String fun(Map.Entry<String, Collection<VirtualFile>> entry) {
+        String roots = StringUtil.join(entry.getValue(), new Function<VirtualFile, String>() {
+          @Override
+          public String fun(VirtualFile file) {
+            return file.getName();
+          }
+        }, ", ");
+        return entry.getKey() + " (in " + roots + ")";
+      }
+    }, "<br/>");
+  }
+
+  @NotNull
+  private static MultiMap<String, VirtualFile> groupByBranches(@NotNull Map<GitRepository, String> heads) {
+    MultiMap<String, VirtualFile> result = MultiMap.createLinked();
+    List<GitRepository> sortedRepos = RepositoryUtil.sortRepositories(heads.keySet());
+    for (GitRepository repo : sortedRepos) {
+      result.putValue(heads.get(repo), repo.getRoot());
+    }
+    return result;
+  }
+
 }
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
index 3b694c4..95546f0 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
@@ -22,6 +22,7 @@
 import git4idea.GitCommit;
 import git4idea.repo.GitRepository;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.List;
@@ -68,14 +69,15 @@
    * Shows the dialog proposing to execute the operation (checkout or merge) smartly, i.e. stash-execute-unstash.
    *
    * @param project
-   * @param changes         local changes that would be overwritten by checkout or merge.
-   * @param paths           paths reported by Git (in most cases this is covered by {@code changes}.
-   * @param operation       operation name: checkout or merge
-   * @param isForcePossible can the operation be executed force (force checkout is possible, force merge - not).
+   * @param changes          local changes that would be overwritten by checkout or merge.
+   * @param paths            paths reported by Git (in most cases this is covered by {@code changes}.
+   * @param operation        operation name: checkout or merge
+   * @param forceButtonTitle if the operation can be executed force (force checkout is possible),
+   *                         specify the title of the force button; otherwise (force merge is not possible) pass null.
    * @return the code of the decision.
    */
   int showSmartOperationDialog(@NotNull Project project, @NotNull List<Change> changes, @NotNull Collection<String> paths,
-                               @NotNull String operation, boolean isForcePossible);
+                               @NotNull String operation, @Nullable String forceButtonTitle);
 
   boolean showBranchIsNotFullyMergedDialog(@NotNull Project project, @NotNull Map<GitRepository, List<GitCommit>> history,
                                            @NotNull String unmergedBranch, @NotNull List<String> mergedToBranches,
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
index cea2b55..20e207d 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
@@ -172,7 +172,7 @@
 
   @Override
   public int showSmartOperationDialog(@NotNull Project project, @NotNull List<Change> changes, @NotNull Collection<String> paths,
-                                      @NotNull String operation, boolean isForcePossible) {
+                                      @NotNull String operation, @Nullable String forceButtonTitle) {
     JComponent fileBrowser;
     if (!changes.isEmpty()) {
       fileBrowser = new ChangesBrowserWithRollback(project, changes);
@@ -180,7 +180,7 @@
     else {
       fileBrowser = new GitSimplePathsBrowser(project, paths);
     }
-    return GitSmartOperationDialog.showAndGetAnswer(myProject, fileBrowser, operation, isForcePossible);
+    return GitSmartOperationDialog.showAndGetAnswer(myProject, fileBrowser, operation, forceButtonTitle);
   }
 
   @Override
diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
index 22e486e..cdc4f77 100644
--- a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
@@ -89,7 +89,7 @@
   protected String getRollbackProposal() {
     return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
            successfulRepositoriesJoined() +
-           "<br/>You may rollback (checkout back to " + myCurrentBranchOrRev + " and delete " + myNewBranchName + ") not to let branches diverge.";
+           "<br/>You may rollback (checkout previous branch back, and delete " + myNewBranchName + ") not to let branches diverge.";
   }
 
   @NotNull
@@ -104,7 +104,7 @@
     GitCompoundResult deleteResult = new GitCompoundResult(myProject);
     Collection<GitRepository> repositories = getSuccessfulRepositories();
     for (GitRepository repository : repositories) {
-      GitCommandResult result = myGit.checkout(repository, myCurrentBranchOrRev, null, true);
+      GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true);
       checkoutResult.append(repository, result);
       if (result.success()) {
         deleteResult.append(repository, myGit.branchDelete(repository, myNewBranchName, false));
@@ -113,7 +113,7 @@
     }
     if (checkoutResult.totalSuccess() && deleteResult.totalSuccess()) {
       VcsNotifier.getInstance(myProject).notifySuccess("Rollback successful", String
-        .format("Checked out %s and deleted %s on %s %s", code(myCurrentBranchOrRev), code(myNewBranchName),
+        .format("Checked out %s and deleted %s on %s %s", stringifyBranchesByRepos(myCurrentHeads), code(myNewBranchName),
                 StringUtil.pluralize("root", repositories.size()), successfulRepositoriesJoined()));
     }
     else {
diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
index 2441bf7..b772434 100644
--- a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
@@ -47,7 +47,7 @@
  */
 class GitCheckoutOperation extends GitBranchOperation {
 
-  public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to %s) not to let branches diverge.";
+  public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to previous branch) not to let branches diverge.";
 
   @NotNull private final String myStartPointReference;
   @Nullable private final String myNewBranch;
@@ -115,12 +115,14 @@
   private boolean smartCheckoutOrNotify(@NotNull GitRepository repository,
                                         @NotNull GitMessageWithFilesDetector localChangesOverwrittenByCheckout) {
     Pair<List<GitRepository>, List<Change>> conflictingRepositoriesAndAffectedChanges =
-      getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByCheckout, myCurrentBranchOrRev, myStartPointReference);
+      getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByCheckout, myCurrentHeads.get(repository),
+                                                   myStartPointReference);
     List<GitRepository> allConflictingRepositories = conflictingRepositoriesAndAffectedChanges.getFirst();
     List<Change> affectedChanges = conflictingRepositoriesAndAffectedChanges.getSecond();
 
     Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), localChangesOverwrittenByCheckout.getRelativeFilePaths());
-    int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "checkout", true);
+    int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "checkout",
+                                                                     "&Force Checkout");
     if (smartCheckoutDecision == GitSmartOperationDialog.SMART_EXIT_CODE) {
       boolean smartCheckedOutSuccessfully = smartCheckout(allConflictingRepositories, myStartPointReference, myNewBranch, getIndicator());
       if (smartCheckedOutSuccessfully) {
@@ -153,8 +155,7 @@
   @Override
   protected String getRollbackProposal() {
     return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
-           successfulRepositoriesJoined() +
-           "<br/>" + String.format(ROLLBACK_PROPOSAL_FORMAT, myCurrentBranchOrRev);
+           successfulRepositoriesJoined() + "<br/>" + ROLLBACK_PROPOSAL_FORMAT;
   }
 
   @NotNull
@@ -168,7 +169,7 @@
     GitCompoundResult checkoutResult = new GitCompoundResult(myProject);
     GitCompoundResult deleteResult = new GitCompoundResult(myProject);
     for (GitRepository repository : getSuccessfulRepositories()) {
-      GitCommandResult result = myGit.checkout(repository, myCurrentBranchOrRev, null, true);
+      GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true);
       checkoutResult.append(repository, result);
       if (result.success() && myNewBranch != null) {
         /*
@@ -183,7 +184,7 @@
     if (!checkoutResult.totalSuccess() || !deleteResult.totalSuccess()) {
       StringBuilder message = new StringBuilder();
       if (!checkoutResult.totalSuccess()) {
-        message.append("Errors during checking out ").append(myCurrentBranchOrRev).append(": ");
+        message.append("Errors during checkout: ");
         message.append(checkoutResult.getErrorOutputWithReposIndication());
       }
       if (!deleteResult.totalSuccess()) {
diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
index d3501ca..1dba1e0 100644
--- a/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
@@ -68,7 +68,7 @@
       else if (notFullyMergedDetector.hasHappened()) {
         String baseBranch = notMergedToUpstreamDetector.getBaseBranch();
         if (baseBranch == null) { // GitBranchNotMergedToUpstreamDetector didn't happen
-          baseBranch = myCurrentBranchOrRev;
+          baseBranch = myCurrentHeads.get(repository);
         }
 
         Collection<GitRepository> remainingRepositories = getRemainingRepositories();
diff --git a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
index 89a50cf..1b8f382 100644
--- a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
@@ -34,6 +34,7 @@
 import git4idea.merge.GitMergeCommittingConflictResolver;
 import git4idea.merge.GitMerger;
 import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
 import git4idea.util.GitPreservingProcess;
 import org.jetbrains.annotations.NotNull;
 
@@ -189,12 +190,13 @@
   private boolean proposeSmartMergePerformAndNotify(@NotNull GitRepository repository,
                                           @NotNull GitMessageWithFilesDetector localChangesOverwrittenByMerge) {
     Pair<List<GitRepository>, List<Change>> conflictingRepositoriesAndAffectedChanges =
-      getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByMerge, myCurrentBranchOrRev, myBranchToMerge);
+      getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByMerge, myCurrentHeads.get(repository),
+                                                   myBranchToMerge);
     List<GitRepository> allConflictingRepositories = conflictingRepositoriesAndAffectedChanges.getFirst();
     List<Change> affectedChanges = conflictingRepositoriesAndAffectedChanges.getSecond();
 
     Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), localChangesOverwrittenByMerge.getRelativeFilePaths());
-    int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "merge", false);
+    int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "merge", null);
     if (smartCheckoutDecision == GitSmartOperationDialog.SMART_EXIT_CODE) {
       return doSmartMerge(allConflictingRepositories);
     }
@@ -322,7 +324,7 @@
 
   @NotNull
   private GitCommandResult rollback(@NotNull GitRepository repository) {
-    return myGit.resetHard(repository, myCurrentRevisionsBeforeMerge.get(repository));
+    return myGit.reset(repository, GitResetMode.HARD, myCurrentRevisionsBeforeMerge.get(repository));
   }
 
   @NotNull
@@ -339,7 +341,8 @@
   @NotNull
   @Override
   public String getSuccessMessage() {
-    return String.format("Merged <b><code>%s</code></b> to <b><code>%s</code></b>", myBranchToMerge, myCurrentBranchOrRev);
+    return String.format("Merged <b><code>%s</code></b> to <b><code>%s</code></b>",
+                         myBranchToMerge, stringifyBranchesByRepos(myCurrentHeads));
   }
 
   @NotNull
diff --git a/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java b/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
index 9c2ef4a..4f50730 100644
--- a/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
+++ b/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
@@ -24,6 +24,7 @@
 import com.intellij.util.ui.UIUtil;
 import git4idea.GitPlatformFacade;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.event.ActionEvent;
@@ -44,18 +45,18 @@
 
   @NotNull private final JComponent myFileBrowser;
   @NotNull private final String myOperationTitle;
-  private final boolean myShowForceButton;
+  @Nullable private final String myForceButton;
 
   /**
    * Shows the dialog with the list of local changes preventing merge/checkout and returns the dialog exit code.
    */
   static int showAndGetAnswer(@NotNull final Project project, @NotNull final JComponent fileBrowser,
-                              @NotNull final String operationTitle, final boolean showForceButton) {
+                              @NotNull final String operationTitle, @Nullable final String forceButtonTitle) {
     final AtomicInteger exitCode = new AtomicInteger();
     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
       @Override
       public void run() {
-        GitSmartOperationDialog dialog = new GitSmartOperationDialog(project, fileBrowser, operationTitle, showForceButton);
+        GitSmartOperationDialog dialog = new GitSmartOperationDialog(project, fileBrowser, operationTitle, forceButtonTitle);
         ServiceManager.getService(project, GitPlatformFacade.class).showDialog(dialog);
         exitCode.set(dialog.getExitCode());
       }
@@ -64,11 +65,11 @@
   }
 
   private GitSmartOperationDialog(@NotNull Project project, @NotNull JComponent fileBrowser, @NotNull String operationTitle,
-                                  boolean showForceButton) {
+                                  @Nullable String forceButton) {
     super(project);
     myFileBrowser = fileBrowser;
     myOperationTitle = operationTitle;
-    myShowForceButton = showForceButton;
+    myForceButton = forceButton;
     String capitalizedOperation = capitalize(myOperationTitle);
     setTitle("Git " + capitalizedOperation + " Problem");
 
@@ -82,8 +83,8 @@
   @NotNull
   @Override
   protected Action[] createLeftSideActions() {
-    if (myShowForceButton) {
-      return new Action[]  {new ForceCheckoutAction(myOperationTitle) };
+    if (myForceButton != null) {
+      return new Action[]{new ForceCheckoutAction(myForceButton, myOperationTitle)};
     }
     return new Action[0];
   }
@@ -110,8 +111,8 @@
 
   private class ForceCheckoutAction extends AbstractAction {
     
-    ForceCheckoutAction(@NotNull String operationTitle) {
-      super("&Force " + capitalize(operationTitle));
+    ForceCheckoutAction(@NotNull String buttonTitle, @NotNull String operationTitle) {
+      super(buttonTitle);
       putValue(Action.SHORT_DESCRIPTION, capitalize(operationTitle) + " and overwrite local changes");
     }
     
diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
index f1ab1d4..31e731f 100644
--- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
+++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
@@ -22,7 +22,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.*;
 import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.ChangesUtil;
 import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
 import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
 import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary;
@@ -199,13 +199,7 @@
     final Collection<Change> changes = commit.getChanges();
     if (changes.size() == 1) {
       Change change = changes.iterator().next();
-      ContentRevision revision = change.getAfterRevision();
-      if (revision == null) {
-        revision = change.getBeforeRevision();
-      }
-      assert revision != null : "Revision can't be null in " + change;
-      FilePath filePathInRevision = revision.getFile();
-      return Pair.create(commit, filePathInRevision);
+      return Pair.create(commit, ChangesUtil.getFilePath(change));
     }
     for (Change change : changes) {
       if (change.getAfterRevision() != null && FileUtil.filesEqual(filePath.getIOFile(), change.getAfterRevision().getFile().getIOFile())) {
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index 3bb008a..448dd25 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -226,10 +226,7 @@
   @NotNull
   private static VcsException cleanupExceptionText(VcsException original) {
     String msg = original.getMessage();
-    final String FATAL_PREFIX = "fatal:";
-    if (msg.startsWith(FATAL_PREFIX)) {
-      msg = msg.substring(FATAL_PREFIX.length());
-    }
+    msg = GitUtil.cleanupErrorPrefixes(msg);
     final String DURING_EXECUTING_SUFFIX = GitSimpleHandler.DURING_EXECUTING_ERROR_MESSAGE;
     int suffix = msg.indexOf(DURING_EXECUTING_SUFFIX);
     if (suffix > 0) {
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java b/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
index e46e98a..ac9834e 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
@@ -35,7 +35,7 @@
       if (at < 0) {
         return author;
       }
-      int email = author.substring(0, at).lastIndexOf(' ');
+      int email = author.lastIndexOf(' ', at - 1);
       if (email < 0) {
         return author;
       }
diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
index aa3e1e4..b4250a0 100644
--- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
+++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
@@ -49,6 +49,8 @@
  * @author Kirill Likhodedov
  */
 public class GitCherryPickAction extends DumbAwareAction {
+
+  private static final String NAME = "Cherry-Pick";
   private static final Logger LOG = Logger.getInstance(GitCherryPickAction.class);
 
   @NotNull private final GitPlatformFacade myPlatformFacade;
@@ -56,7 +58,7 @@
   @NotNull private final Set<Hash> myIdsInProgress;
 
   public GitCherryPickAction() {
-    super("Cherry-pick", "Cherry-pick", Git4ideaIcons.CherryPick);
+    super(NAME, null, Git4ideaIcons.CherryPick);
     myGit = ServiceManager.getService(Git.class);
     myPlatformFacade = ServiceManager.getService(GitPlatformFacade.class);
     myIdsInProgress = ContainerUtil.newHashSet();
@@ -81,9 +83,8 @@
     new Task.Backgroundable(project, "Cherry-picking", false) {
       public void run(@NotNull ProgressIndicator indicator) {
         try {
-          boolean autoCommit = GitVcsSettings.getInstance(myProject).isAutoCommitOnCherryPick();
           Map<GitRepository, List<VcsFullCommitDetails>> commitsInRoots = sortCommits(groupCommitsByRoots(project, commits));
-          new GitCherryPicker(myProject, myGit, myPlatformFacade, autoCommit).cherryPick(commitsInRoots);
+          new GitCherryPicker(project, myGit, myPlatformFacade, isAutoCommit(project)).cherryPick(commitsInRoots);
         }
         finally {
           ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -130,15 +131,21 @@
     return groupedCommits;
   }
 
+  private static boolean isAutoCommit(@NotNull Project project) {
+    return GitVcsSettings.getInstance(project).isAutoCommitOnCherryPick();
+  }
+
   @Override
   public void update(AnActionEvent e) {
     super.update(e);
-    final VcsLog log = getVcsLog(e);
-    if (log != null && !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
+    VcsLog log = getVcsLog(e);
+    Project project = getEventProject(e);
+    if (project == null || log == null || !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
       e.getPresentation().setEnabledAndVisible(false);
     }
     else {
       e.getPresentation().setEnabled(enabled(e));
+      e.getPresentation().setText(isAutoCommit(project) ? NAME : NAME + "...");
     }
   }
 
diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java
index 284ccc1..830f73b 100644
--- a/plugins/git4idea/src/git4idea/commands/Git.java
+++ b/plugins/git4idea/src/git4idea/commands/Git.java
@@ -22,6 +22,7 @@
 import git4idea.GitCommit;
 import git4idea.push.GitPushSpec;
 import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -93,7 +94,8 @@
   GitCommandResult branchCreate(@NotNull GitRepository repository, @NotNull String branchName);
 
   @NotNull
-  GitCommandResult resetHard(@NotNull GitRepository repository, @NotNull String revision);
+  GitCommandResult reset(@NotNull GitRepository repository, @NotNull GitResetMode mode, @NotNull String target,
+                         @NotNull GitLineHandlerListener... listeners);
 
   @NotNull
   GitCommandResult resetMerge(@NotNull GitRepository repository, @Nullable String revision);
diff --git a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
index f89a489..0683d73 100644
--- a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
+++ b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
@@ -16,10 +16,14 @@
 package git4idea.commands;
 
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import git4idea.GitUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -64,9 +68,10 @@
 
   @NotNull
   public String getErrorOutputAsHtmlString() {
-    return StringUtil.join(myErrorOutput, "<br/>");
+    return StringUtil.join(cleanup(myErrorOutput), "<br/>");
   }
-  
+
+  @NotNull
   public String getErrorOutputAsJoinedString() {
     return StringUtil.join(myErrorOutput, "\n");
   }
@@ -90,4 +95,14 @@
     return false; // will be implemented later
   }
 
+  @NotNull
+  private static Collection<String> cleanup(@NotNull Collection<String> errorOutput) {
+    return ContainerUtil.map(errorOutput, new Function<String, String>() {
+      @Override
+      public String fun(String errorMessage) {
+        return GitUtil.cleanupErrorPrefixes(errorMessage);
+      }
+    });
+  }
+
 }
diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java
index 3350b74..c2d85b7 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java
@@ -18,7 +18,6 @@
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
@@ -103,7 +102,6 @@
 
   private long myStartTime; // git execution start timestamp
   private static final long LONG_TIME = 10 * 1000;
-  @Nullable private ModalityState myState;
   @Nullable private String myUrl;
   private boolean myHttpAuthFailed;
 
@@ -423,7 +421,7 @@
       }
       else {
         LOG.debug("cd " + myWorkingDirectory);
-        LOG.debug(printableCommandLine());
+        LOG.debug("[" + myWorkingDirectory.getName() + "] " + printableCommandLine());
       }
 
       // setup environment
@@ -431,7 +429,7 @@
       if (remoteProtocol == GitRemoteProtocol.SSH && myProjectSettings.isIdeaSsh()) {
         GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class);
         myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath());
-        myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject, myState));
+        myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject));
         myEnvironmentCleanedUp = false;
         myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(myHandlerNo));
         int port = ssh.getXmlRcpPort();
@@ -458,7 +456,7 @@
         GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class);
         myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath());
         assert myUrl != null : "myUrl can't be null here";
-        GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myState, myCommand, myUrl);
+        GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, myUrl);
         myHandlerNo = service.registerHandler(httpAuthenticator);
         myEnvironmentCleanedUp = false;
         myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHandlerNo));
@@ -474,7 +472,9 @@
       startHandlingStreams();
     }
     catch (Throwable t) {
-      LOG.error(t);
+      if (!ApplicationManager.getApplication().isUnitTestMode() || !myProject.isDisposed()) {
+        LOG.error(t); // will surely happen if called during unit test disposal, because the working dir is simply removed then
+      }
       cleanupEnv();
       myListeners.getMulticaster().startFailed(t);
     }
@@ -715,10 +715,6 @@
     myResumeAction.run();
   }
 
-  public void setModalityState(@Nullable ModalityState state) {
-    myState = state;
-  }
-
   /**
    * @return true if the command line is too big
    */
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
index 69be489..7125823 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
@@ -15,10 +15,8 @@
  */
 package git4idea.commands;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 import org.jetbrains.git4idea.http.GitAskPassApp;
 import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler;
 import org.jetbrains.git4idea.ssh.GitXmlRpcHandlerService;
@@ -47,8 +45,7 @@
    * Creates new {@link GitHttpAuthenticator} that will be requested to handle username and password requests from Git.
    */
   @NotNull
-  public abstract GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state,
-                                                           @NotNull GitCommand command, @NotNull String url);
+  public abstract GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url);
 
   /**
    * Internal handler implementation class, it is made public to be accessible via XML RPC.
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
index 06374bf..cda188d 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
@@ -15,10 +15,8 @@
  */
 package git4idea.commands;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * @author Kirill Likhodedov
@@ -27,9 +25,8 @@
 
   @Override
   @NotNull
-  public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
-                                                  @NotNull String url) {
-    return new GitHttpGuiAuthenticator(project, state, command, url);
+  public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
+    return new GitHttpGuiAuthenticator(project, command, url);
   }
 
 }
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
index e0312e5..c5931f9 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
@@ -57,7 +57,6 @@
   private static final Class<GitHttpAuthenticator> PASS_REQUESTER = GitHttpAuthenticator.class;
 
   @NotNull  private final Project myProject;
-  @Nullable private final ModalityState myModalityState;
   @NotNull  private final String myTitle;
   @NotNull private final String myUrlFromCommand;
 
@@ -69,10 +68,8 @@
   @Nullable private GitHttpAuthDataProvider myDataProvider;
   private boolean myWasCancelled;
 
-  GitHttpGuiAuthenticator(@NotNull Project project, @Nullable ModalityState modalityState, @NotNull GitCommand command,
-                          @NotNull String url) {
+  GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
     myProject = project;
-    myModalityState = modalityState;
     myTitle = "Git " + StringUtil.capitalize(command.name());
     myUrlFromCommand = url;
   }
@@ -87,7 +84,7 @@
       return "";
     }
     url = adjustUrl(url);
-    Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
+    Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
     if (authData != null && authData.second.getPassword() != null) {
       String password = authData.second.getPassword();
       myDataProvider = authData.first;
@@ -97,7 +94,7 @@
 
     String prompt = "Enter the password for " + url;
     myPasswordKey = url;
-    String password = PasswordSafePromptDialog.askPassword(myProject, myModalityState, myTitle, prompt, PASS_REQUESTER, url, false, null);
+    String password = PasswordSafePromptDialog.askPassword(myProject, myTitle, prompt, PASS_REQUESTER, url, false, null);
     if (password == null) {
       myWasCancelled = true;
       return "";
@@ -114,7 +111,7 @@
   @NotNull
   public String askUsername(@NotNull String url) {
     url = adjustUrl(url);
-    Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
+    Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
     String login = null;
     String password = null;
     if (authData != null) {
@@ -152,7 +149,7 @@
         dialog.set(new AuthDialog(myProject, myTitle, "Enter credentials for " + url, login, null, true));
         dialog.get().show();
       }
-    }, myModalityState == null ? ModalityState.defaultModalityState() : myModalityState);
+    }, ModalityState.any());
     return dialog.get();
   }
 
@@ -223,10 +220,10 @@
 
   // return the first that knows username + password; otherwise return the first that knows just the username
   @Nullable
-  private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+  private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url) {
     Pair<GitHttpAuthDataProvider, AuthData> candidate = null;
     for (GitHttpAuthDataProvider provider : getProviders()) {
-      AuthData data = provider.getAuthData(url, modalityState);
+      AuthData data = provider.getAuthData(url);
       if (data != null) {
         Pair<GitHttpAuthDataProvider, AuthData> pair = Pair.create(provider, data);
         if (data.getPassword() != null) {
@@ -268,12 +265,12 @@
 
     @Nullable
     @Override
-    public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+    public AuthData getAuthData(@NotNull String url) {
       String userName = getUsername(url);
       String key = makeKey(url, userName);
       final PasswordSafe passwordSafe = PasswordSafe.getInstance();
       try {
-        String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key, modalityState);
+        String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key);
         return new AuthData(StringUtil.notNullize(userName), password);
       }
       catch (PasswordSafeException e) {
diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java
index c873e71..09e254f 100644
--- a/plugins/git4idea/src/git4idea/commands/GitImpl.java
+++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java
@@ -32,6 +32,7 @@
 import git4idea.push.GitPushSpec;
 import git4idea.repo.GitRemote;
 import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -338,20 +339,26 @@
 
   @Override
   @NotNull
-  public GitCommandResult resetHard(@NotNull GitRepository repository, @NotNull String revision) {
-    final GitLineHandler handler = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.RESET);
-    handler.addParameters("--hard", revision);
-    return run(handler);
+  public GitCommandResult reset(@NotNull GitRepository repository, @NotNull GitResetMode mode, @NotNull String target,
+                                @NotNull GitLineHandlerListener... listeners) {
+    return reset(repository, mode.getArgument(), target, listeners);
   }
 
   @Override
   @NotNull
   public GitCommandResult resetMerge(@NotNull GitRepository repository, @Nullable String revision) {
+    return reset(repository, "--merge", revision);
+  }
+
+  @NotNull
+  private static GitCommandResult reset(@NotNull GitRepository repository, @NotNull String argument, @Nullable String target,
+                                        @NotNull GitLineHandlerListener... listeners) {
     final GitLineHandler handler = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.RESET);
-    handler.addParameters("--merge");
-    if (revision != null) {
-      handler.addParameters(revision);
+    handler.addParameters(argument);
+    if (target != null) {
+      handler.addParameters(target);
     }
+    addListeners(handler, listeners);
     return run(handler);
   }
 
diff --git a/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java b/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
index b62f128..e9d8df8 100644
--- a/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
+++ b/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
@@ -40,6 +40,13 @@
     ".*Your local changes to '(.*)' would be overwritten by merge.*"
   );
 
+  private static final Pattern[] RESET_PATTERNS = new Pattern[]{Pattern.compile(
+    ".*Entry '(.*)' not uptodate. Cannot merge.*"
+  ),
+  Pattern.compile(
+    ".*Entry '(.*)' would be overwritten by merge.*"
+  )};
+
   // common for checkout and merge
   public static final Event NEW_PATTERN = new Event(
     "Your local changes to the following files would be overwritten by",
@@ -49,17 +56,18 @@
 
   public enum Operation {
     CHECKOUT(OLD_CHECKOUT_PATTERN),
-    MERGE(OLD_MERGE_PATTERN);
+    MERGE(OLD_MERGE_PATTERN),
+    RESET(RESET_PATTERNS);
 
-    @NotNull private final Pattern myPattern;
+    @NotNull private final Pattern[] myPatterns;
 
-    Operation(@NotNull Pattern pattern) {
-      myPattern = pattern;
+    Operation(@NotNull Pattern... patterns) {
+      myPatterns = patterns;
     }
 
     @NotNull
-    public Pattern getPattern() {
-      return myPattern;
+    Pattern[] getPatterns() {
+      return myPatterns;
     }
   }
 
@@ -71,10 +79,13 @@
   @Override
   public void onLineAvailable(@NotNull String line, @NotNull Key outputType) {
     super.onLineAvailable(line, outputType);
-    Matcher m = myOperation.getPattern().matcher(line);
-    if (m.matches()) {
-      myMessageDetected = true;
-      myAffectedFiles.add(m.group(1));
+    for (Pattern pattern : myOperation.getPatterns()) {
+      Matcher m = pattern.matcher(line);
+      if (m.matches()) {
+        myMessageDetected = true;
+        myAffectedFiles.add(m.group(1));
+        break;
+      }
     }
   }
 }
diff --git a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
index 9822704..4d1c134 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
@@ -16,7 +16,6 @@
 package git4idea.commands;
 
 import com.intellij.ide.passwordSafe.ui.PasswordSafePromptDialog;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
@@ -39,17 +38,9 @@
  */
 public class GitSSHGUIHandler {
   @Nullable private final Project myProject;
-  @Nullable private final ModalityState myState;
 
-  /**
-   * A constructor
-   *
-   * @param project a project to use
-   * @param state   modality state using which any prompts initiated by the git process should be shown in the UI.
-   */
-  GitSSHGUIHandler(@Nullable Project project, @Nullable ModalityState state) {
+  GitSSHGUIHandler(@Nullable Project project) {
     myProject = project;
-    myState = state;
   }
 
   public boolean verifyServerHostKey(final String hostname,
@@ -76,7 +67,7 @@
   @Nullable
   public String askPassphrase(final String username, final String keyPath, boolean resetPassword, final String lastError) {
     String error = processLastError(resetPassword, lastError);
-    return PasswordSafePromptDialog.askPassphrase(myProject, myState, GitBundle.getString("ssh.ask.passphrase.title"),
+    return PasswordSafePromptDialog.askPassphrase(myProject, GitBundle.getString("ssh.ask.passphrase.title"),
                                                   GitBundle.message("ssh.askPassphrase.message", keyPath, username),
                                                   GitSSHGUIHandler.class, "PASSPHRASE:" + keyPath, resetPassword, error
     );
@@ -165,7 +156,7 @@
   @Nullable
   public String askPassword(final String username, boolean resetPassword, final String lastError) {
     String error = processLastError(resetPassword, lastError);
-    return PasswordSafePromptDialog.askPassword(myProject, myState, GitBundle.getString("ssh.password.title"),
+    return PasswordSafePromptDialog.askPassword(myProject, GitBundle.getString("ssh.password.title"),
                                                 GitBundle.message("ssh.password.message", username),
                                                 GitSSHGUIHandler.class, "PASSWORD:" + username, resetPassword, error);
   }
diff --git a/plugins/git4idea/src/git4idea/commands/GitTask.java b/plugins/git4idea/src/git4idea/commands/GitTask.java
index c22ce07..79f8e33 100644
--- a/plugins/git4idea/src/git4idea/commands/GitTask.java
+++ b/plugins/git4idea/src/git4idea/commands/GitTask.java
@@ -324,7 +324,6 @@
 
     @Override
     public final void run(@NotNull ProgressIndicator indicator) {
-      myHandler.setModalityState(indicator.getModalityState());
       myDelegate.run(indicator);
     }
 
diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
index 4f74f7c..1b58606 100644
--- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
+++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.components.*;
 import com.intellij.openapi.project.Project;
 import com.intellij.util.ArrayUtil;
+import git4idea.reset.GitResetMode;
 import git4idea.ui.branch.GitBranchSyncSetting;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,7 @@
     public String RECENT_COMMON_BRANCH = null;
     public boolean AUTO_COMMIT_ON_CHERRY_PICK = false;
     public boolean WARN_ABOUT_CRLF = true;
+    public GitResetMode RESET_MODE = null;
   }
 
   public GitVcsSettings(GitVcsApplicationSettings appSettings) {
@@ -177,6 +179,15 @@
     myState.WARN_ABOUT_CRLF = warn;
   }
 
+  @Nullable
+  public GitResetMode getResetMode() {
+    return myState.RESET_MODE;
+  }
+
+  public void setResetMode(@NotNull GitResetMode mode) {
+    myState.RESET_MODE = mode;
+  }
+
   /**
    * Provides migration from project settings.
    * This method is to be removed in IDEA 13: it should be moved to {@link GitVcsApplicationSettings}
diff --git a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
index 87edd30..a6488d4 100644
--- a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
+++ b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
@@ -22,25 +22,22 @@
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogBuilder;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.ui.popup.ListPopup;
-import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.Change;
 import com.intellij.openapi.vcs.changes.ContentRevision;
-import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
-import com.intellij.openapi.vcs.history.CurrentRevision;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
 import com.intellij.openapi.vcs.history.DiffFromHistoryHandler;
 import com.intellij.openapi.vcs.history.VcsFileRevision;
-import com.intellij.openapi.vcs.history.VcsHistoryUtil;
 import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
 import git4idea.GitFileRevision;
 import git4idea.GitRevisionNumber;
 import git4idea.GitUtil;
@@ -67,71 +64,59 @@
  *
  * @author Kirill Likhodedov
  */
-public class GitDiffFromHistoryHandler implements DiffFromHistoryHandler {
+public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFileRevision> {
   
   private static final Logger LOG = Logger.getInstance(GitDiffFromHistoryHandler.class);
 
-  @NotNull private final Project myProject;
   @NotNull private final Git myGit;
   @NotNull private final GitRepositoryManager myRepositoryManager;
 
   public GitDiffFromHistoryHandler(@NotNull Project project) {
-    myProject = project;
+    super(project);
     myGit = ServiceManager.getService(project, Git.class);
     myRepositoryManager = GitUtil.getRepositoryManager(project);
   }
 
   @Override
-  public void showDiffForOne(@NotNull AnActionEvent e, @NotNull FilePath filePath,
-                             @NotNull VcsFileRevision previousRevision, @NotNull VcsFileRevision revision) {
+  public void showDiffForOne(@NotNull AnActionEvent e,
+                             @NotNull FilePath filePath,
+                             @NotNull VcsFileRevision previousRevision,
+                             @NotNull VcsFileRevision revision) {
     GitFileRevision rev = (GitFileRevision)revision;
     Collection<String> parents = rev.getParents();
     if (parents.size() < 2) {
-      doShowDiff(filePath, previousRevision, revision, false);
+      super.showDiffForOne(e, filePath, previousRevision, revision);
     }
     else { // merge 
       showDiffForMergeCommit(e, filePath, rev, parents);
     }
   }
 
+  @NotNull
   @Override
-  public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
-    doShowDiff(filePath, revision1, revision2, true);
-  }
-
-  private void doShowDiff(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2,
-                          boolean autoSort) {
-    if (!filePath.isDirectory()) {
-      VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
-    }
-    else if (revision2 instanceof CurrentRevision) {
-      GitFileRevision left = (GitFileRevision)revision1;
-      showDiffForDirectory(filePath, left.getHash(), null);
-    }
-    else if (revision1.equals(VcsFileRevision.NULL)) {
-      GitFileRevision right = (GitFileRevision)revision2;
-      showDiffForDirectory(filePath, null, right.getHash());
-    }
-    else {
-      GitFileRevision left = (GitFileRevision)revision1;
-      GitFileRevision right = (GitFileRevision)revision2;
-      if (autoSort) {
-        Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
-        left = (GitFileRevision)pair.first;
-        right = (GitFileRevision)pair.second;
-      }
-      showDiffForDirectory(filePath, left.getHash(), right.getHash());
-    }
-  }
-
-  private void showDiffForDirectory(@NotNull final FilePath path, @Nullable final String hash1, @Nullable final String hash2) {
+  protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull GitFileRevision rev1, @Nullable GitFileRevision rev2)
+    throws VcsException {
     GitRepository repository = getRepository(path);
-    calculateDiffInBackground(repository, path, hash1, hash2, new Consumer<List<Change>>() {
-      @Override
-      public void consume(List<Change> changes) {
-        showDirDiffDialog(path, hash1, hash2, changes);
-      }
-    });
+    String hash1 = rev1.getHash();
+    String hash2 = rev2 != null ? rev2.getHash() : null;
+
+    return ContainerUtil
+      .newArrayList(GitChangeUtils.getDiff(repository.getProject(), repository.getRoot(), hash1, hash2, Collections.singletonList(path)));
+  }
+
+  @NotNull
+  @Override
+  protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull GitFileRevision rev) throws VcsException {
+    GitRepository repository = getRepository(path);
+
+    return ContainerUtil.newArrayList(
+      GitChangeUtils.getRevisionChanges(repository.getProject(), repository.getRoot(), rev.getHash(), false, true, true).getChanges());
+  }
+
+  @NotNull
+  @Override
+  protected String getPresentableName(@NotNull GitFileRevision revision) {
+    return GitUtil.getShortHash(revision.getHash());
   }
 
   @NotNull
@@ -141,63 +126,6 @@
     return repository;
   }
 
-  // hash1 == null => hash2 is the initial commit
-  // hash2 == null => comparing hash1 with local
-  private void calculateDiffInBackground(@NotNull final GitRepository repository, @NotNull final FilePath path,
-                                         @Nullable  final String hash1, @Nullable final String hash2,
-                                         final Consumer<List<Change>> successHandler) {
-    new Task.Backgroundable(myProject, "Comparing revisions...") {
-      private List<Change> myChanges;
-      @Override
-      public void run(@NotNull ProgressIndicator indicator) {
-        try {
-          if (hash1 != null) {
-            // diff
-            myChanges = new ArrayList<Change>(GitChangeUtils.getDiff(repository.getProject(), repository.getRoot(), hash1, hash2,
-                                                                     Collections.singletonList(path)));
-          }
-          else {
-            // show the initial commit
-            myChanges = new ArrayList<Change>(GitChangeUtils.getRevisionChanges(repository.getProject(), repository.getRoot(), hash2, false,
-                                                                                true, true).getChanges());
-          }
-        }
-        catch (VcsException e) {
-          showError(e, "Error during requesting diff for directory");
-        }
-      }
-
-      @Override
-      public void onSuccess() {
-        successHandler.consume(myChanges);
-      }
-    }.queue();
-  }
-
-  private void showDirDiffDialog(@NotNull FilePath path, @Nullable String hash1, @Nullable String hash2, @NotNull List<Change> diff) {
-    DialogBuilder dialogBuilder = new DialogBuilder(myProject);
-    String title;
-    if (hash2 != null) {
-      if (hash1 != null) {
-        title = String.format("Difference between %s and %s in %s", GitUtil.getShortHash(hash1), GitUtil.getShortHash(hash2), path.getName());
-      }
-      else {
-        title = String.format("Initial commit %s in %s", GitUtil.getShortHash(hash2), path.getName());
-      }
-    }
-    else {
-      LOG.assertTrue(hash1 != null, "hash1 and hash2 can't both be null. Path: " + path);
-      title = String.format("Difference between %s and local version in %s", GitUtil.getShortHash(hash1), path.getName());
-    }
-    dialogBuilder.setTitle(title);
-    dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[] { new DialogBuilder.CloseDialogAction()});
-    final ChangesBrowser changesBrowser = new ChangesBrowser(myProject, null, diff, null, false, true,
-                                                             null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
-    changesBrowser.setChangesToDisplay(diff);
-    dialogBuilder.setCenterPanel(changesBrowser);
-    dialogBuilder.showNotModal();
-  }
-
   private void showDiffForMergeCommit(@NotNull final AnActionEvent event, @NotNull final FilePath filePath,
                                       @NotNull final GitFileRevision rev, @NotNull final Collection<String> parents) {
 
@@ -299,12 +227,6 @@
     return makeRevisionFromHash(currentRevisionPath, parentHash);
   }
 
-
-  private void showError(VcsException e, String logMessage) {
-    LOG.info(logMessage, e);
-    VcsBalloonProblemNotifier.showOverVersionControlView(this.myProject, e.getMessage(), MessageType.ERROR);
-  }
-
   private void showPopup(@NotNull AnActionEvent event, @NotNull GitFileRevision rev, @NotNull FilePath filePath,
                          @NotNull Collection<GitFileRevision> parents) {
     ActionGroup parentActions = createActionGroup(rev, filePath, parents);
diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
index 114b4be..8273c3e 100644
--- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
+++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
@@ -520,9 +520,19 @@
                                                  @NotNull VirtualFile root,
                                                  @NotNull final Consumer<VcsUser> userRegistry,
                                                  @NotNull List<String> parameters) throws VcsException {
+    List<TimedVcsCommit> collector = ContainerUtil.newArrayList();
+    readCommits(project, root, userRegistry, parameters, new CollectConsumer<TimedVcsCommit>(collector));
+    return collector;
+  }
+
+  public static void readCommits(@NotNull final Project project,
+                                                 @NotNull VirtualFile root,
+                                                 @NotNull final Consumer<VcsUser> userRegistry,
+                                                 @NotNull List<String> parameters,
+                                                 @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
     final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
     if (factory == null) {
-      return Collections.emptyList();
+      return;
     }
 
     final int COMMIT_BUFFER = 1000;
@@ -536,8 +546,6 @@
     h.addParameters(parameters);
     h.endOptions();
 
-    final List<TimedVcsCommit> commits = ContainerUtil.newArrayList();
-
     final StringBuilder record = new StringBuilder();
     final AtomicInteger records = new AtomicInteger();
     final Ref<VcsException> ex = new Ref<VcsException>();
@@ -560,7 +568,10 @@
             afterParseRemainder = line.substring(recordEnd + 1);
           }
           if (afterParseRemainder != null && records.incrementAndGet() > COMMIT_BUFFER) { // null means can't parse now
-            commits.addAll(parseCommit(parser, record, userRegistry, factory));
+            List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory);
+            for (TimedVcsCommit commit : commits) {
+              commitConsumer.consume(commit);
+            }
             record.setLength(0);
             record.append(afterParseRemainder);
           }
@@ -573,7 +584,10 @@
       @Override
       public void processTerminated(int exitCode) {
         try {
-          commits.addAll(parseCommit(parser, record, userRegistry, factory));
+          List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory);
+          for (TimedVcsCommit commit : commits) {
+            commitConsumer.consume(commit);
+          }
         }
         catch (Exception e) {
           ex.set(new VcsException(e));
@@ -589,7 +603,6 @@
     if (!ex.isNull()) {
       throw ex.get();
     }
-    return commits;
   }
 
   @NotNull
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index 79e7f70..03803fb 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -491,9 +491,9 @@
 git.push.active.close=Close
 
 git.unstash.clear.confirmation.message=Remove all stashes? This cannot be undone.
-git.unstash.clear.confirmation.title=Remove all stashes?
+git.unstash.clear.confirmation.title=Remove All Stashes?
 git.unstash.drop.confirmation.message=<html>Do you want to remove {0}?<br/>"{1}"</html>
-git.unstash.drop.confirmation.title=Remove stash {0}?
+git.unstash.drop.confirmation.title=Remove Stash {0}?
 
 branch.delete.not_fully_merged.description=The branch <code><b>{0}</b></code> is not fully merged to the branch <code><b>{1}</b></code>.<br/>Below is the list of unmerged commits.
 branch.delete.not_fully_merged.description.not_on_branch=You are currently not on the branch (<code>{1}</code>). <br>\
diff --git a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
index e469e61..054ed9f 100644
--- a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
+++ b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
@@ -27,49 +27,34 @@
 import java.util.*;
 
 class GitBekParentFixer {
-  @NotNull
-  private final static String MAGIC_TEXT = "Merge remote";
-  @NotNull
-  private final VcsLogFilterCollection MAGIC_FILTER = createVcsLogFilterCollection();
+  @NotNull private static final String MAGIC_TEXT = "Merge remote";
+  @NotNull private static final VcsLogFilterCollection MAGIC_FILTER = createVcsLogFilterCollection();
 
-  @NotNull
-  private final VirtualFile myRoot;
-  @NotNull
-  private final GitLogProvider myGitLogProvider;
-  @NotNull
-  private final List<TimedVcsCommit> myAllCommits;
+  @NotNull private final Set<Hash> myWrongCommits;
 
-  GitBekParentFixer(@NotNull VirtualFile root, @NotNull GitLogProvider gitLogProvider, @NotNull List<TimedVcsCommit> allCommits) {
-    myRoot = root;
-    myGitLogProvider = gitLogProvider;
-    myAllCommits = allCommits;
+  private GitBekParentFixer(@NotNull Set<Hash> wrongCommits) {
+    myWrongCommits = wrongCommits;
   }
 
   @NotNull
-  List<TimedVcsCommit> getCorrectCommits() throws VcsException {
-    if (!BekSorter.isBekEnabled())
-      return myAllCommits;
-
-    final Set<Hash> wrongCommits = getWrongCommits();
-    return new AbstractList<TimedVcsCommit>() {
-      @Override
-      public TimedVcsCommit get(int index) {
-        TimedVcsCommit commit = myAllCommits.get(index);
-        if (!wrongCommits.contains(commit.getId()))
-          return commit;
-
-        return reverseParents(commit);
-      }
-
-      @Override
-      public int size() {
-        return myAllCommits.size();
-      }
-    };
+  static GitBekParentFixer prepare(@NotNull VirtualFile root, @NotNull GitLogProvider provider) throws VcsException {
+    if (!BekSorter.isBekEnabled()) {
+      return new GitBekParentFixer(Collections.<Hash>emptySet());
+    }
+    return new GitBekParentFixer(getWrongCommits(provider, root));
   }
 
-  private Set<Hash> getWrongCommits() throws VcsException {
-    List<TimedVcsCommit> commitsMatchingFilter = myGitLogProvider.getCommitsMatchingFilter(myRoot, MAGIC_FILTER, -1);
+  @NotNull
+  TimedVcsCommit fixCommit(@NotNull TimedVcsCommit commit) {
+    if (!myWrongCommits.contains(commit.getId())) {
+      return commit;
+    }
+    return reverseParents(commit);
+  }
+
+  @NotNull
+  private static Set<Hash> getWrongCommits(@NotNull GitLogProvider provider, @NotNull VirtualFile root) throws VcsException {
+    List<TimedVcsCommit> commitsMatchingFilter = provider.getCommitsMatchingFilter(root, MAGIC_FILTER, -1);
     return ContainerUtil.map2Set(commitsMatchingFilter, new Function<TimedVcsCommit, Hash>() {
       @Override
       public Hash fun(TimedVcsCommit timedVcsCommit) {
diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
index ecc4709..435313f 100644
--- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java
+++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
@@ -154,18 +154,23 @@
     });
   }
 
-  @NotNull
   @Override
-  public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
+  public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+                            @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
     if (!isRepositoryReady(root)) {
-      return Collections.emptyList();
+      return;
     }
 
     List<String> parameters = new ArrayList<String>(GitHistoryUtils.LOG_ALL);
     parameters.add("--sparse");
 
-    List<TimedVcsCommit> timedVcsCommits = GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters);
-    return new GitBekParentFixer(root, this, timedVcsCommits).getCorrectCommits();
+    final GitBekParentFixer parentFixer = GitBekParentFixer.prepare(root, this);
+    GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters, new Consumer<TimedVcsCommit>() {
+      @Override
+      public void consume(TimedVcsCommit commit) {
+        commitConsumer.consume(parentFixer.fixCommit(commit));
+      }
+    });
   }
 
   @NotNull
diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
index f9d8085..68b1616 100644
--- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
+++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
@@ -44,66 +44,23 @@
 import java.util.Collections;
 import java.util.List;
 
-/**
- * Git pull dialog
- */
 public class GitPullDialog extends DialogWrapper {
 
   private static final Logger LOG = Logger.getInstance(GitPullDialog.class);
 
-  /**
-   * root panel
-   */
   private JPanel myPanel;
-  /**
-   * The selected git root
-   */
   private JComboBox myGitRoot;
-  /**
-   * Current branch label
-   */
   private JLabel myCurrentBranch;
-  /**
-   * The merge strategy
-   */
   private JComboBox myStrategy;
-  /**
-   * No commit option
-   */
   private JCheckBox myNoCommitCheckBox;
-  /**
-   * Squash commit option
-   */
   private JCheckBox mySquashCommitCheckBox;
-  /**
-   * No fast forward option
-   */
   private JCheckBox myNoFastForwardCheckBox;
-  /**
-   * Add log info to commit option
-   */
   private JCheckBox myAddLogInformationCheckBox;
-  /**
-   * Selected remote option
-   */
   private JComboBox myRemote;
-  /**
-   * The branch chooser
-   */
   private ElementsChooser<String> myBranchChooser;
-  /**
-   * The context project
-   */
   private final Project myProject;
   private final GitRepositoryManager myRepositoryManager;
 
-  /**
-   * A constructor
-   *
-   * @param project     a project to select
-   * @param roots       a git repository roots for the project
-   * @param defaultRoot a guessed default root
-   */
   public GitPullDialog(Project project, List<VirtualFile> roots, VirtualFile defaultRoot) {
     super(project, true);
     setTitle(GitBundle.getString("pull.title"));
@@ -138,9 +95,6 @@
     init();
   }
 
-  /**
-   * Validate dialog and enable buttons
-   */
   private void validateDialog() {
     String selectedRemote = getRemote();
     if (StringUtil.isEmptyOrSpaces(selectedRemote)) {
@@ -150,9 +104,6 @@
     setOKActionEnabled(myBranchChooser.getMarkedElements().size() != 0);
   }
 
-  /**
-   * @return a pull handler configured according to dialog options
-   */
   public GitLineHandler makeHandler(@NotNull String url) {
     GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.PULL);
     // ignore merge failure for the pull
@@ -232,9 +183,6 @@
     return branch.getName().startsWith(remote + "/");
   }
 
-  /**
-   * Update remotes for the git root
-   */
   private void updateRemotes() {
     GitRepository repository = getRepository();
     if (repository == null) {
@@ -331,39 +279,23 @@
     };
   }
 
-  /**
-   * @return a currently selected git root
-   */
   public VirtualFile gitRoot() {
     return (VirtualFile)myGitRoot.getSelectedItem();
   }
 
-
-  /**
-   * Create branch chooser
-   */
   private void createUIComponents() {
     myBranchChooser = new ElementsChooser<String>(true);
   }
 
-  /**
-   * {@inheritDoc}
-   */
   protected JComponent createCenterPanel() {
     return myPanel;
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getDimensionServiceKey() {
     return getClass().getName();
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getHelpId() {
     return "reference.VersionControl.Git.Pull";
diff --git a/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java b/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
index 281d69b..6c0860c 100644
--- a/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
+++ b/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
@@ -15,7 +15,6 @@
  */
 package git4idea.remote;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.util.AuthData;
 import org.jetbrains.annotations.NotNull;
@@ -32,7 +31,7 @@
   ExtensionPointName<GitHttpAuthDataProvider> EP_NAME = ExtensionPointName.create("Git4Idea.GitHttpAuthDataProvider");
 
   @Nullable
-  AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState);
+  AuthData getAuthData(@NotNull String url);
 
   void forgetPassword(@NotNull String url);
 
diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
index 29f2c4c..e401334 100644
--- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
+++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
@@ -34,7 +34,7 @@
 /**
  * @author Kirill Likhodedov
  */
-public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, Disposable {
+public class GitRepositoryImpl extends RepositoryImpl implements GitRepository {
 
   @NotNull private final GitPlatformFacade myPlatformFacade;
   @NotNull private final GitRepositoryReader myReader;
diff --git a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
index 0cf82d9..4ad12d8 100644
--- a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
+++ b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
@@ -237,9 +237,6 @@
         break;
       }
       String path = event.getPath();
-      if (path == null) {
-        continue;
-      }
       if (totalRefreshNeeded(path)) {
         allChanged = true;
       }
@@ -253,7 +250,7 @@
 
     // if index has changed, no need to refresh specific files - we get the full status of all files
     if (allChanged) {
-      LOG.info(String.format("GitUntrackedFilesHolder: Index has changed, marking %s recursively dirty", myRoot));
+      LOG.debug(String.format("GitUntrackedFilesHolder: Index has changed, marking %s recursively dirty", myRoot));
       myDirtyScopeManager.dirDirtyRecursively(myRoot);
       synchronized (LOCK) {
         myReady = false;
diff --git a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
new file mode 100644
index 0000000..5e2cb18
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+package git4idea.reset;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.components.JBRadioButton;
+import com.intellij.util.ui.GridBag;
+import com.intellij.util.ui.RadioButtonEnumModel;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.xml.util.XmlStringUtil;
+import git4idea.GitUtil;
+import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+import static com.intellij.dvcs.DvcsUtil.getShortRepositoryName;
+
+public class GitNewResetDialog extends DialogWrapper {
+
+  private static final String DIALOG_ID = "git.new.reset.dialog";
+  
+  @NotNull private final Project myProject;
+  @NotNull private final Map<GitRepository, VcsFullCommitDetails> myCommits;
+  @NotNull private final GitResetMode myDefaultMode;
+  @NotNull private final ButtonGroup myButtonGroup;
+
+  private RadioButtonEnumModel<GitResetMode> myEnumModel;
+
+  protected GitNewResetDialog(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> commits,
+                              @NotNull GitResetMode defaultMode) {
+    super(project);
+    myProject = project;
+    myCommits = commits;
+    myDefaultMode = defaultMode;
+    myButtonGroup = new ButtonGroup();
+
+    init();
+    setTitle("Git Reset");
+    setOKButtonText("Reset");
+    setOKButtonMnemonic('R');
+    setResizable(false);
+  }
+
+  @Nullable
+  @Override
+  protected JComponent createCenterPanel() {
+    JPanel panel = new JPanel(new GridBagLayout());
+    GridBag gb = new GridBag().
+      setDefaultAnchor(GridBagConstraints.LINE_START).
+      setDefaultInsets(0, UIUtil.DEFAULT_HGAP, UIUtil.LARGE_VGAP, 0);
+
+    String description = prepareDescription(myProject, myCommits);
+    panel.add(new JBLabel(XmlStringUtil.wrapInHtml(description)), gb.nextLine().next().coverLine());
+
+    String explanation = "This will reset the current branch head to the selected commit, <br/>" +
+                         "and update the working tree and the index according to the selected mode:";
+    panel.add(new JBLabel(XmlStringUtil.wrapInHtml(explanation), UIUtil.ComponentStyle.SMALL), gb.nextLine().next().coverLine());
+
+    for (GitResetMode mode : GitResetMode.values()) {
+      JBRadioButton button = new JBRadioButton(mode.getName());
+      button.setMnemonic(mode.getName().charAt(0));
+      myButtonGroup.add(button);
+      panel.add(button, gb.nextLine().next());
+      panel.add(new JBLabel(XmlStringUtil.wrapInHtml(mode.getDescription()), UIUtil.ComponentStyle.SMALL), gb.next());
+    }
+
+    myEnumModel = RadioButtonEnumModel.bindEnum(GitResetMode.class, myButtonGroup);
+    myEnumModel.setSelected(myDefaultMode);
+    return panel;
+  }
+
+  @Nullable
+  @Override
+  protected String getHelpId() {
+    return DIALOG_ID;
+  }
+
+  @NotNull
+  private static String prepareDescription(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> commits) {
+    if (commits.size() == 1 && !isMultiRepo(project)) {
+      Map.Entry<GitRepository, VcsFullCommitDetails> entry = commits.entrySet().iterator().next();
+      return String.format("%s -> %s", getSourceText(entry.getKey()), getTargetText(entry.getValue()));
+    }
+
+    StringBuilder desc = new StringBuilder("");
+    for (Map.Entry<GitRepository, VcsFullCommitDetails> entry : commits.entrySet()) {
+      GitRepository repository = entry.getKey();
+      VcsFullCommitDetails commit = entry.getValue();
+      desc.append(String.format("%s in %s -> %s<br/>", getSourceText(repository),
+                                getShortRepositoryName(repository), getTargetText(commit)));
+    }
+    return desc.toString();
+  }
+
+  @NotNull
+  private static String getTargetText(@NotNull VcsFullCommitDetails commit) {
+    String commitMessage = StringUtil.shortenTextWithEllipsis(commit.getSubject(), 20, 0);
+    return String.format("<code><b>%s</b> \"%s\"</code> by <code>%s</code>",
+                         commit.getId().toShortString(), commitMessage, commit.getAuthor().getName());
+  }
+
+  @NotNull
+  private static String getSourceText(@NotNull GitRepository repository) {
+    String currentRevision = repository.getCurrentRevision();
+    assert currentRevision != null;
+    String text = repository.getCurrentBranch() == null ?
+                  "HEAD (" + GitUtil.getShortHash(currentRevision) + ")" :
+                  repository.getCurrentBranch().getName();
+    return "<b>" + text + "</b>";
+  }
+
+  private static boolean isMultiRepo(@NotNull Project project) {
+    return ServiceManager.getService(project, GitRepositoryManager.class).moreThanOneRoot();
+  }
+
+  @NotNull
+  public GitResetMode getResetMode() {
+    return myEnumModel.getSelected();
+  }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetAction.java b/plugins/git4idea/src/git4idea/reset/GitResetAction.java
new file mode 100644
index 0000000..749acd7
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetAction.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package git4idea.reset;
+
+import com.intellij.dvcs.ui.VcsLogOneCommitPerRepoAction;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ObjectUtils;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import git4idea.config.GitVcsSettings;
+import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public class GitResetAction extends VcsLogOneCommitPerRepoAction<GitRepository> {
+
+  @Nullable
+  @Override
+  protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+    return getRepoManager(project).getRepositoryForRoot(root);
+  }
+
+  @Override
+  protected void actionPerformed(@NotNull final Project project, @NotNull final Map<GitRepository, VcsFullCommitDetails> commits) {
+    GitVcsSettings settings = GitVcsSettings.getInstance(project);
+    GitResetMode defaultMode = ObjectUtils.notNull(settings.getResetMode(), GitResetMode.getDefault());
+    GitNewResetDialog dialog = new GitNewResetDialog(project, commits, defaultMode);
+    dialog.show();
+    if (dialog.isOK()) {
+      final GitResetMode selectedMode = dialog.getResetMode();
+      settings.setResetMode(selectedMode);
+      new Task.Backgroundable(project, "Git reset", false) {
+        @Override
+        public void run(@NotNull ProgressIndicator indicator) {
+          new GitResetOperation(project, commits, selectedMode, indicator).execute();
+        }
+      }.queue();
+    }
+  }
+
+  @NotNull
+  private static GitRepositoryManager getRepoManager(@NotNull Project project) {
+    return ServiceManager.getService(project, GitRepositoryManager.class);
+  }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetMode.java b/plugins/git4idea/src/git4idea/reset/GitResetMode.java
new file mode 100644
index 0000000..c10d957
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetMode.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package git4idea.reset;
+
+import org.jetbrains.annotations.NotNull;
+
+public enum GitResetMode {
+
+  SOFT("Soft", "--soft", "Files won't change, differences will be staged for commit."),
+  MIXED("Mixed", "--mixed", "Files won't change, differences won't be staged."),
+  HARD("Hard", "--hard", "Files will be reverted to the state of the selected commit.<br/>" +
+                         "Warning: any local changes will be lost."),
+  KEEP("Keep", "--keep", "Files will be reverted to the state of the selected commit,<br/>" +
+                         "but local changes will be kept intact.");
+
+  @NotNull private final String myName;
+  @NotNull private final String myArgument;
+  @NotNull private final String myDescription;
+
+  GitResetMode(@NotNull String name, @NotNull String argument, @NotNull String description) {
+    myName = name;
+    myArgument = argument;
+    myDescription = description;
+  }
+
+  @NotNull
+  public static GitResetMode getDefault() {
+    return MIXED;
+  }
+
+  @NotNull
+  public String getName() {
+    return myName;
+  }
+
+  @NotNull
+  public String getArgument() {
+    return myArgument;
+  }
+
+  @NotNull
+  public String getDescription() {
+    return myDescription;
+  }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetOperation.java b/plugins/git4idea/src/git4idea/reset/GitResetOperation.java
new file mode 100644
index 0000000..9c66a52
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetOperation.java
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+package git4idea.reset;
+
+import com.intellij.dvcs.repo.RepositoryUtil;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsNotifier;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import git4idea.GitPlatformFacade;
+import git4idea.GitUtil;
+import git4idea.branch.GitBranchUiHandlerImpl;
+import git4idea.branch.GitSmartOperationDialog;
+import git4idea.commands.Git;
+import git4idea.commands.GitCommandResult;
+import git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector;
+import git4idea.repo.GitRepository;
+import git4idea.util.GitPreservingProcess;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.RESET;
+
+public class GitResetOperation {
+
+  @NotNull private final Project myProject;
+  @NotNull private final Map<GitRepository, VcsFullCommitDetails> myCommits;
+  @NotNull private final GitResetMode myMode;
+  @NotNull private final ProgressIndicator myIndicator;
+  @NotNull private final Git myGit;
+  @NotNull private final VcsNotifier myNotifier;
+  @NotNull private final GitPlatformFacade myFacade;
+  @NotNull private final GitBranchUiHandlerImpl myUiHandler;
+
+  public GitResetOperation(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> targetCommits,
+                           @NotNull GitResetMode mode, @NotNull ProgressIndicator indicator) {
+    myProject = project;
+    myCommits = targetCommits;
+    myMode = mode;
+    myIndicator = indicator;
+    myGit = ServiceManager.getService(Git.class);
+    myNotifier = VcsNotifier.getInstance(project);
+    myFacade = ServiceManager.getService(GitPlatformFacade.class);
+    myUiHandler = new GitBranchUiHandlerImpl(myProject, myFacade, myGit, indicator);
+  }
+
+  public void execute() {
+    saveAllDocuments();
+    GitUtil.workingTreeChangeStarted(myProject);
+    Map<GitRepository, GitCommandResult> results = ContainerUtil.newHashMap();
+    try {
+      for (Map.Entry<GitRepository, VcsFullCommitDetails> entry : myCommits.entrySet()) {
+        GitRepository repository = entry.getKey();
+        VirtualFile root = repository.getRoot();
+        String target = entry.getValue().getId().asString();
+        GitLocalChangesWouldBeOverwrittenDetector detector = new GitLocalChangesWouldBeOverwrittenDetector(root, RESET);
+
+        GitCommandResult result = myGit.reset(repository, myMode, target, detector);
+        if (!result.success() && detector.wasMessageDetected()) {
+          GitCommandResult smartResult = proposeSmartReset(detector, repository, target);
+          if (smartResult != null) {
+            result = smartResult;
+          }
+        }
+        results.put(repository, result);
+        repository.update();
+        VfsUtil.markDirtyAndRefresh(true, true, false, root);
+      }
+    }
+    finally {
+      GitUtil.workingTreeChangeFinished(myProject);
+    }
+    notifyResult(results);
+  }
+
+  private GitCommandResult proposeSmartReset(@NotNull GitLocalChangesWouldBeOverwrittenDetector detector,
+                                             @NotNull final GitRepository repository, @NotNull final String target) {
+    Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), detector.getRelativeFilePaths());
+    List<Change> affectedChanges = GitUtil.findLocalChangesForPaths(myProject, repository.getRoot(), absolutePaths, false);
+    int choice = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "reset", "&Hard Reset");
+    if (choice == GitSmartOperationDialog.SMART_EXIT_CODE) {
+      final Ref<GitCommandResult> result = Ref.create();
+      new GitPreservingProcess(myProject, myFacade, myGit, Collections.singleton(repository), "reset", target, myIndicator, new Runnable() {
+        @Override
+        public void run() {
+          result.set(myGit.reset(repository, myMode, target));
+        }
+      }).execute();
+      return result.get();
+    }
+    if (choice == GitSmartOperationDialog.FORCE_EXIT_CODE) {
+      return myGit.reset(repository, GitResetMode.HARD, target);
+    }
+    return null;
+  }
+
+  private void notifyResult(@NotNull Map<GitRepository, GitCommandResult> results) {
+    Map<GitRepository, GitCommandResult> successes = ContainerUtil.newHashMap();
+    Map<GitRepository, GitCommandResult> errors = ContainerUtil.newHashMap();
+    for (Map.Entry<GitRepository, GitCommandResult> entry : results.entrySet()) {
+      GitCommandResult result = entry.getValue();
+      GitRepository repository = entry.getKey();
+      if (result.success()) {
+        successes.put(repository, result);
+      }
+      else {
+        errors.put(repository, result);
+      }
+    }
+
+    if (errors.isEmpty()) {
+      myNotifier.notifySuccess("", "Reset successful");
+    }
+    else if (!successes.isEmpty()) {
+      myNotifier.notifyImportantWarning("Reset partially failed",
+                                        "Reset was successful for " + joinRepos(successes.keySet())
+                                        + "<br/>but failed for " + joinRepos(errors.keySet()) + ": <br/>" + formErrorReport(errors));
+    }
+    else {
+      myNotifier.notifyError("Reset Failed", formErrorReport(errors));
+    }
+  }
+
+  @NotNull
+  private static String formErrorReport(@NotNull Map<GitRepository, GitCommandResult> errorResults) {
+    MultiMap<String, GitRepository> grouped = groupByResult(errorResults);
+    if (grouped.size() == 1) {
+      return "<code>" + grouped.keySet().iterator().next() + "</code>";
+    }
+    return StringUtil.join(grouped.entrySet(), new Function<Map.Entry<String, Collection<GitRepository>>, String>() {
+      @NotNull
+      @Override
+      public String fun(@NotNull Map.Entry<String, Collection<GitRepository>> entry) {
+        return joinRepos(entry.getValue()) + ":<br/><code>" + entry.getKey() + "</code>";
+      }
+    }, "<br/>");
+  }
+
+  // to avoid duplicate error reports if they are the same for different repositories
+  @NotNull
+  private static MultiMap<String, GitRepository> groupByResult(@NotNull Map<GitRepository, GitCommandResult> results) {
+    MultiMap<String, GitRepository> grouped = MultiMap.create();
+    for (Map.Entry<GitRepository, GitCommandResult> entry : results.entrySet()) {
+      grouped.putValue(entry.getValue().getErrorOutputAsHtmlString(), entry.getKey());
+    }
+    return grouped;
+  }
+
+  @NotNull
+  private static String joinRepos(@NotNull Collection<GitRepository> repositories) {
+    return StringUtil.join(RepositoryUtil.sortRepositories(repositories), ", ");
+  }
+
+  private static void saveAllDocuments() {
+    UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+      @Override
+      public void run() {
+        FileDocumentManager.getInstance().saveAllDocuments();
+      }
+    });
+  }
+
+}
diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
index 9b13bb6..eccaa44 100644
--- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
@@ -72,65 +72,25 @@
  * The unstash dialog
  */
 public class GitUnstashDialog extends DialogWrapper {
-  /**
-   * Git root selector
-   */
   private JComboBox myGitRootComboBox;
-  /**
-   * The current branch label
-   */
   private JLabel myCurrentBranch;
-  /**
-   * The view stash button
-   */
   private JButton myViewButton;
-  /**
-   * The drop stash button
-   */
   private JButton myDropButton;
-  /**
-   * The clear stashes button
-   */
   private JButton myClearButton;
-  /**
-   * The pop stash checkbox
-   */
   private JCheckBox myPopStashCheckBox;
-  /**
-   * The branch text field
-   */
   private JTextField myBranchTextField;
-  /**
-   * The root panel of the dialog
-   */
   private JPanel myPanel;
-  /**
-   * The stash list
-   */
   private JList myStashList;
-  /**
-   * If this checkbox is selected, the index is reinstated as well as working tree
-   */
   private JCheckBox myReinstateIndexCheckBox;
   /**
    * Set of branches for the current root
    */
   private final HashSet<String> myBranches = new HashSet<String>();
 
-  /**
-   * The project
-   */
   private final Project myProject;
   private GitVcs myVcs;
   private static final Logger LOG = Logger.getInstance(GitUnstashDialog.class);
 
-  /**
-   * A constructor
-   *
-   * @param project     the project
-   * @param roots       the list of the roots
-   * @param defaultRoot the default root to select
-   */
   public GitUnstashDialog(final Project project, final List<VirtualFile> roots, final VirtualFile defaultRoot) {
     super(project, true);
     setModal(false);
@@ -310,9 +270,6 @@
     setOKActionEnabled(true);
   }
 
-  /**
-   * Refresh stash list
-   */
   private void refreshStashList() {
     final DefaultListModel listModel = (DefaultListModel)myStashList.getModel();
     listModel.clear();
@@ -334,16 +291,10 @@
     myStashList.setSelectedIndex(0);
   }
 
-  /**
-   * @return the selected git root
-   */
   private VirtualFile getGitRoot() {
     return (VirtualFile)myGitRootComboBox.getSelectedItem();
   }
 
-  /**
-   * @return unstash handler
-   */
   private GitLineHandler handler() {
     GitLineHandler h = new GitLineHandler(myProject, getGitRoot(), GitCommand.STASH);
     String branch = myBranchTextField.getText();
@@ -361,32 +312,19 @@
     return h;
   }
 
-  /**
-   * @return selected stash
-   * @throws NullPointerException if no stash is selected
-   */
   private StashInfo getSelectedStash() {
     return (StashInfo)myStashList.getSelectedValue();
   }
 
-  /**
-   * {@inheritDoc}
-   */
   protected JComponent createCenterPanel() {
     return myPanel;
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getDimensionServiceKey() {
     return getClass().getName();
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getHelpId() {
     return "reference.VersionControl.Git.Unstash";
@@ -418,6 +356,7 @@
       final Ref<GitCommandResult> result = Ref.create();
       ProgressManager.getInstance().run(new Task.Modal(h.project(), GitBundle.getString("unstash.unstashing"), false) {
         public void run(@NotNull final ProgressIndicator indicator) {
+          indicator.setIndeterminate(true);
           h.addLineListener(new GitHandlerUtil.GitLineHandlerListenerProgress(indicator, h, "stash", false));
           Git git = ServiceManager.getService(Git.class);
           result.set(git.runCommand(new Computable.PredefinedValueComputable<GitLineHandler>(h)));
diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
index 80074fb..4d3497f 100644
--- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
+++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
@@ -136,7 +136,7 @@
       @Override
       public void run() {
         Project project = getProject();
-        if (project == null) {
+        if (project == null || project.isDisposed()) {
           emptyTextAndTooltip();
           return;
         }
diff --git a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
index 4315e65..08c5103 100644
--- a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
@@ -19,15 +19,21 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.FilePathImpl;
 import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.LocalChangeList;
 import com.intellij.openapi.vcs.changes.ui.ChangeListViewerDialog;
 import com.intellij.openapi.vcs.update.UpdatedFiles;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.UIUtil;
 import git4idea.GitUtil;
 import git4idea.branch.GitBranchPair;
@@ -173,9 +179,14 @@
       final Collection<String> remotelyChanged = GitUtil.getPathsDiffBetweenRefs(ServiceManager.getService(Git.class), repository,
                                                                                  currentBranch, remoteBranch);
       final List<File> locallyChanged = myChangeListManager.getAffectedPaths();
-      for (File localPath : locallyChanged) {
-        if (remotelyChanged.contains(FilePathsHelper.convertPath(localPath.getPath()))) {
-         // found a file which was changed locally and remotely => need to save
+      for (final File localPath : locallyChanged) {
+        if (ContainerUtil.exists(remotelyChanged, new Condition<String>() {
+          @Override
+          public boolean value(String remotelyChangedPath) {
+            return FileUtil.pathsEqual(localPath.getPath(), remotelyChangedPath);
+          }
+        })) {
+          // found a file which was changed locally and remotely => need to save
           return true;
         }
       }
diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
index 35acc41..9a2bad2 100644
--- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
+++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
@@ -14,16 +14,14 @@
  * limitations under the License.
  */
 package git4idea.branch
-import com.intellij.dvcs.test.MockVirtualFile
+
 import com.intellij.openapi.progress.ProgressIndicator
 import com.intellij.openapi.progress.util.ProgressIndicatorBase
 import com.intellij.openapi.project.Project
 import com.intellij.openapi.ui.DialogWrapper
 import com.intellij.openapi.util.io.FileUtil
 import com.intellij.openapi.util.text.StringUtil
-import com.intellij.openapi.vcs.FilePathImpl
 import com.intellij.openapi.vcs.changes.Change
-import com.intellij.openapi.vcs.changes.CurrentContentRevision
 import com.intellij.openapi.vfs.VirtualFile
 import com.intellij.util.Function
 import com.intellij.util.LineSeparator
@@ -35,12 +33,11 @@
 import git4idea.repo.GitRepository
 import git4idea.test.GitPlatformTest
 import org.jetbrains.annotations.NotNull
+import org.jetbrains.annotations.Nullable
 
 import java.util.regex.Matcher
 
-import static com.intellij.openapi.vcs.Executor.*
-import static git4idea.test.GitExecutor.cd
-import static git4idea.test.GitExecutor.git
+import static git4idea.test.GitExecutor.*
 import static git4idea.test.GitScenarios.*
 
 class GitBranchWorkerTest extends GitPlatformTest {
@@ -248,7 +245,7 @@
 
     List<Change> changes = null;
     checkoutOrMerge(operation, "feature", [
-      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
+      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force ->
               changes = cs
               DialogWrapper.CANCEL_EXIT_CODE
             }
@@ -270,17 +267,6 @@
     return !GitVersionSpecialty.OLD_STYLE_OF_UNTRACKED_AND_LOCAL_CHANGES_WOULD_BE_OVERWRITTEN.existsIn(GitVersion.parse(git("version")));
   }
 
-  Change[] changesFromFiles(Collection<String> paths) {
-    paths.collect {
-      toChange(it)
-    }
-  }
-
-  Change toChange(String relPath) {
-    // we don't care about the before revision
-    new Change(null, CurrentContentRevision.create(new FilePathImpl(new MockVirtualFile(myProjectRoot + "/" + relPath))))
-  }
-
   public void "test agree to smart checkout should smart checkout"() {
     def localChanges = agree_to_smart_operation("checkout", "Checked out <b><code>feature</code></b>")
 
@@ -345,7 +331,7 @@
     prepareLocalChangesOverwrittenBy(myUltimate)
 
     checkoutOrMerge(operation, "feature", [
-      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean f
+      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force
         -> GitSmartOperationDialog.CANCEL_EXIT_CODE
       },
     ] as GitBranchUiHandler )
@@ -371,7 +357,7 @@
     def rollbackMsg = null
     checkoutOrMerge(operation, "feature", [
       showSmartOperationDialog       : {
-        Project p, List<Change> cs, Collection<String> paths, String op, boolean f -> GitSmartOperationDialog.CANCEL_EXIT_CODE
+        Project p, List<Change> cs, Collection<String> paths, String op, String f -> GitSmartOperationDialog.CANCEL_EXIT_CODE
       },
       notifyErrorWithRollbackProposal: { String t, String m, String rp -> rollbackMsg = m; false }
     ] as GitBranchUiHandler )
@@ -384,7 +370,7 @@
     prepareLocalChangesOverwrittenBy(myUltimate)
 
     def uiHandler = [
-      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
+      showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force ->
         GitSmartOperationDialog.FORCE_EXIT_CODE;
       },
     ] as GitBranchUiHandler
@@ -611,6 +597,39 @@
     assertEquals "Merge in ultimate should have been reset", ultimateTipAfterMerge, tip(myUltimate)
   }
 
+  public void test_checkout_in_detached_head() {
+    cd(myCommunity);
+    touch("file.txt", "some content");
+    add("file.txt");
+    commit("msg");
+    git(myCommunity, "checkout HEAD^");
+
+    checkoutBranch("master", []);
+    assertCurrentBranch("master");
+  }
+
+  // inspired by IDEA-127472
+  public void test_checkout_to_common_branch_when_branches_have_diverged() {
+    branchWithCommit(myUltimate, "feature", "feature-file.txt", "feature_content", false);
+    branchWithCommit(myCommunity, "newbranch", "newbranch-file.txt", "newbranch_content", false);
+    checkoutBranch("master", [])
+    assertCurrentBranch("master");
+  }
+
+  public void test_rollback_checkout_from_diverged_branches_should_return_to_proper_branches() {
+    branchWithCommit(myUltimate, "feature", "feature-file.txt", "feature_content", false);
+    branchWithCommit(myCommunity, "newbranch", "newbranch-file.txt", "newbranch_content", false);
+    unmergedFiles(myContrib)
+
+    checkoutBranch "master", [
+            showUnmergedFilesMessageWithRollback: { String s1, String s2 -> true },
+    ]
+
+    assertCurrentBranch(myUltimate, "feature");
+    assertCurrentBranch(myCommunity, "newbranch");
+    assertCurrentBranch(myContrib, "master");
+  }
+
   static def assertCurrentBranch(GitRepository repository, String name) {
     def curBranch = git(repository, "branch").split("\n").find { it -> it.contains("*") }.replace('*', ' ').trim()
     assertEquals("Current branch is incorrect in ${repository}", name, curBranch)
@@ -716,7 +735,7 @@
       @NotNull List<Change> changes,
       @NotNull Collection<String> paths,
       @NotNull String operation,
-      boolean isForcePossible) {
+      @Nullable String forceButton) {
       GitSmartOperationDialog.SMART_EXIT_CODE
     }
 
diff --git a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
index 797e027..0bb6767 100644
--- a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
+++ b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
@@ -20,6 +20,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.CollectConsumer;
 import com.intellij.util.Consumer;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
@@ -84,9 +85,10 @@
     prepareSomeHistory();
     createTaggedBranch();
     List<VcsCommitMetadata> expectedLog = log();
-    @SuppressWarnings("unchecked")
-    List<TimedVcsCommit> actualLog = myLogProvider.readAllHashes(myProjectRoot, Consumer.EMPTY_CONSUMER);
-    assertOrderedEquals(expectedLog, actualLog);
+    List<TimedVcsCommit> collector = ContainerUtil.newArrayList();
+    //noinspection unchecked
+    myLogProvider.readAllHashes(myProjectRoot, Consumer.EMPTY_CONSUMER, new CollectConsumer<TimedVcsCommit>(collector));
+    assertOrderedEquals(expectedLog, collector);
   }
 
   public void test_get_current_user() throws Exception {
diff --git a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
index 707e972..14d8831 100644
--- a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
+++ b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
@@ -15,7 +15,7 @@
 import git4idea.GitRemoteBranch;
 import git4idea.branch.GitBranchesCollection;
 import git4idea.repo.*;
-import git4idea.test.GitTestRepositoryManager;
+import git4idea.test.GitMockRepositoryManager;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -145,7 +145,7 @@
   }
 
   private static List<VcsRef> sort(final Collection<VcsRef> refs) {
-    final GitTestRepositoryManager manager = new GitTestRepositoryManager();
+    final GitMockRepositoryManager manager = new GitMockRepositoryManager();
     manager.add(new MockGitRepository() {
       @NotNull
       @Override
@@ -304,5 +304,9 @@
     public String toLogString() {
       throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void dispose() {
+    }
   }
 }
diff --git a/plugins/git4idea/tests/git4idea/test/GitExecutor.java b/plugins/git4idea/tests/git4idea/test/GitExecutor.java
index 7c561c3..f1b042a 100644
--- a/plugins/git4idea/tests/git4idea/test/GitExecutor.java
+++ b/plugins/git4idea/tests/git4idea/test/GitExecutor.java
@@ -53,11 +53,12 @@
     printVersionTheFirstTime();
     List<String> split = splitCommandInParameters(command);
     split.add(0, PathHolder.GIT_EXECUTABLE);
-    debug("# git " + command);
+    File workingDir = ourCurrentDir();
+    debug("[" + workingDir.getName() + "] # git " + command);
     for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
       String stdout;
       try {
-        stdout = run(split, ignoreNonZeroExitCode);
+        stdout = run(workingDir, split, ignoreNonZeroExitCode);
         if (!isIndexLockFileError(stdout)) {
           return stdout;
         }
@@ -97,7 +98,7 @@
   }
 
   public static void add(@NotNull String path) {
-    git("add " + path);
+    git("add --verbose " + path);
   }
 
   public static void addCommit(@NotNull String message) {
diff --git a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
index b6f25e7..8723ce2 100644
--- a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
+++ b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
@@ -15,13 +15,11 @@
  */
 package git4idea.test;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
 import git4idea.commands.GitCommand;
 import git4idea.commands.GitHttpAuthService;
 import git4idea.commands.GitHttpAuthenticator;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * @author Kirill Likhodedov
@@ -61,8 +59,7 @@
 
   @NotNull
   @Override
-  public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
-                                                  @NotNull String url) {
+  public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
     return myAuthenticator;
   }
 
diff --git a/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java b/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java
new file mode 100644
index 0000000..21ed4da
--- /dev/null
+++ b/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2013 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 git4idea.test;
+
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vfs.VirtualFile;
+import git4idea.repo.GitRepository;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitMockRepositoryManager implements RepositoryManager<GitRepository> {
+  private final List<GitRepository> myRepositories = new ArrayList<GitRepository>();
+
+  public void add(GitRepository repository) {
+    myRepositories.add(repository);
+  }
+
+  @Override
+  public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) {
+    for (GitRepository repository : myRepositories) {
+      if (repository.getRoot().equals(root)) {
+        return repository;
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public GitRepository getRepositoryForFile(@NotNull FilePath file) {
+    throw new UnsupportedOperationException();
+  }
+
+  @NotNull
+  @Override
+  public List<GitRepository> getRepositories() {
+    return myRepositories;
+  }
+
+  @Override
+  public boolean moreThanOneRoot() {
+    return myRepositories.size() > 1;
+  }
+
+  @Override
+  public void updateRepository(VirtualFile root) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void updateAllRepositories() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void waitUntilInitialized() {
+  }
+
+}
diff --git a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
index ef3f963..c02ec55 100644
--- a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
+++ b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.*;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
@@ -51,19 +52,19 @@
 
   private static final Logger LOG = Logger.getInstance(GitPlatformTest.class);
 
-  @NotNull protected Project myProject;
-  @NotNull protected VirtualFile myProjectRoot;
-  @NotNull protected String myProjectPath;
-  @NotNull protected GitRepositoryManager myGitRepositoryManager;
-  @NotNull protected GitVcsSettings myGitSettings;
-  @NotNull protected GitPlatformFacade myPlatformFacade;
-  @NotNull protected Git myGit;
-  @NotNull protected GitVcs myVcs;
+  protected Project myProject;
+  protected VirtualFile myProjectRoot;
+  protected String myProjectPath;
+  protected GitRepositoryManager myGitRepositoryManager;
+  protected GitVcsSettings myGitSettings;
+  protected GitPlatformFacade myPlatformFacade;
+  protected Git myGit;
+  protected GitVcs myVcs;
 
-  @NotNull protected TestDialogManager myDialogManager;
-  @NotNull protected TestVcsNotifier myVcsNotifier;
+  protected TestDialogManager myDialogManager;
+  protected TestVcsNotifier myVcsNotifier;
 
-  @NotNull private IdeaProjectTestFixture myProjectFixture;
+  private IdeaProjectTestFixture myProjectFixture;
   private String myTestStartedIndicator;
 
   @SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedDeclaration"})
@@ -86,35 +87,41 @@
       throw e;
     }
 
-    myProject = myProjectFixture.getProject();
-    myProjectRoot = myProject.getBaseDir();
-    myProjectPath = myProjectRoot.getPath();
+    try {
+      myProject = myProjectFixture.getProject();
+      myProjectRoot = myProject.getBaseDir();
+      myProjectPath = myProjectRoot.getPath();
 
-    myGitSettings = GitVcsSettings.getInstance(myProject);
-    myGitSettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);
+      myGitSettings = GitVcsSettings.getInstance(myProject);
+      myGitSettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);
 
-    myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
-    myVcsNotifier = (TestVcsNotifier)ServiceManager.getService(myProject, VcsNotifier.class);
+      myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
+      myVcsNotifier = (TestVcsNotifier)ServiceManager.getService(myProject, VcsNotifier.class);
 
-    myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
-    myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class);
-    myGit = ServiceManager.getService(myProject, Git.class);
-    myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject));
-    myVcs.doActivate();
+      myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
+      myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class);
+      myGit = ServiceManager.getService(myProject, Git.class);
+      myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject));
+      myVcs.doActivate();
 
-    GitTestUtil.assumeSupportedGitVersion(myVcs);
-    initChangeListManager();
-    addSilently();
-    removeSilently();
+      GitTestUtil.assumeSupportedGitVersion(myVcs);
+      initChangeListManager();
+      addSilently();
+      removeSilently();
+    }
+    catch (Exception e) {
+      tearDown();
+      throw e;
+    }
   }
 
   @Override
   @NotNull
   public String getTestName(boolean lowercaseFirstLetter) {
     String name = super.getTestName(lowercaseFirstLetter);
-    name = name.trim().replace(' ', '_');
-    if (name.length() > 50) {
-      name = name.substring(0, 50);
+    name = StringUtil.shortenTextWithEllipsis(name.trim().replace(" ", "_"), 12, 6, "_");
+    if (name.startsWith("_")) {
+      name = name.substring(1);
     }
     return name;
   }
@@ -127,16 +134,25 @@
   @Override
   protected void tearDown() throws Exception {
     try {
-      myDialogManager.cleanup();
-      myVcsNotifier.cleanup();
-      myProjectFixture.tearDown();
-
-      String tempTestIndicator = myTestStartedIndicator;
-      clearFields(this);
-      myTestStartedIndicator = tempTestIndicator;
+      if (myDialogManager != null) {
+        myDialogManager.cleanup();
+      }
+      if (myVcsNotifier != null) {
+        myVcsNotifier.cleanup();
+      }
+      if (myProjectFixture != null) {
+        myProjectFixture.tearDown();
+      }
     }
     finally {
-      super.tearDown();
+      try {
+        String tempTestIndicator = myTestStartedIndicator;
+        clearFields(this);
+        myTestStartedIndicator = tempTestIndicator;
+      }
+      finally {
+        super.tearDown();
+      }
     }
   }
 
diff --git a/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy b/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
index 77ecf0b..1fe574a 100644
--- a/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
+++ b/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
@@ -38,14 +38,17 @@
   /**
    * Create a branch with a commit and return back to master.
    */
-  static def branchWithCommit(GitRepository repository, String name, String file = "branch_file.txt", String content = "branch content") {
+  static def branchWithCommit(GitRepository repository, String name, String file = "branch_file.txt", String content = "branch content",
+                              boolean returnToMaster = true) {
     cd repository
     git("checkout -b $name")
     touch(file, content)
     git("add $file")
     git("commit -m branch_content")
 
-    git("checkout master")
+    if (returnToMaster) {
+      git("checkout master")
+    }
   }
 
   /**
diff --git a/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
index 52bf562..b02e952 100644
--- a/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
+++ b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -15,70 +15,46 @@
  */
 package git4idea.test;
 
-import com.intellij.dvcs.repo.RepositoryManager;
-import com.intellij.openapi.vcs.FilePath;
+import com.intellij.dvcs.repo.RepoStateException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vfs.VirtualFile;
+import git4idea.GitPlatformFacade;
 import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryImpl;
+import git4idea.repo.GitRepositoryManager;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.List;
+public class GitTestRepositoryManager extends GitRepositoryManager {
 
-/**
- * @author Kirill Likhodedov
- */
-public class GitTestRepositoryManager implements RepositoryManager<GitRepository> {
-  private final List<GitRepository> myRepositories = new ArrayList<GitRepository>();
+  @NotNull private final Project myProject;
+  @NotNull private final GitPlatformFacade myFacade;
 
-  public void add(GitRepository repository) {
-    myRepositories.add(repository);
-  }
-
-  @Override
-  public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) {
-    for (GitRepository repository : myRepositories) {
-      if (repository.getRoot().equals(root)) {
-        return repository;
-      }
-    }
-
-    return null;
-  }
-
-  @Override
-  public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public GitRepository getRepositoryForFile(@NotNull FilePath file) {
-    throw new UnsupportedOperationException();
+  public GitTestRepositoryManager(@NotNull Project project,
+                                  @NotNull GitPlatformFacade platformFacade,
+                                  @NotNull ProjectLevelVcsManager vcsManager) {
+    super(project, platformFacade, vcsManager);
+    myProject = project;
+    myFacade = platformFacade;
   }
 
   @NotNull
   @Override
-  public List<GitRepository> getRepositories() {
-    return myRepositories;
-  }
-
-  @Override
-  public boolean moreThanOneRoot() {
-    return myRepositories.size() > 1;
-  }
-
-  @Override
-  public void updateRepository(VirtualFile root) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void updateAllRepositories() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void waitUntilInitialized() {
+  protected GitRepository createRepository(@NotNull VirtualFile root) {
+    return new GitRepositoryImpl(root, myFacade, myProject, this, false) {
+      @Override
+      public void update() {
+        try {
+          super.update();
+        }
+        catch (RepoStateException e) {
+          if (!Disposer.isDisposed(this)) { // project dir will simply be removed during dispose
+            throw e;
+          }
+        }
+      }
+    };
   }
 
 }
diff --git a/plugins/git4idea/tests/git4idea/test/GitTestUtil.java b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
index 842b1b1..3525ad1 100644
--- a/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
+++ b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import git4idea.GitUtil;
 import git4idea.GitVcs;
+import git4idea.config.GitVersion;
 import git4idea.repo.GitRepository;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.ide.BuiltInServerManagerImpl;
@@ -111,6 +112,7 @@
   }
 
   public static void assumeSupportedGitVersion(@NotNull GitVcs vcs) {
-    assumeTrue(vcs.getVersion().isSupported());
+    GitVersion version = vcs.getVersion();
+    assumeTrue("Unsupported Git version: " + version, version.isSupported());
   }
 }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index 714191d..bfceb0c 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -195,7 +195,7 @@
     }
 
     try {
-      return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()), indicator,
+      return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
                                 new ThrowableConvertor<GithubAuthData, GithubRepoDetailed, IOException>() {
                                   @NotNull
                                   @Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
index 7c18b3b..cca5afa 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -23,10 +23,10 @@
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsDataKeys;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
@@ -54,7 +54,6 @@
 import org.jetbrains.plugins.github.api.GithubApiUtil;
 import org.jetbrains.plugins.github.api.GithubRepo;
 import org.jetbrains.plugins.github.api.GithubUserDetailed;
-import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.ui.GithubShareDialog;
 import org.jetbrains.plugins.github.util.*;
 
@@ -125,7 +124,7 @@
       externalRemoteDetected = !gitRepository.getRemotes().isEmpty();
     }
 
-    final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings(null);
+    final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings();
 
     // get available GitHub repos with modal progress
     final GithubInfo githubInfo = loadGithubInfoWithModal(authHolder, project);
@@ -351,11 +350,11 @@
   @NotNull
   private static Collection<VirtualFile> filterOutIgnored(@NotNull Project project, @NotNull Collection<VirtualFile> files) {
     final ChangeListManager changeListManager = ChangeListManager.getInstance(project);
-    final FileIndexFacade fileIndex = FileIndexFacade.getInstance(project);
+    final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
     return ContainerUtil.filter(files, new Condition<VirtualFile>() {
       @Override
       public boolean value(VirtualFile file) {
-        return !changeListManager.isIgnoredFile(file) && !fileIndex.isExcludedFile(file);
+        return !changeListManager.isIgnoredFile(file) && !vcsManager.isIgnored(file);
       }
     });
   }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
index 115258d..6b3f73f 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
@@ -61,7 +61,7 @@
           @NotNull
           @Override
           public List<GithubRepo> convert(ProgressIndicator indicator) throws IOException {
-            return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()), indicator,
+            return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
                                       new ThrowableConvertor<GithubAuthData, List<GithubRepo>, IOException>() {
                                         @NotNull
                                         @Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
index 47d3edc..5a7daf9 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
@@ -15,7 +15,6 @@
  */
 package org.jetbrains.plugins.github.extensions;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.AuthData;
 import git4idea.remote.GitHttpAuthDataProvider;
@@ -32,7 +31,7 @@
 
   @Nullable
   @Override
-  public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+  public AuthData getAuthData(@NotNull String url) {
     if (!GithubUrlUtil.isGithubUrl(url)) {
       return null;
     }
@@ -48,7 +47,7 @@
       return null;
     }
 
-    GithubAuthData auth = settings.getAuthData(modalityState);
+    GithubAuthData auth = settings.getAuthData();
     switch (auth.getAuthType()) {
       case BASIC:
         GithubAuthData.BasicAuth basicAuth = auth.getBasicAuth();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
index 9cf3cdf..5333d82 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -125,8 +125,7 @@
           @Override
           public String convert(ProgressIndicator indicator) throws IOException {
             return GithubUtil
-              .runTaskWithBasicAuthForHost(myProject, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()),
-                                           indicator, getHost(),
+              .runTaskWithBasicAuthForHost(myProject, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
                                            new ThrowableConvertor<GithubAuthData, String, IOException>() {
                                              @NotNull
                                              @Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
index 229170e..7de0dae 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -130,8 +130,7 @@
               @NotNull
               @Override
               public String convert(ProgressIndicator indicator) throws IOException {
-                return GithubUtil.runTaskWithBasicAuthForHost(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()),
-                                                              indicator, getHost(),
+                return GithubUtil.runTaskWithBasicAuthForHost(project, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
                                                               new ThrowableConvertor<GithubAuthData, String, IOException>() {
                                                                 @NotNull
                                                                 @Override
@@ -263,7 +262,7 @@
   @NotNull
   public GithubAuthData getAuthData() {
     if (!myCredentialsModified) {
-      return mySettings.getAuthData(null);
+      return mySettings.getAuthData();
     }
     Object selected = myAuthTypeComboBox.getSelectedItem();
     if (AUTH_PASSWORD.equals(selected)) return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword());
@@ -291,7 +290,7 @@
 
   public void apply() {
     if (myCredentialsModified) {
-      mySettings.setAuthData(getAuthData(), true, null);
+      mySettings.setAuthData(getAuthData(), true);
     }
     mySettings.setConnectionTimeout(getConnectionTimeout());
     resetCredentialsModification();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
index d7981b2..f110444 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
@@ -15,7 +15,6 @@
  */
 package org.jetbrains.plugins.github.util;
 
-import com.intellij.openapi.application.ModalityState;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.github.api.GithubApiUtil;
@@ -53,8 +52,8 @@
     myUseProxy = useProxy;
   }
 
-  public static GithubAuthData createFromSettings(@Nullable ModalityState state) {
-    return GithubSettings.getInstance().getAuthData(state);
+  public static GithubAuthData createFromSettings() {
+    return GithubSettings.getInstance().getAuthData();
   }
 
   public static GithubAuthData createAnonymous() {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
index 24303a3..695dfe7 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
@@ -15,10 +15,8 @@
  */
 package org.jetbrains.plugins.github.util;
 
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.util.ThrowableComputable;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 
 public class GithubAuthDataHolder {
@@ -42,7 +40,7 @@
     myAuthData = task.compute();
   }
 
-  public static GithubAuthDataHolder createFromSettings(@Nullable ModalityState state) {
-    return new GithubAuthDataHolder(GithubSettings.getInstance().getAuthData(state));
+  public static GithubAuthDataHolder createFromSettings() {
+    return new GithubAuthDataHolder(GithubSettings.getInstance().getAuthData());
   }
 }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
index a2bdca5..3523e41 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
@@ -19,7 +19,6 @@
 import com.intellij.ide.passwordSafe.PasswordSafeException;
 import com.intellij.ide.passwordSafe.config.PasswordSafeSettings;
 import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.components.*;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.text.StringUtil;
@@ -152,10 +151,10 @@
   }
 
   @NotNull
-  private String getPassword(@Nullable ModalityState state) {
+  private String getPassword() {
     String password;
     try {
-      password = PasswordSafe.getInstance().getPassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, state);
+      password = PasswordSafe.getInstance().getPassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY);
     }
     catch (PasswordSafeException e) {
       LOG.info("Couldn't get password for key [" + GITHUB_SETTINGS_PASSWORD_KEY + "]", e);
@@ -165,10 +164,10 @@
     return StringUtil.notNullize(password);
   }
 
-  private void setPassword(@NotNull String password, boolean rememberPassword, @Nullable ModalityState state) {
+  private void setPassword(@NotNull String password, boolean rememberPassword) {
     try {
       if (rememberPassword) {
-        PasswordSafe.getInstance().storePassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, password, state);
+        PasswordSafe.getInstance().storePassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, password);
       }
       else {
         final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
@@ -197,13 +196,13 @@
   }
 
   @NotNull
-  public GithubAuthData getAuthData(@Nullable ModalityState state) {
+  public GithubAuthData getAuthData() {
     switch (getAuthType()) {
       case BASIC:
         //noinspection ConstantConditions
-        return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword(state));
+        return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword());
       case TOKEN:
-        return GithubAuthData.createTokenAuth(getHost(), getPassword(state));
+        return GithubAuthData.createTokenAuth(getHost(), getPassword());
       case ANONYMOUS:
         return GithubAuthData.createAnonymous();
       default:
@@ -211,7 +210,7 @@
     }
   }
 
-  public void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword, @Nullable ModalityState state) {
+  public void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword) {
     setValidGitAuth(isValidGitAuth(auth));
 
     setAuthType(auth.getAuthType());
@@ -221,16 +220,16 @@
       case BASIC:
         assert auth.getBasicAuth() != null;
         setLogin(auth.getBasicAuth().getLogin());
-        setPassword(auth.getBasicAuth().getPassword(), rememberPassword, state);
+        setPassword(auth.getBasicAuth().getPassword(), rememberPassword);
         break;
       case TOKEN:
         assert auth.getTokenAuth() != null;
         setLogin(null);
-        setPassword(auth.getTokenAuth().getToken(), rememberPassword, state);
+        setPassword(auth.getTokenAuth().getToken(), rememberPassword);
         break;
       case ANONYMOUS:
         setLogin(null);
-        setPassword("", rememberPassword, state);
+        setPassword("", rememberPassword);
         break;
       default:
         throw new IllegalStateException("GithubSettings: setAuthData - wrong AuthType: " + auth.getAuthType());
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
index e4af54f..edd12ab 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
@@ -161,7 +161,7 @@
 
             if (ok[0]) {
               authData[0] = dialog.getAuthData();
-              GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected(), indicator.getModalityState());
+              GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected());
             }
           }
         }, indicator.getModalityState());
@@ -195,7 +195,7 @@
 
               final GithubSettings settings = GithubSettings.getInstance();
               if (settings.getAuthType() != GithubAuthData.AuthType.TOKEN) {
-                GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected(), indicator.getModalityState());
+                GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected());
               }
             }
           }
@@ -247,7 +247,7 @@
   @NotNull
   public static GithubAuthDataHolder getValidAuthDataHolderFromConfig(@NotNull Project project, @NotNull ProgressIndicator indicator)
     throws IOException {
-    GithubAuthData auth = GithubAuthData.createFromSettings(indicator.getModalityState());
+    GithubAuthData auth = GithubAuthData.createFromSettings();
     GithubAuthDataHolder authHolder = new GithubAuthDataHolder(auth);
     try {
       checkAuthData(project, authHolder, indicator);
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
index d313398..b54bd8c 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
@@ -54,12 +54,12 @@
 
   @NotNull
   protected GithubAuthDataHolder getAuthDataHolder() {
-    return new GithubAuthDataHolder(myGitHubSettings.getAuthData(null));
+    return new GithubAuthDataHolder(myGitHubSettings.getAuthData());
   }
 
   protected void deleteGist() throws IOException {
     if (GIST_ID != null) {
-      GithubApiUtil.deleteGist(myGitHubSettings.getAuthData(null), GIST_ID);
+      GithubApiUtil.deleteGist(myGitHubSettings.getAuthData(), GIST_ID);
       GIST = null;
       GIST_ID = null;
     }
@@ -82,7 +82,7 @@
 
     if (GIST == null) {
       try {
-        GIST = GithubApiUtil.getGist(myGitHubSettings.getAuthData(null), GIST_ID);
+        GIST = GithubApiUtil.getGist(myGitHubSettings.getAuthData(), GIST_ID);
       }
       catch (IOException e) {
         System.err.println(e.getMessage());
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
index 97b34aa..4fec0d1 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
@@ -36,7 +36,7 @@
 
   public void testAvailableRepos() throws Throwable {
 
-    List<GithubRepo> availableRepos = GithubApiUtil.getUserRepos(myGitHubSettings.getAuthData(null), myLogin2);
+    List<GithubRepo> availableRepos = GithubApiUtil.getUserRepos(myGitHubSettings.getAuthData(), myLogin2);
     List<String> realData = new ArrayList<String>();
     for (GithubRepo info : availableRepos) {
       realData.add(info.getName());
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
index e6da326..c406362 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
@@ -99,7 +99,7 @@
   }
 
   protected void checkGithubExists() throws IOException {
-    GithubAuthData auth = myGitHubSettings.getAuthData(null);
+    GithubAuthData auth = myGitHubSettings.getAuthData();
     GithubRepoDetailed githubInfo = GithubApiUtil.getDetailedRepoInfo(auth, myLogin1, PROJECT_NAME);
     assertNotNull("GitHub repository does not exist", githubInfo);
   }
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
index f146b37..abfb5ec 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
@@ -48,7 +48,7 @@
   }
 
   protected void deleteGithubRepo() throws IOException {
-    GithubApiUtil.deleteGithubRepository(myGitHubSettings.getAuthData(null), myLogin1, PROJECT_NAME);
+    GithubApiUtil.deleteGithubRepository(myGitHubSettings.getAuthData(), myLogin1, PROJECT_NAME);
   }
 
   protected void registerDefaultShareDialogHandler() {
diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
index b728913..3d3d820 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
@@ -172,7 +172,7 @@
     myAuth = GithubAuthData.createBasicAuth(host, login1, password);
 
     myGitHubSettings = GithubSettings.getInstance();
-    myGitHubSettings.setAuthData(myAuth, false, null);
+    myGitHubSettings.setAuthData(myAuth, false);
 
     myHttpAuthService = (GitHttpAuthTestService)ServiceManager.getService(GitHttpAuthService.class);
 
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
index 549aa1a..e6ab874 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
@@ -113,7 +113,11 @@
     List<String> classpath = new ArrayList<String>();
     classpath.add(extension.getToolsApiJarPath());
     classpath.add(PathManager.getJarPathForClass(EnhancerRunner.class));
+    boolean removeOrmJars = Boolean.parseBoolean(System.getProperty("jps.appengine.enhancer.remove.orm.jars", "true"));
     for (File file : JpsJavaExtensionService.dependencies(module).recursively().compileOnly().productionOnly().classes().getRoots()) {
+      if (removeOrmJars && FileUtil.isAncestor(new File(extension.getOrmLibPath()), file, true)) {
+        continue;
+      }
       classpath.add(file.getAbsolutePath());
     }
 
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
index 0c68b41..beb54b5 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
@@ -26,6 +26,8 @@
 public interface JpsAppEngineModuleExtension extends JpsElement {
   JpsModule getModule();
 
+  String getOrmLibPath();
+
   String getSdkHomePath();
 
   boolean isRunEnhancerOnMake();
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
index e52d54d..d40f7c0 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
@@ -71,6 +71,11 @@
   }
 
   @Override
+  public String getOrmLibPath() {
+    return FileUtil.toSystemDependentName(JpsArtifactPathUtil.appendToPath(getSdkHomePath(), "/lib/user/orm"));
+  }
+
+  @Override
   public String getSdkHomePath() {
     return myProperties.mySdkHomePath;
   }
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
index afe24f1..e3a7762 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
@@ -21,6 +21,7 @@
 import com.intellij.facet.ProjectFacetManager;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.packaging.artifacts.Artifact;
@@ -67,8 +68,12 @@
         }
 
         @Override
-        public void errorOccurred(@NotNull String errorMessage) {
-          Messages.showErrorDialog(project, errorMessage, CommonBundle.getErrorTitle());
+        public void errorOccurred(@NotNull final String errorMessage) {
+          ApplicationManager.getApplication().invokeLater(new Runnable() {
+            public void run() {
+              Messages.showErrorDialog(project, errorMessage, CommonBundle.getErrorTitle());
+            }
+          });
         }
       }, null);
       if (uploader != null) {
diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml
index 878ec39..9e9fb73 100644
--- a/plugins/gradle/gradle.iml
+++ b/plugins/gradle/gradle.iml
@@ -14,6 +14,7 @@
     <orderEntry type="module" module-name="external-system-impl" exported="" />
     <orderEntry type="module" module-name="gradle-tooling-extension-api" exported="" />
     <orderEntry type="module" module-name="gradle-tooling-extension-impl" />
+    <orderEntry type="module" module-name="gradle-jps-plugin" />
     <orderEntry type="module" module-name="idea-ui" />
     <orderEntry type="module" module-name="lang-api" />
     <orderEntry type="module" module-name="compiler-openapi" />
@@ -105,6 +106,9 @@
     <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
     <orderEntry type="module" module-name="junit" />
     <orderEntry type="module" module-name="smRunner" />
+    <orderEntry type="library" name="Kryo" level="project" />
+    <orderEntry type="library" name="Ant" level="project" />
+    <orderEntry type="library" name="gson" level="project" />
   </component>
 </module>
 
diff --git a/plugins/gradle/jps-plugin/gradle-jps-plugin.iml b/plugins/gradle/jps-plugin/gradle-jps-plugin.iml
new file mode 100644
index 0000000..0d1d530
--- /dev/null
+++ b/plugins/gradle/jps-plugin/gradle-jps-plugin.iml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="util" />
+    <orderEntry type="module" module-name="jps-builders" />
+    <orderEntry type="module" module-name="jps-model-impl" />
+    <orderEntry type="module" module-name="jps-model-api" />
+    <orderEntry type="module" module-name="jps-model-serialization" />
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/../lib/gradle-tooling-api-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-core-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-messaging-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-wrapper-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-groovy-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-native-2.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-resources-2.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES>
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/tooling-api/src/main/java" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/core/src/main/groovy" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/messaging/src/main/java" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/wrapper/src/main/java" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/base-services/src/main/java" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/base-services-groovy/src/main/groovy" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/native/src/main/java" />
+          <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/resources/src/main/java" />
+        </SOURCES>
+      </library>
+    </orderEntry>
+    <orderEntry type="library" exported="" name="Ant" level="project" />
+    <orderEntry type="library" name="gson" level="project" />
+  </component>
+</module>
+
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService
new file mode 100644
index 0000000..526afcc
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService
@@ -0,0 +1,16 @@
+#
+# 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.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleExtensionServiceImpl
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
new file mode 100644
index 0000000..90e686d
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
@@ -0,0 +1,16 @@
+#
+# 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.
+#
+org.jetbrains.jps.gradle.compiler.GradleBuilderService
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory
new file mode 100644
index 0000000..f1518a3
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory
@@ -0,0 +1,16 @@
+#
+# 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.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleDependenciesEnumerationHandler$GradleFactory
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
new file mode 100644
index 0000000..a86ddcf
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
@@ -0,0 +1,16 @@
+#
+# 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.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleModelSerializationExtension
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java
new file mode 100644
index 0000000..c717fe1
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import org.gradle.api.Transformer;
+import org.gradle.util.ConfigureUtil;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootFilter;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+
+import java.io.File;
+import java.io.FilterReader;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/24/2014
+ */
+public class ChainingFilterTransformer implements Transformer<Reader, Reader> {
+  private final Collection<ResourceRootFilter> myFilters = new ArrayList<ResourceRootFilter>();
+  private final CompileContext myContext;
+  private final Ref<File> myOutputFileRef;
+
+
+  public ChainingFilterTransformer(CompileContext context, Collection<ResourceRootFilter> filters, Ref<File> outputFileRef) {
+    myContext = context;
+    myOutputFileRef = outputFileRef;
+    myFilters.addAll(filters);
+  }
+
+  public ChainingFilterTransformer(CompileContext context, Collection<ResourceRootFilter> filters) {
+    this(context, filters, null);
+  }
+
+  public void addAll(Collection<ResourceRootFilter> filters) {
+    myFilters.addAll(filters);
+  }
+
+  public void add(ResourceRootFilter... filters) {
+    Collections.addAll(myFilters, filters);
+  }
+
+  @Override
+  public Reader transform(Reader original) {
+    Reader value = original;
+    for (ResourceRootFilter filter : myFilters) {
+      value = doTransform(filter, value);
+    }
+    return value;
+  }
+
+  private Reader doTransform(ResourceRootFilter filter, Reader original) {
+    if ("RenamingCopyFilter" .equals(filter.filterType)) {
+      final Matcher matcher = (Matcher)filter.getProperties().get("matcher");
+      final String replacement = (String)filter.getProperties().get("replacement");
+      if (matcher == null || replacement == null) return original;
+
+      matcher.reset(myOutputFileRef.get().getName());
+      if (matcher.find()) {
+        final String newFileName = matcher.replaceFirst(replacement);
+        myOutputFileRef.set(new File(myOutputFileRef.get().getParentFile(), newFileName));
+      }
+      return original;
+    }
+    try {
+      Class<?> clazz = Class.forName(filter.filterType);
+      if (!FilterReader.class.isAssignableFrom(clazz)) {
+        myContext.processMessage(
+          new CompilerMessage(
+            GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+            String.format("Error - Invalid filter specification for %s. It should extend java.io.FilterReader.", filter.filterType), null)
+        );
+      }
+      Constructor constructor = clazz.getConstructor(Reader.class);
+      FilterReader result = (FilterReader)constructor.newInstance(original);
+      final Map<Object, Object> properties = filter.getProperties();
+      if (!properties.isEmpty()) {
+        ConfigureUtil.configureByMap(properties, result);
+      }
+      return result;
+    }
+    catch (Throwable th) {
+      myContext.processMessage(new CompilerMessage(
+                                 GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+                                 String.format("Error - Failed to apply filter(%s): %s", filter.filterType, th.getMessage()), null)
+      );
+    }
+    return original;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java
new file mode 100644
index 0000000..5219a2c
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.gradle.model.impl.GradleResourcesTargetType;
+import org.jetbrains.jps.incremental.BuilderService;
+import org.jetbrains.jps.incremental.TargetBuilder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleBuilderService extends BuilderService {
+  @NotNull
+  @Override
+  public List<? extends BuildTargetType<?>> getTargetTypes() {
+    return Arrays.asList(GradleResourcesTargetType.PRODUCTION, GradleResourcesTargetType.TEST);
+  }
+
+  @NotNull
+  @Override
+  public List<? extends TargetBuilder<?, ?>> createBuilders() {
+    return Collections.singletonList(new GradleResourcesBuilder());
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java
new file mode 100644
index 0000000..dadfa21
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import org.apache.tools.ant.util.ReaderInputStream;
+import org.jetbrains.jps.gradle.model.impl.GradleModuleResourceConfiguration;
+import org.jetbrains.jps.gradle.model.impl.GradleProjectConfiguration;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootConfiguration;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootFilter;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.JpsProject;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceFileProcessor {
+  private static final int FILTERING_SIZE_LIMIT = 10 * 1024 * 1024 /*10 mb*/;
+  protected final JpsEncodingProjectConfiguration myEncodingConfig;
+  protected final GradleProjectConfiguration myProjectConfig;
+  protected final GradleModuleResourceConfiguration myModuleConfiguration;
+
+  public GradleResourceFileProcessor(GradleProjectConfiguration projectConfiguration, JpsProject project,
+                                     GradleModuleResourceConfiguration moduleConfiguration) {
+    myProjectConfig = projectConfiguration;
+    myEncodingConfig = JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(project);
+    myModuleConfiguration = moduleConfiguration;
+  }
+
+  public void copyFile(File file, Ref<File> targetFileRef, ResourceRootConfiguration rootConfiguration, CompileContext context,
+                       FileFilter filteringFilter) throws IOException {
+    boolean shouldFilter = rootConfiguration.isFiltered && !rootConfiguration.filters.isEmpty() && filteringFilter.accept(file);
+    if (shouldFilter && file.length() > FILTERING_SIZE_LIMIT) {
+      context.processMessage(new CompilerMessage(
+        GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+        "File is too big to be filtered. Most likely it is a binary file and should be excluded from filtering", file.getPath())
+      );
+      shouldFilter = false;
+    }
+    if (shouldFilter) {
+      copyWithFiltering(file, targetFileRef, rootConfiguration.filters, context);
+    }
+    else {
+      FileUtil.copyContent(file, targetFileRef.get());
+    }
+  }
+
+  private static void copyWithFiltering(File file, Ref<File> outputFileRef, List<ResourceRootFilter> filters, CompileContext context)
+    throws IOException {
+    final FileInputStream originalInputStream = new FileInputStream(file);
+    try {
+      final InputStream inputStream = transform(filters, originalInputStream, outputFileRef, context);
+      FileUtil.createIfDoesntExist(outputFileRef.get());
+      FileOutputStream outputStream = new FileOutputStream(outputFileRef.get());
+      try {
+        FileUtil.copy(inputStream, outputStream);
+      }
+      finally {
+        StreamUtil.closeStream(inputStream);
+        StreamUtil.closeStream(outputStream);
+      }
+    }
+    finally {
+      StreamUtil.closeStream(originalInputStream);
+    }
+  }
+
+  private static InputStream transform(List<ResourceRootFilter> filters, FileInputStream original, Ref<File> outputFileRef, CompileContext context) {
+    return new ReaderInputStream(new ChainingFilterTransformer(context, filters, outputFileRef).transform(new InputStreamReader(original)));
+  }
+}
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java
new file mode 100644
index 0000000..295c8ba
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.gradle.model.impl.*;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.TargetBuilder;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesBuilder extends TargetBuilder<GradleResourceRootDescriptor, GradleResourcesTarget> {
+  public static final String BUILDER_NAME = "Gradle Resources Compiler";
+
+  public GradleResourcesBuilder() {
+    super(Arrays.asList(GradleResourcesTargetType.PRODUCTION, GradleResourcesTargetType.TEST));
+  }
+
+  @Override
+  public void build(@NotNull final GradleResourcesTarget target,
+                    @NotNull final DirtyFilesHolder<GradleResourceRootDescriptor, GradleResourcesTarget> holder,
+                    @NotNull final BuildOutputConsumer outputConsumer,
+                    @NotNull final CompileContext context) throws ProjectBuildException, IOException {
+    final BuildDataPaths dataPaths = context.getProjectDescriptor().dataManager.getDataPaths();
+    final GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+    final GradleModuleResourceConfiguration config = target.getModuleResourcesConfiguration(dataPaths);
+    if (config == null) return;
+
+    final Map<GradleResourceRootDescriptor, List<File>> files = new HashMap<GradleResourceRootDescriptor, List<File>>();
+
+    holder.processDirtyFiles(new FileProcessor<GradleResourceRootDescriptor, GradleResourcesTarget>() {
+
+      @Override
+      public boolean apply(GradleResourcesTarget t, File file, GradleResourceRootDescriptor rd) throws IOException {
+        assert target == t;
+
+        List<File> fileList = files.get(rd);
+        if (fileList == null) {
+          fileList = new ArrayList<File>();
+          files.put(rd, fileList);
+        }
+
+        fileList.add(file);
+        return true;
+      }
+    });
+
+    GradleResourceRootDescriptor[] roots = files.keySet().toArray(new GradleResourceRootDescriptor[files.keySet().size()]);
+    Arrays.sort(roots, new Comparator<GradleResourceRootDescriptor>() {
+      @Override
+      public int compare(GradleResourceRootDescriptor r1, GradleResourceRootDescriptor r2) {
+        int res = r1.getIndexInPom() - r2.getIndexInPom();
+        if (r1.isOverwrite()) {
+          assert r2.isOverwrite();
+          return res;
+        }
+
+        if (r1.getConfiguration().isFiltered && !r2.getConfiguration().isFiltered) return 1;
+        if (!r1.getConfiguration().isFiltered && r2.getConfiguration().isFiltered) return -1;
+
+        if (!r1.getConfiguration().isFiltered) {
+          res = -res;
+        }
+
+        return res;
+      }
+    });
+
+    GradleResourceFileProcessor fileProcessor = new GradleResourceFileProcessor(projectConfig, target.getModule().getProject(), config);
+
+    for (GradleResourceRootDescriptor rd : roots) {
+      for (File file : files.get(rd)) {
+
+        String relPath = FileUtil.getRelativePath(rd.getRootFile(), file);
+        if (relPath == null) continue;
+
+        final File outputDir =
+          GradleResourcesTarget.getOutputDir(target.getModuleOutputDir(), rd.getConfiguration(), config.outputDirectory);
+        if (outputDir == null) continue;
+
+        context.processMessage(new ProgressMessage("Copying resources... [" + target.getModule().getName() + "]"));
+
+        final Ref<File> fileRef = Ref.create(new File(outputDir, relPath));
+        fileProcessor.copyFile(file, fileRef, rd.getConfiguration(), context, FileUtilRt.ALL_FILES);
+        outputConsumer.registerOutputFile(fileRef.get(), Collections.singleton(file.getPath()));
+
+        if (context.getCancelStatus().isCanceled()) return;
+      }
+    }
+
+    context.checkCanceled();
+    context.processMessage(new ProgressMessage(""));
+  }
+
+  @NotNull
+  public String getPresentableName() {
+    return BUILDER_NAME;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java
new file mode 100644
index 0000000..126cf57
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.impl.GradleProjectConfiguration;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public abstract class JpsGradleExtensionService {
+  public static JpsGradleExtensionService getInstance() {
+    return JpsServiceManager.getInstance().getService(JpsGradleExtensionService.class);
+  }
+
+  @Nullable
+  public abstract JpsGradleModuleExtension getExtension(@NotNull JpsModule module);
+
+  @NotNull
+  public abstract JpsGradleModuleExtension getOrCreateExtension(@NotNull JpsModule module);
+
+  public abstract void setProductionOnTestDependency(@NotNull JpsDependencyElement dependency, boolean value);
+
+  public abstract boolean isProductionOnTestDependency(@NotNull JpsDependencyElement dependency);
+
+  public abstract boolean hasGradleProjectConfiguration(@NotNull BuildDataPaths paths);
+
+  @NotNull
+  public abstract GradleProjectConfiguration getGradleProjectConfiguration(BuildDataPaths paths);
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java
new file mode 100644
index 0000000..c673e4c
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public interface JpsGradleModuleExtension extends JpsElement {
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java
new file mode 100644
index 0000000..98938f5
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Tag;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class FilePattern {
+
+  @Tag("includes")
+  @AbstractCollection(surroundWithTag =  false, elementTag = "pattern")
+  public Set<String> includes = new HashSet<String>();
+
+  @Tag("excludes")
+  @AbstractCollection(surroundWithTag =  false, elementTag = "pattern")
+  public Set<String> excludes = new HashSet<String>();
+
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java
new file mode 100644
index 0000000..9b6732a
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.OptionTag;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleModuleResourceConfiguration {
+  @NotNull
+  @Tag("id")
+  public ModuleVersion id;
+
+  @Nullable
+  @Tag("parentId")
+  public ModuleVersion parentId;
+
+  @NotNull
+  @Tag("directory")
+  public String directory;
+
+  @OptionTag
+  public boolean overwrite;
+
+  @OptionTag
+  public String outputDirectory = null;
+
+  @Tag("resources")
+  @AbstractCollection(surroundWithTag = false, elementTag = "resource")
+  public List<ResourceRootConfiguration> resources = new ArrayList<ResourceRootConfiguration>();
+
+  @Tag("test-resources")
+  @AbstractCollection(surroundWithTag = false, elementTag = "resource")
+  public List<ResourceRootConfiguration> testResources = new ArrayList<ResourceRootConfiguration>();
+
+  public int computeConfigurationHash(boolean forTestResources) {
+    int result = computeModuleConfigurationHash();
+
+    final List<ResourceRootConfiguration> _resources = forTestResources ? testResources : resources;
+    result = 31 * result;
+    for (ResourceRootConfiguration resource : _resources) {
+      result += resource.computeConfigurationHash();
+    }
+    return result;
+  }
+
+  public int computeModuleConfigurationHash() {
+    int result = id.hashCode();
+    result = 31 * result + (parentId != null ? parentId.hashCode() : 0);
+    result = 31 * result + directory.hashCode();
+    result = 31 * result + (outputDirectory != null ? outputDirectory.hashCode() : 0);
+    result = 31 * result + (overwrite ? 1 : 0);
+    return result;
+  }
+}
+
+
+
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java
new file mode 100644
index 0000000..083bba5
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.MapAnnotation;
+import com.intellij.util.xmlb.annotations.Tag;
+import gnu.trove.THashMap;
+
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleProjectConfiguration {
+  public static final String CONFIGURATION_FILE_RELATIVE_PATH = "gradle/configuration.xml";
+
+  @Tag("resource-processing")
+  @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false, entryTagName = "gradle-module",
+                 keyAttributeName = "name")
+  public Map<String, GradleModuleResourceConfiguration> moduleConfigurations = new THashMap<String, GradleModuleResourceConfiguration>();
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java
new file mode 100644
index 0000000..60e7fd2
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.pattern.PatternMatcherFactory;
+import org.gradle.api.specs.Spec;
+import org.gradle.api.specs.Specs;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceFileFilter implements FileFilter {
+  private FilePattern myFilePattern;
+  private File myRoot;
+  private final Spec<RelativePath> myFileFilterSpec;
+
+  public GradleResourceFileFilter(@NotNull File rootFile, @NotNull FilePattern filePattern) {
+    myFilePattern = filePattern;
+    myRoot = rootFile;
+    myFileFilterSpec = getAsSpec();
+  }
+
+  @Override
+  public boolean accept(@NotNull File file) {
+    final String relPath = FileUtil.getRelativePath(myRoot, file);
+    return relPath != null && isIncluded(relPath);
+  }
+
+  private boolean isIncluded(@NotNull String relativePath) {
+    RelativePath path = new RelativePath(true, relativePath.split(Pattern.quote(File.separator)));
+    return myFileFilterSpec.isSatisfiedBy(path);
+  }
+
+  private Spec<RelativePath> getAsSpec() {
+    return Specs.and(getAsIncludeSpec(true), Specs.not(getAsExcludeSpec(true)));
+  }
+
+  private Spec<RelativePath> getAsExcludeSpec(boolean caseSensitive) {
+    Collection<String> allExcludes = new LinkedHashSet<String>(myFilePattern.excludes);
+    List<Spec<RelativePath>> matchers = new ArrayList<Spec<RelativePath>>();
+    for (String exclude : allExcludes) {
+      Spec<RelativePath> patternMatcher = PatternMatcherFactory.getPatternMatcher(false, caseSensitive, exclude);
+      matchers.add(patternMatcher);
+    }
+    return Specs.or(false, matchers);
+  }
+
+  private Spec<RelativePath> getAsIncludeSpec(boolean caseSensitive) {
+    List<Spec<RelativePath>> matchers = new ArrayList<Spec<RelativePath>>();
+    for (String include : myFilePattern.includes) {
+      Spec<RelativePath> patternMatcher = PatternMatcherFactory.getPatternMatcher(true, caseSensitive, include);
+      matchers.add(patternMatcher);
+    }
+    return Specs.or(true, matchers);
+  }
+}
\ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java
new file mode 100644
index 0000000..e8ae0d7
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceRootDescriptor extends BuildRootDescriptor {
+  private final GradleResourcesTarget myTarget;
+  private final ResourceRootConfiguration myConfig;
+  private final File myFile;
+  private final String myId;
+  private final boolean myOverwrite;
+
+  private final int myIndexInPom;
+
+  public GradleResourceRootDescriptor(@NotNull GradleResourcesTarget target,
+                                      ResourceRootConfiguration config,
+                                      int indexInPom,
+                                      boolean overwrite) {
+    myTarget = target;
+    myConfig = config;
+    final String path = FileUtil.toCanonicalPath(config.directory);
+    myFile = new File(path);
+    myId = path;
+    myIndexInPom = indexInPom;
+    myOverwrite = overwrite;
+  }
+
+  public ResourceRootConfiguration getConfiguration() {
+    return myConfig;
+  }
+
+  @Override
+  public String getRootId() {
+    return myId;
+  }
+
+  @Override
+  public File getRootFile() {
+    return myFile;
+  }
+
+  @Override
+  public GradleResourcesTarget getTarget() {
+    return myTarget;
+  }
+
+  @NotNull
+  @Override
+  public FileFilter createFileFilter() {
+    return new GradleResourceFileFilter(myFile, myConfig);
+  }
+
+  @Override
+  public boolean canUseFileCache() {
+    return true;
+  }
+
+  public int getIndexInPom() {
+    return myIndexInPom;
+  }
+
+  public boolean isOverwrite() {
+    return myOverwrite;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java
new file mode 100644
index 0000000..344c830
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesTarget extends ModuleBasedTarget<GradleResourceRootDescriptor> {
+
+  GradleResourcesTarget(final GradleResourcesTargetType type, @NotNull JpsModule module) {
+    super(type, module);
+  }
+
+  @Override
+  public String getId() {
+    return myModule.getName();
+  }
+
+  @Override
+  public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public boolean isCompiledBeforeModuleLevelBuilders() {
+    return true;
+  }
+
+  @NotNull
+  @Override
+  public List<GradleResourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex, BuildDataPaths dataPaths) {
+    final List<GradleResourceRootDescriptor> result = new ArrayList<GradleResourceRootDescriptor>();
+
+    GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+    GradleModuleResourceConfiguration moduleConfig = projectConfig.moduleConfigurations.get(myModule.getName());
+    if (moduleConfig == null) return Collections.emptyList();
+
+    int i = 0;
+
+    for (ResourceRootConfiguration resource : getRootConfigurations(moduleConfig)) {
+      result.add(new GradleResourceRootDescriptor(this, resource, i++, moduleConfig.overwrite));
+    }
+    return result;
+  }
+
+  private Collection<ResourceRootConfiguration> getRootConfigurations(@Nullable GradleModuleResourceConfiguration moduleConfig) {
+    if (moduleConfig != null) {
+      return isTests() ? moduleConfig.testResources : moduleConfig.resources;
+    }
+    return Collections.emptyList();
+  }
+
+  public GradleModuleResourceConfiguration getModuleResourcesConfiguration(BuildDataPaths dataPaths) {
+    final GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+    return projectConfig.moduleConfigurations.get(myModule.getName());
+  }
+
+  public boolean isTests() {
+    return ((GradleResourcesTargetType)getTargetType()).isTests();
+  }
+
+  @Nullable
+  @Override
+  public GradleResourceRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
+    for (GradleResourceRootDescriptor descriptor : rootIndex.getTargetRoots(this, null)) {
+      if (descriptor.getRootId().equals(rootId)) {
+        return descriptor;
+      }
+    }
+    return null;
+  }
+
+  @NotNull
+  @Override
+  public String getPresentableName() {
+    return getTargetType().getTypeId() + ":" + myModule.getName();
+  }
+
+  @NotNull
+  @Override
+  public Collection<File> getOutputRoots(CompileContext context) {
+    GradleModuleResourceConfiguration configuration =
+      getModuleResourcesConfiguration(context.getProjectDescriptor().dataManager.getDataPaths());
+    final Set<File> result = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+    final File moduleOutput = getModuleOutputDir();
+    for (ResourceRootConfiguration resConfig : getRootConfigurations(configuration)) {
+      final File output = getOutputDir(moduleOutput, resConfig, configuration.outputDirectory);
+      if (output != null) {
+        result.add(output);
+      }
+    }
+    return result;
+  }
+
+  @Nullable
+  public File getModuleOutputDir() {
+    return JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, isTests());
+  }
+
+  @Nullable
+  public static File getOutputDir(@Nullable File moduleOutput, ResourceRootConfiguration config, @Nullable String outputDirectory) {
+    if(outputDirectory != null) {
+      moduleOutput = JpsPathUtil.urlToFile(outputDirectory);
+    }
+
+    if (moduleOutput == null) {
+      return null;
+    }
+    String targetPath = config.targetPath;
+    if (StringUtil.isEmptyOrSpaces(targetPath)) {
+      return moduleOutput;
+    }
+    final File targetPathFile = new File(targetPath);
+    final File outputFile = targetPathFile.isAbsolute() ? targetPathFile : new File(moduleOutput, targetPath);
+    return new File(FileUtil.toCanonicalPath(outputFile.getPath()));
+  }
+
+  @Override
+  public void writeConfiguration(ProjectDescriptor pd, PrintWriter out) {
+    final BuildDataPaths dataPaths = pd.getTargetsState().getDataPaths();
+    final GradleModuleResourceConfiguration configuration = getModuleResourcesConfiguration(dataPaths);
+    if (configuration != null) {
+      out.write(Integer.toHexString(configuration.computeConfigurationHash(isTests())));
+    }
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java
new file mode 100644
index 0000000..bd399a1
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.ModuleBasedBuildTargetType;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesTargetType extends ModuleBasedBuildTargetType<GradleResourcesTarget> {
+  public static final GradleResourcesTargetType PRODUCTION = new GradleResourcesTargetType("gradle-resources-production", false);
+  public static final GradleResourcesTargetType TEST = new GradleResourcesTargetType("gradle-resources-test", true);
+
+  private final boolean myIsTests;
+
+  private GradleResourcesTargetType(final String typeId, boolean isTests) {
+    super(typeId);
+    myIsTests = isTests;
+  }
+
+  public boolean isTests() {
+    return myIsTests;
+  }
+
+  @NotNull
+  @Override
+  public List<GradleResourcesTarget> computeAllTargets(@NotNull JpsModel model) {
+    final List<GradleResourcesTarget> targets = new ArrayList<GradleResourcesTarget>();
+    for (JpsModule module : model.getProject().getModules()) {
+      if (JpsGradleExtensionService.getInstance().getExtension(module) != null) {
+        targets.add(new GradleResourcesTarget(this, module));
+      }
+    }
+    return targets;
+  }
+
+  @NotNull
+  @Override
+  public BuildTargetLoader<GradleResourcesTarget> createLoader(@NotNull JpsModel model) {
+    final Map<String, JpsModule> modules = new HashMap<String, JpsModule>();
+    for (JpsModule module : model.getProject().getModules()) {
+      modules.put(module.getName(), module);
+    }
+    return new BuildTargetLoader<GradleResourcesTarget>() {
+      @Nullable
+      @Override
+      public GradleResourcesTarget createTarget(@NotNull String targetId) {
+        final JpsModule module = modules.get(targetId);
+        return module != null ? new GradleResourcesTarget(GradleResourcesTargetType.this, module) : null;
+      }
+    };
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java
new file mode 100644
index 0000000..af0fd08
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.Collection;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleDependenciesEnumerationHandler extends JpsJavaDependenciesEnumerationHandler {
+  private static final JpsGradleDependenciesEnumerationHandler INSTANCE = new JpsGradleDependenciesEnumerationHandler();
+
+  @Override
+  public boolean shouldAddRuntimeDependenciesToTestCompilationClasspath() {
+    return true;
+  }
+
+  @Override
+  public boolean isProductionOnTestsDependency(JpsDependencyElement element) {
+    return JpsGradleExtensionService.getInstance().isProductionOnTestDependency(element);
+  }
+
+  public static class GradleFactory extends Factory {
+    @Nullable
+    @Override
+    public JpsJavaDependenciesEnumerationHandler createHandler(@NotNull Collection<JpsModule> modules) {
+      JpsGradleExtensionService service = JpsGradleExtensionService.getInstance();
+      for (JpsModule module : modules) {
+        if (service.getExtension(module) != null) {
+          return INSTANCE;
+        }
+      }
+      return null;
+    }
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java
new file mode 100644
index 0000000..81ed907
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.util.xmlb.XmlSerializer;
+import gnu.trove.THashMap;
+import org.jdom.Document;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.gradle.model.JpsGradleModuleExtension;
+import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
+import org.jetbrains.jps.incremental.resources.StandardResourceBuilderEnabler;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleExtensionServiceImpl extends JpsGradleExtensionService {
+  private static final Logger LOG = Logger.getInstance(JpsGradleExtensionServiceImpl.class);
+  private static final JpsElementChildRole<JpsSimpleElement<Boolean>> PRODUCTION_ON_TEST_ROLE = JpsElementChildRoleBase.create("production on test");
+  private final Map<File, GradleProjectConfiguration> myLoadedConfigs =
+    new THashMap<File, GradleProjectConfiguration>(FileUtil.FILE_HASHING_STRATEGY);
+  private final FactoryMap<File, Boolean> myConfigFileExists = new ConcurrentFactoryMap<File, Boolean>() {
+    @Nullable
+    @Override
+    protected Boolean create(File key) {
+      return key.exists();
+    }
+  };
+
+  public JpsGradleExtensionServiceImpl() {
+    ResourcesBuilder.registerEnabler(new StandardResourceBuilderEnabler() {
+      @Override
+      public boolean isResourceProcessingEnabled(JpsModule module) {
+        // enable standard resource processing only if this is not a gradle module
+        // for gradle modules use gradle-aware resource builder
+        return getExtension(module) == null;
+      }
+    });
+  }
+
+  @Nullable
+  @Override
+  public JpsGradleModuleExtension getExtension(@NotNull JpsModule module) {
+    return module.getContainer().getChild(JpsGradleModuleExtensionImpl.ROLE);
+  }
+
+  @NotNull
+  @Override
+  public JpsGradleModuleExtension getOrCreateExtension(@NotNull JpsModule module) {
+    JpsGradleModuleExtension extension = module.getContainer().getChild(JpsGradleModuleExtensionImpl.ROLE);
+    if (extension == null) {
+      extension = new JpsGradleModuleExtensionImpl();
+      module.getContainer().setChild(JpsGradleModuleExtensionImpl.ROLE, extension);
+    }
+    return extension;
+  }
+
+  @Override
+  public void setProductionOnTestDependency(@NotNull JpsDependencyElement dependency, boolean value) {
+    if (value) {
+      dependency.getContainer().setChild(PRODUCTION_ON_TEST_ROLE, JpsElementFactory.getInstance().createSimpleElement(true));
+    }
+    else {
+      dependency.getContainer().removeChild(PRODUCTION_ON_TEST_ROLE);
+    }
+  }
+
+  @Override
+  public boolean isProductionOnTestDependency(@NotNull JpsDependencyElement dependency) {
+    JpsSimpleElement<Boolean> child = dependency.getContainer().getChild(PRODUCTION_ON_TEST_ROLE);
+    return child != null && child.getData();
+  }
+
+  @Override
+  public boolean hasGradleProjectConfiguration(@NotNull BuildDataPaths paths) {
+    return myConfigFileExists.get(new File(paths.getDataStorageRoot(), GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH));
+  }
+
+  @NotNull
+  @Override
+  public GradleProjectConfiguration getGradleProjectConfiguration(BuildDataPaths paths) {
+    final File dataStorageRoot = paths.getDataStorageRoot();
+    return getGradleProjectConfiguration(dataStorageRoot);
+  }
+
+  @NotNull
+  public GradleProjectConfiguration getGradleProjectConfiguration(@NotNull File dataStorageRoot) {
+    final File configFile = new File(dataStorageRoot, GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+    GradleProjectConfiguration config;
+    synchronized (myLoadedConfigs) {
+      config = myLoadedConfigs.get(configFile);
+      if (config == null) {
+        config = new GradleProjectConfiguration();
+        try {
+          final Document document = JDOMUtil.loadDocument(configFile);
+          XmlSerializer.deserializeInto(config, document.getRootElement());
+        }
+        catch (Exception e) {
+          LOG.info(e);
+        }
+        myLoadedConfigs.put(configFile, config);
+      }
+    }
+    return config;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java
new file mode 100644
index 0000000..cebd008
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleModelSerializationExtension extends JpsModelSerializerExtension {
+  private static final String PRODUCTION_ON_TEST_ATTRIBUTE = "production-on-test";
+
+  @Override
+  public void loadModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+    if ("GRADLE".equals(rootElement.getAttributeValue("external.system.id"))) {
+      JpsGradleExtensionService.getInstance().getOrCreateExtension(module);
+    }
+  }
+
+  @Override
+  public void saveModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+    if (JpsGradleExtensionService.getInstance().getExtension(module) != null) {
+      rootElement.setAttribute("external.system.id", "GRADLE");
+    }
+  }
+
+  @Override
+  public void loadModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+    if (orderEntry.getAttributeValue(PRODUCTION_ON_TEST_ATTRIBUTE) != null) {
+      JpsGradleExtensionService.getInstance().setProductionOnTestDependency(dependency, true);
+    }
+  }
+
+  @Override
+  public void saveModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+    if (JpsGradleExtensionService.getInstance().isProductionOnTestDependency(dependency)) {
+      orderEntry.setAttribute(PRODUCTION_ON_TEST_ATTRIBUTE, "");
+    }
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java
new file mode 100644
index 0000000..ecdd04f
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.gradle.model.JpsGradleModuleExtension;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleModuleExtensionImpl extends JpsElementBase<JpsGradleModuleExtensionImpl> implements JpsGradleModuleExtension {
+  public static final JpsElementChildRole<JpsGradleModuleExtension> ROLE = JpsElementChildRoleBase.create("gradle");
+
+  public JpsGradleModuleExtensionImpl() {
+  }
+
+  @NotNull
+  @Override
+  public JpsGradleModuleExtensionImpl createCopy() {
+    return new JpsGradleModuleExtensionImpl();
+  }
+
+  @Override
+  public void applyChanges(@NotNull JpsGradleModuleExtensionImpl modified) {
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java
new file mode 100644
index 0000000..dbb696d
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.Tag;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class ModuleVersion {
+  @Tag("groupId")
+  public String groupId;
+
+  @Tag("artifactId")
+  public String artifactId;
+
+  @Tag("version")
+  public String version;
+
+  public ModuleVersion() {
+  }
+
+  public ModuleVersion(String groupId, String artifactId, String version) {
+    this.groupId = groupId;
+    this.artifactId = artifactId;
+    this.version = version;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ModuleVersion bean = (ModuleVersion)o;
+
+    if (artifactId != null ? !artifactId.equals(bean.artifactId) : bean.artifactId != null) return false;
+    if (groupId != null ? !groupId.equals(bean.groupId) : bean.groupId != null) return false;
+    if (version != null ? !version.equals(bean.version) : bean.version != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = groupId != null ? groupId.hashCode() : 0;
+    result = 31 * result + (artifactId != null ? artifactId.hashCode() : 0);
+    result = 31 * result + (version != null ? version.hashCode() : 0);
+    return result;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java
new file mode 100644
index 0000000..efd4191
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+@Tag("resource")
+public class ResourceRootConfiguration extends FilePattern {
+  @Tag("directory")
+  @NotNull
+  public String directory;
+
+  @Tag("targetPath")
+  @Nullable
+  public String targetPath;
+
+  @Attribute("filtered")
+  public boolean isFiltered;
+
+  @Tag("filters")
+  @AbstractCollection(surroundWithTag = false, elementTag = "filter")
+  public List<ResourceRootFilter> filters = new ArrayList<ResourceRootFilter>();
+
+  public int computeConfigurationHash() {
+    int result = directory.hashCode();
+    result = 31 * result + (targetPath != null ? targetPath.hashCode() : 0);
+    result = 31 * result + (isFiltered ? 1 : 0);
+    result = 31 * result + includes.hashCode();
+    result = 31 * result + excludes.hashCode();
+    for (ResourceRootFilter filter : filters) {
+       result = 31 * result + filter.computeConfigurationHash();
+    }
+    return result;
+  }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java
new file mode 100644
index 0000000..e8c39e3
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+@Tag("filter")
+public class ResourceRootFilter {
+  @Tag("filterType")
+  @NotNull
+  public String filterType;
+  @Tag("properties")
+  @NotNull
+  public String properties;
+
+  private transient Map<Object, Object> propertiesMap;
+
+  public int computeConfigurationHash() {
+    int result = filterType.hashCode();
+    result = 31 * result + properties.hashCode();
+    return result;
+  }
+
+  @NotNull
+  public Map<Object, Object> getProperties() {
+    if (propertiesMap == null) {
+      try {
+        Gson gson = new GsonBuilder().create();
+        propertiesMap = gson.fromJson(
+          properties,
+          new TypeToken<Map<Object, Object>>() {
+          }.getType());
+
+        if("RenamingCopyFilter".equals(filterType)) {
+          final Object pattern = propertiesMap.get("pattern");
+          final Matcher matcher = Pattern.compile(pattern instanceof String ? (String)pattern : "").matcher("");
+          propertiesMap.put("matcher", matcher);
+        }
+      }
+      catch (JsonSyntaxException e) {
+        throw new RuntimeException("Unsupported filter: " + properties , e);
+      } catch (JsonParseException e) {
+        throw new RuntimeException("Unsupported filter: " + properties , e);
+      }
+    }
+    return propertiesMap;
+  }
+}
diff --git a/plugins/gradle/src/META-INF/gradle-maven-integration.xml b/plugins/gradle/src/META-INF/gradle-maven-integration.xml
index 72f46b7..b8fad2f 100644
--- a/plugins/gradle/src/META-INF/gradle-maven-integration.xml
+++ b/plugins/gradle/src/META-INF/gradle-maven-integration.xml
@@ -21,7 +21,6 @@
     <postStartupActivity implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleProjectStartupActivity"/>
     <externalSystemTaskNotificationListener
         implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleMavenProjectImportNotificationListener"/>
-    <externalProjectDataService implementation="com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService"/>
     <completion.contributor language="Groovy" order="first"
                             implementationClass="org.jetbrains.plugins.gradle.integrations.maven.codeInsight.completion.MavenDependenciesGradleCompletionContributor"/>
   </extensions>
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index de6937c..f15f424 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -67,6 +67,11 @@
   <extensions defaultExtensionNs="com.intellij">
 
     <postStartupActivity implementation="org.jetbrains.plugins.gradle.service.project.GradleStartupActivity"/>
+
+    <orderEnumerationHandlerFactory implementation="org.jetbrains.plugins.gradle.execution.GradleOrderEnumeratorHandler$FactoryImpl"/>
+    <compileServer.plugin classpath="gradle-jps-plugin.jar"/>
+    <buildProcess.parametersProvider implementation="org.jetbrains.plugins.gradle.compiler.GradleBuildProcessParametersProvider"/>
+
     <resolveScopeEnlarger implementation="org.jetbrains.plugins.gradle.config.GradleBuildClasspathResolveScopeEnlarger"/>
 
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
@@ -95,6 +100,7 @@
     <externalSystemConfigLocator implementation="org.jetbrains.plugins.gradle.service.settings.GradleConfigLocator"/>
     <externalSystemManager implementation="org.jetbrains.plugins.gradle.GradleManager"/>
     <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.BuildClasspathModuleGradleDataService"/>
+    <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService"/>
     <externalSystemNotificationExtension implementation="org.jetbrains.plugins.gradle.service.notification.GradleNotificationExtension" order="last"/>
     <externalSystemTaskNotificationListener implementation="org.jetbrains.plugins.gradle.service.project.GradleProjectImportNotificationListener"/>
 
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java
new file mode 100644
index 0000000..4337686
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import com.google.gson.Gson;
+import com.intellij.compiler.server.BuildProcessParametersProvider;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtil;
+import com.intellij.util.containers.ContainerUtil;
+import groovy.lang.GroovyObject;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.gradle.tooling.ProjectConnection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Adds Gradle build dependencies to the project build process' classpath.
+ *
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+public class GradleBuildProcessParametersProvider extends BuildProcessParametersProvider {
+  @NotNull private final Project myProject;
+
+  private List<String> myClasspath;
+
+  public GradleBuildProcessParametersProvider(@NotNull Project project) {
+    myProject = project;
+  }
+
+  @Override
+  @NotNull
+  public List<String> getClassPath() {
+    if (myClasspath == null) {
+      myClasspath = ContainerUtil.newArrayList();
+      addGradleClassPath(myClasspath);
+      final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
+      for (Module module : moduleManager.getModules()) {
+        if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) {
+          addOtherClassPath(myClasspath);
+          break;
+        }
+      }
+    }
+    return myClasspath;
+  }
+
+  private static void addGradleClassPath(@NotNull final List<String> classpath) {
+    String gradleLibDirPath = null;
+    String gradleToolingApiJarPath = PathUtil.getJarPathForClass(ProjectConnection.class);
+    if (!StringUtil.isEmpty(gradleToolingApiJarPath)) {
+      gradleLibDirPath = PathUtil.getParentPath(gradleToolingApiJarPath);
+    }
+    if (gradleLibDirPath == null || gradleLibDirPath.isEmpty()) return;
+
+    File gradleLibDir = new File(gradleLibDirPath);
+    if (!gradleLibDir.isDirectory()) return;
+
+    File[] children = FileUtil.notNullize(gradleLibDir.listFiles());
+    for (File child : children) {
+      if (child.isFile() && child.getName().endsWith(".jar")) {
+        classpath.add(child.getAbsolutePath());
+      }
+    }
+  }
+
+  private static void addOtherClassPath(@NotNull final List<String> classpath) {
+    classpath.add(PathUtil.getJarPathForClass(Ant.class));
+    classpath.add(PathUtil.getJarPathForClass(GroovyObject.class));
+    classpath.add(PathUtil.getJarPathForClass(Gson.class));
+  }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java
new file mode 100644
index 0000000..01c5275
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.config;
+
+import com.intellij.compiler.server.BuildManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.ExternalFilter;
+import com.intellij.openapi.externalSystem.model.ExternalProject;
+import com.intellij.openapi.externalSystem.model.ExternalSourceDirectorySet;
+import com.intellij.openapi.externalSystem.model.ExternalSourceSet;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.CompilerModuleExtension;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.gradle.model.impl.*;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceCompilerConfigurationGenerator {
+
+  private static Logger LOG = Logger.getInstance(GradleResourceCompilerConfigurationGenerator.class);
+
+  @NotNull private final Project myProject;
+  @NotNull private final CompileContext myContext;
+  @NotNull private final Map<String, ExternalProject> myExternalProjectMap;
+  private final ExternalProjectDataService myExternalProjectDataService;
+
+  public GradleResourceCompilerConfigurationGenerator(@NotNull final Project project, @NotNull final CompileContext context) {
+    myProject = project;
+    myContext = context;
+    myExternalProjectDataService =
+      (ExternalProjectDataService)ServiceManager.getService(ProjectDataManager.class).getDataService(ExternalProjectDataService.KEY);
+    assert myExternalProjectDataService != null;
+
+    myExternalProjectMap = new FactoryMap<String, ExternalProject>() {
+      @Nullable
+      @Override
+      protected ExternalProject create(String gradleProjectPath) {
+        return myExternalProjectDataService.getOrImportRootExternalProject(project, GradleConstants.SYSTEM_ID, new File(gradleProjectPath));
+      }
+    };
+  }
+
+  public void generateBuildConfiguration() {
+    if (!hasGradleModules()) return;
+
+    final BuildManager buildManager = BuildManager.getInstance();
+    final File projectSystemDir = buildManager.getProjectSystemDirectory(myProject);
+    if (projectSystemDir == null) return;
+
+    final File gradleConfigFile = new File(projectSystemDir, GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+
+    GradleProjectConfiguration projectConfig = new GradleProjectConfiguration();
+    for (Module module : myContext.getCompileScope().getAffectedModules()) {
+      if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) continue;
+
+      final String gradleProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+      assert gradleProjectPath != null;
+      final ExternalProject externalRootProject = myExternalProjectMap.get(gradleProjectPath);
+      if (externalRootProject == null) {
+        myContext.addMessage(CompilerMessageCategory.ERROR,
+                             String.format("Unable to make the module: %s, related gradle module configuration was not imported",
+                                           module.getName()),
+                             VfsUtilCore.pathToUrl(gradleProjectPath), -1, -1);
+        continue;
+      }
+
+      ExternalProject externalProject = myExternalProjectDataService.findExternalProject(externalRootProject, module);
+      if (externalProject == null) {
+        LOG.warn("Unable to find config for module: " + module.getName());
+        continue;
+      }
+
+      final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
+      assert compilerModuleExtension != null;
+
+      GradleModuleResourceConfiguration resourceConfig = new GradleModuleResourceConfiguration();
+      resourceConfig.id = new ModuleVersion(externalProject.getGroup(), externalProject.getName(), externalProject.getVersion());
+      resourceConfig.directory = FileUtil.toSystemIndependentName(externalProject.getProjectDir().getPath());
+
+      final ExternalSourceSet mainSourcesSet = externalProject.getSourceSets().get("main");
+      addResources(resourceConfig.resources, mainSourcesSet, ExternalSystemSourceType.RESOURCE);
+
+      final ExternalSourceSet testSourcesSet = externalProject.getSourceSets().get("test");
+      addResources(resourceConfig.testResources, testSourcesSet, ExternalSystemSourceType.TEST_RESOURCE);
+
+      projectConfig.moduleConfigurations.put(module.getName(), resourceConfig);
+    }
+
+    final Document document = new Document(new Element("gradle-project-configuration"));
+    XmlSerializer.serializeInto(projectConfig, document.getRootElement());
+    buildManager.runCommand(new Runnable() {
+      @Override
+      public void run() {
+        buildManager.clearState(myProject);
+        FileUtil.createIfDoesntExist(gradleConfigFile);
+        try {
+          JDOMUtil.writeDocument(document, gradleConfigFile, "\n");
+        }
+        catch (IOException e) {
+          throw new RuntimeException(e);
+        }
+      }
+    });
+  }
+
+  private boolean hasGradleModules() {
+    for (Module module : myContext.getCompileScope().getAffectedModules()) {
+      if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return true;
+    }
+    return false;
+  }
+
+  private static void addResources(@NotNull List<ResourceRootConfiguration> container,
+                                   @Nullable ExternalSourceSet externalSourceSet,
+                                   @NotNull ExternalSystemSourceType sourceType) {
+    if (externalSourceSet == null) return;
+    final ExternalSourceDirectorySet directorySet = externalSourceSet.getSources().get(sourceType);
+    if (directorySet == null) return;
+
+    for (File file : directorySet.getSrcDirs()) {
+      final String dir = file.getPath();
+      final ResourceRootConfiguration rootConfiguration = new ResourceRootConfiguration();
+      rootConfiguration.directory = FileUtil.toSystemIndependentName(dir);
+      final String target = directorySet.getOutputDir().getPath();
+      rootConfiguration.targetPath = FileUtil.toSystemIndependentName(target);
+
+      rootConfiguration.includes.clear();
+      for (String include : directorySet.getIncludes()) {
+        rootConfiguration.includes.add(include.trim());
+      }
+      rootConfiguration.excludes.clear();
+      for (String exclude : directorySet.getExcludes()) {
+        rootConfiguration.excludes.add(exclude.trim());
+      }
+
+      rootConfiguration.isFiltered = !directorySet.getFilters().isEmpty();
+      rootConfiguration.filters.clear();
+      for (ExternalFilter filter : directorySet.getFilters()) {
+        final ResourceRootFilter resourceRootFilter = new ResourceRootFilter();
+        resourceRootFilter.filterType = filter.getFilterType();
+        resourceRootFilter.properties = filter.getPropertiesAsJsonMap();
+        rootConfiguration.filters.add(resourceRootFilter);
+      }
+
+      container.add(rootConfiguration);
+    }
+  }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java
new file mode 100644
index 0000000..113e49a
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.execution;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.ExternalProject;
+import com.intellij.openapi.externalSystem.model.ExternalSourceDirectorySet;
+import com.intellij.openapi.externalSystem.model.ExternalSourceSet;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootModel;
+import com.intellij.openapi.roots.OrderEnumerationHandler;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.util.Collection;
+
+public class GradleOrderEnumeratorHandler extends OrderEnumerationHandler {
+  private static final Logger LOG = Logger.getInstance(GradleOrderEnumeratorHandler.class);
+
+  public static class FactoryImpl extends Factory {
+    @Override
+    public boolean isApplicable(@NotNull Project project) {
+      return true;
+    }
+
+    @Override
+    public boolean isApplicable(@NotNull Module module) {
+      return ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module);
+    }
+
+    @Override
+    public OrderEnumerationHandler createHandler(@Nullable Module module) {
+      return INSTANCE;
+    }
+  }
+
+  private static final GradleOrderEnumeratorHandler INSTANCE = new GradleOrderEnumeratorHandler();
+
+  @Override
+  public boolean addCustomModuleRoots(@NotNull OrderRootType type,
+                                      @NotNull ModuleRootModel rootModel,
+                                      @NotNull Collection<String> result,
+                                      boolean includeProduction,
+                                      boolean includeTests) {
+    if (!type.equals(OrderRootType.CLASSES)) return false;
+    if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, rootModel.getModule())) return false;
+
+    final String gradleProjectPath = rootModel.getModule().getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+    if (gradleProjectPath == null) {
+      LOG.error("Root project path of the Gradle project not found for " + rootModel.getModule());
+      return false;
+    }
+
+    final ExternalProjectDataService externalProjectDataService =
+      (ExternalProjectDataService)ServiceManager.getService(ProjectDataManager.class).getDataService(ExternalProjectDataService.KEY);
+
+    assert externalProjectDataService != null;
+    final ExternalProject externalRootProject =
+      externalProjectDataService.getRootExternalProject(GradleConstants.SYSTEM_ID, new File(gradleProjectPath));
+    if (externalRootProject == null) {
+      LOG.debug("Root external project was not yep imported for the project path: " + gradleProjectPath);
+      return false;
+    }
+
+    ExternalProject externalProject = externalProjectDataService.findExternalProject(externalRootProject, rootModel.getModule());
+    if (externalProject == null) return false;
+
+    if (includeProduction) {
+      addOutputRoots(externalProject.getSourceSets().get("main"), ExternalSystemSourceType.RESOURCE, result);
+    }
+
+    if (includeTests) {
+      addOutputRoots(externalProject.getSourceSets().get("test"), ExternalSystemSourceType.TEST_RESOURCE, result);
+    }
+
+    return true;
+  }
+
+  private static void addOutputRoots(@Nullable ExternalSourceSet externalSourceSet,
+                                     @NotNull ExternalSystemSourceType sourceType,
+                                     @NotNull Collection<String> result) {
+    if (externalSourceSet == null) return;
+    final ExternalSourceDirectorySet directorySet = externalSourceSet.getSources().get(sourceType);
+    if (directorySet == null) return;
+
+    result.add(VfsUtilCore.pathToUrl(directorySet.getOutputDir().getAbsolutePath()));
+  }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
index 1d8addd..9603470 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
@@ -28,6 +28,7 @@
 import com.intellij.openapi.util.KeyValue;
 import com.intellij.util.Consumer;
 import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -80,6 +81,11 @@
     return nextResolver.createJavaProjectData();
   }
 
+  @Override
+  public void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject) {
+    nextResolver.populateProjectExtraModels(gradleProject, ideProject);
+  }
+
   @NotNull
   @Override
   public ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index 6f43559..ad7ade6 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -15,14 +15,13 @@
  */
 package org.jetbrains.plugins.gradle.service.project;
 
+import com.google.gson.GsonBuilder;
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.configurations.SimpleJavaParameters;
 import com.intellij.externalSystem.JavaProjectData;
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.externalSystem.model.DataNode;
-import com.intellij.openapi.externalSystem.model.ExternalSystemException;
-import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.*;
 import com.intellij.openapi.externalSystem.model.project.*;
 import com.intellij.openapi.externalSystem.model.task.TaskData;
 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
@@ -56,6 +55,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.gradle.model.*;
 import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
 import org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl;
 import org.jetbrains.plugins.gradle.tooling.internal.init.Init;
 import org.jetbrains.plugins.gradle.util.GradleBundle;
@@ -79,6 +79,8 @@
   private static final Logger LOG = Logger.getInstance("#" + BaseGradleProjectResolverExtension.class.getName());
 
   @NotNull @NonNls private static final String UNRESOLVED_DEPENDENCY_PREFIX = "unresolved dependency - ";
+  private static final String MAIN_SOURCE_SET = "main";
+  private static final String TEST_SOURCE_SET = "test";
 
   @NotNull private ProjectResolverContext resolverCtx;
   @NotNull private final BaseProjectImportErrorHandler myErrorHandler = new BaseProjectImportErrorHandler();
@@ -120,6 +122,14 @@
     return javaProjectData;
   }
 
+  @Override
+  public void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject) {
+    final ExternalProject externalProject = resolverCtx.getExtraProject(ExternalProject.class);
+    if (externalProject != null) {
+      ideProject.createChild(ExternalProjectDataService.KEY, externalProject);
+    }
+  }
+
   @NotNull
   @Override
   public ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData) {
@@ -220,6 +230,8 @@
 
     File sourceCompileOutputPath = null;
     File testCompileOutputPath = null;
+    File resourceCompileOutputPath;
+    File testResourceCompileOutputPath;
     boolean inheritOutputDirs = false;
 
     ModuleData moduleData = ideModule.getData();
@@ -229,30 +241,71 @@
       inheritOutputDirs = moduleCompilerOutput.getInheritOutputDirs();
     }
 
+    ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
+    if (externalProject != null) {
+      externalProject = new DefaultExternalProject(externalProject);
+    }
+
     if (!inheritOutputDirs && (sourceCompileOutputPath == null || testCompileOutputPath == null)) {
-      ModuleExtendedModel moduleExtendedModel = resolverCtx.getExtraProject(gradleModule, ModuleExtendedModel.class);
-      if (moduleExtendedModel != null) {
-        ExtIdeaCompilerOutput output = moduleExtendedModel.getCompilerOutput();
-        if (output != null) {
-          if (sourceCompileOutputPath == null) {
-            sourceCompileOutputPath = output.getMainClassesDir();
-          }
-          if (testCompileOutputPath == null) {
-            testCompileOutputPath = output.getTestClassesDir();
+      sourceCompileOutputPath = getCompileOutputPath(externalProject, MAIN_SOURCE_SET, ExternalSystemSourceType.SOURCE);
+      resourceCompileOutputPath = getCompileOutputPath(externalProject, MAIN_SOURCE_SET, ExternalSystemSourceType.RESOURCE);
+      testCompileOutputPath = getCompileOutputPath(externalProject, TEST_SOURCE_SET, ExternalSystemSourceType.TEST);
+      testResourceCompileOutputPath = getCompileOutputPath(externalProject, TEST_SOURCE_SET, ExternalSystemSourceType.TEST_RESOURCE);
+    }
+    else {
+      resourceCompileOutputPath = sourceCompileOutputPath;
+      testResourceCompileOutputPath = testCompileOutputPath;
+
+      if (externalProject != null) {
+        final ExternalSourceSet mainSourceSet = externalProject.getSourceSets().get(MAIN_SOURCE_SET);
+        if (mainSourceSet != null) {
+          final ExternalSourceDirectorySet resourceDirectories = mainSourceSet.getSources().get(ExternalSystemSourceType.RESOURCE);
+          if (resourceDirectories instanceof DefaultExternalSourceDirectorySet) {
+            ((DefaultExternalSourceDirectorySet)resourceDirectories).setOutputDir(sourceCompileOutputPath);
           }
         }
+        final ExternalSourceSet testSourceSet = externalProject.getSourceSets().get(TEST_SOURCE_SET);
+        if (testSourceSet != null) {
+          final ExternalSourceDirectorySet testResourceDirectories = testSourceSet.getSources().get(ExternalSystemSourceType.TEST_RESOURCE);
+          if (testResourceDirectories instanceof DefaultExternalSourceDirectorySet) {
+            ((DefaultExternalSourceDirectorySet)testResourceDirectories).setOutputDir(testCompileOutputPath);
+          }
+        }
+
+        final DataNode<ProjectData> projectDataNode = ExternalSystemApiUtil.findParent(ideModule, ProjectKeys.PROJECT);
+        assert projectDataNode != null;
+        projectDataNode.createOrReplaceChild(ExternalProjectDataService.KEY, externalProject);
       }
     }
 
     if (sourceCompileOutputPath != null) {
       moduleData.setCompileOutputPath(ExternalSystemSourceType.SOURCE, sourceCompileOutputPath.getAbsolutePath());
     }
+    if (resourceCompileOutputPath != null) {
+      moduleData.setCompileOutputPath(ExternalSystemSourceType.RESOURCE, resourceCompileOutputPath.getAbsolutePath());
+    }
     if (testCompileOutputPath != null) {
       moduleData.setCompileOutputPath(ExternalSystemSourceType.TEST, testCompileOutputPath.getAbsolutePath());
     }
+    if (testResourceCompileOutputPath != null) {
+      moduleData.setCompileOutputPath(ExternalSystemSourceType.TEST_RESOURCE, testResourceCompileOutputPath.getAbsolutePath());
+    }
+
     moduleData.setInheritProjectCompileOutputPath(inheritOutputDirs || sourceCompileOutputPath == null);
   }
 
+  @Nullable
+  private static File getCompileOutputPath(@Nullable ExternalProject externalProject,
+                                           @NotNull String sourceSetName,
+                                           @NotNull ExternalSystemSourceType sourceType) {
+    if (externalProject == null) return null;
+    final ExternalSourceSet sourceSet = externalProject.getSourceSets().get(sourceSetName);
+    if(sourceSet == null) return null;
+
+    final ExternalSourceDirectorySet directorySet = sourceSet.getSources().get(sourceType);
+    return directorySet != null ? directorySet.getOutputDir() : null;
+  }
+
   @Override
   public void populateModuleDependencies(@NotNull IdeaModule gradleModule,
                                          @NotNull DataNode<ModuleData> ideModule,
@@ -319,17 +372,19 @@
   @Override
   public Set<Class> getExtraProjectModelClasses() {
     return ContainerUtil.<Class>set(
-      GradleBuild.class, ModuleExtendedModel.class, BuildScriptClasspathModel.class);
+      GradleBuild.class, ExternalProject.class, ModuleExtendedModel.class, BuildScriptClasspathModel.class);
   }
 
   @NotNull
   @Override
   public Set<Class> getToolingExtensionsClasses() {
     return ContainerUtil.<Class>set(
+      ExternalProject.class,
       // gradle-tooling-extension-api jar
       ProjectImportAction.class,
       // gradle-tooling-extension-impl jar
-      ModelBuildScriptClasspathBuilderImpl.class
+      ModelBuildScriptClasspathBuilderImpl.class,
+      GsonBuilder.class
     );
   }
 
@@ -416,6 +471,8 @@
 
     List<String> additionalEntries = ContainerUtilRt.newArrayList();
     ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(GroovyObject.class));
+    ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(GsonBuilder.class));
+    ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ExternalProject.class));
     ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(JavaProjectData.class));
     ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(LanguageLevel.class));
     ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(StdModuleTypes.class));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
index 8a2ffaa..24c8e12 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
@@ -199,6 +199,9 @@
     projectDataNode.createChild(JavaProjectData.KEY, javaProjectData);
 
     IdeaProject ideaProject = resolverCtx.getModels().getIdeaProject();
+
+    projectResolverChain.populateProjectExtraModels(ideaProject, projectDataNode);
+
     DomainObjectSet<? extends IdeaModule> gradleModules = ideaProject.getModules();
     if (gradleModules == null || gradleModules.isEmpty()) {
       throw new IllegalStateException("No modules found for the target project: " + ideaProject);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
index b727005..6dd201b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
@@ -27,6 +27,7 @@
 import com.intellij.openapi.util.KeyValue;
 import com.intellij.util.Consumer;
 import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.gradle.GradleManager;
@@ -62,6 +63,8 @@
   @NotNull
   JavaProjectData createJavaProjectData();
 
+  void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject);
+
   @NotNull
   ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData);
 
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
index 81ceaa3..0e5fcc1 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
@@ -21,6 +21,11 @@
 import com.intellij.notification.Notification;
 import com.intellij.notification.NotificationListener;
 import com.intellij.notification.NotificationType;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
 import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
@@ -30,6 +35,8 @@
 import com.intellij.openapi.vfs.VfsUtilCore;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.project.MavenResourceCompilerConfigurationGenerator;
+import org.jetbrains.plugins.gradle.config.GradleResourceCompilerConfigurationGenerator;
 import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
 import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportBuilder;
 import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportProvider;
@@ -52,9 +59,22 @@
   private static final String DO_NOT_SHOW_EVENT_DESCRIPTION = "do.not.show";
 
   @Override
-  public void runActivity(@NotNull Project project) {
+  public void runActivity(@NotNull final Project project) {
     configureBuildClasspath(project);
     showNotificationForUnlinkedGradleProject(project);
+    CompilerManager.getInstance(project).addBeforeTask(new CompileTask() {
+      @Override
+      public boolean execute(CompileContext context) {
+        AccessToken token = ReadAction.start();
+        try {
+          new GradleResourceCompilerConfigurationGenerator(project, context).generateBuildConfiguration();
+        }
+        finally {
+          token.finish();
+        }
+        return true;
+      }
+    });
   }
 
   private static void configureBuildClasspath(@NotNull final Project project) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
index b7f94dd..3aa0027 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
 import org.gradle.tooling.ProjectConnection;
 import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.gradle.model.ProjectImportAction;
@@ -93,7 +94,12 @@
   }
 
   @Nullable
-  public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
+  public <T> T getExtraProject(Class<T> modelClazz) {
+    return myModels.getExtraProject(null, modelClazz);
+  }
+
+  @Nullable
+  public <T> T getExtraProject(@Nullable IdeaModule module, Class<T> modelClazz) {
     return myModels.getExtraProject(module, modelClazz);
   }
 
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java
new file mode 100644
index 0000000..fae9ee0
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.service.project.data;
+
+import com.intellij.CommonBundle;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.*;
+import com.intellij.openapi.externalSystem.model.project.ProjectData;
+import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
+import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask;
+import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager;
+import com.intellij.openapi.externalSystem.service.notification.NotificationSource;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService;
+import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
+import com.intellij.openapi.externalSystem.util.*;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/17/2014
+ */
+@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
+public class ExternalProjectDataService implements ProjectDataService<ExternalProject, Project> {
+  private static final Logger LOG = Logger.getInstance(ExternalProjectDataService.class);
+
+  @NotNull public static final Key<ExternalProject> KEY = Key.create(ExternalProject.class, ProjectKeys.TASK.getProcessingWeight() + 1);
+
+  @NotNull private final Map<Pair<ProjectSystemId, File>, ExternalProject> myExternalRootProjects;
+
+  @NotNull private ProjectDataManager myProjectDataManager;
+
+  public ExternalProjectDataService(@NotNull ProjectDataManager projectDataManager) {
+    myProjectDataManager = projectDataManager;
+    myExternalRootProjects = new ConcurrentFactoryMap<Pair<ProjectSystemId, File>, ExternalProject>() {
+      @Nullable
+      @Override
+      protected ExternalProject create(Pair<ProjectSystemId, File> key) {
+        return new ExternalProjectSerializer().load(key.first, key.second);
+      }
+
+      @Override
+      public ExternalProject put(Pair<ProjectSystemId, File> key, ExternalProject value) {
+        new ExternalProjectSerializer().save(value);
+        return super.put(key, value);
+      }
+    };
+  }
+
+  @NotNull
+  @Override
+  public Key<ExternalProject> getTargetDataKey() {
+    return KEY;
+  }
+
+  public void importData(@NotNull final Collection<DataNode<ExternalProject>> toImport,
+                         @NotNull final Project project,
+                         final boolean synchronous) {
+    if (toImport.size() != 1) {
+      throw new IllegalArgumentException(
+        String.format("Expected to get a single external project but got %d: %s", toImport.size(), toImport));
+    }
+    saveExternalProject(toImport.iterator().next().getData());
+  }
+
+  @Override
+  public void removeData(@NotNull final Collection<? extends Project> modules, @NotNull Project project, boolean synchronous) {
+  }
+
+  @Nullable
+  public ExternalProject getOrImportRootExternalProject(@NotNull Project project,
+                                                        @NotNull ProjectSystemId systemId,
+                                                        @NotNull File projectRootDir) {
+    final ExternalProject externalProject = getRootExternalProject(systemId, projectRootDir);
+    return externalProject != null ? externalProject : importExternalProject(project, systemId, projectRootDir);
+  }
+
+  @Nullable
+  private ExternalProject importExternalProject(@NotNull final Project project,
+                                                @NotNull final ProjectSystemId projectSystemId,
+                                                @NotNull final File projectRootDir) {
+    final Boolean result = UIUtil.invokeAndWaitIfNeeded(new Computable<Boolean>() {
+      @Override
+      public Boolean compute() {
+        final Ref<Boolean> result = new Ref<Boolean>(false);
+        if (project.isDisposed()) return false;
+
+        final String linkedProjectPath = FileUtil.toCanonicalPath(projectRootDir.getPath());
+        final ExternalProjectSettings projectSettings =
+          ExternalSystemApiUtil.getSettings(project, projectSystemId).getLinkedProjectSettings(linkedProjectPath);
+        if (projectSettings == null) {
+          LOG.warn("Unable to get project settings for project path: " + linkedProjectPath);
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Available projects paths: " + ContainerUtil.map(
+              ExternalSystemApiUtil.getSettings(project, projectSystemId).getLinkedProjectsSettings(),
+              new Function<ExternalProjectSettings, String>() {
+                @Override
+                public String fun(ExternalProjectSettings settings) {
+                  return settings.getExternalProjectPath();
+                }
+              }));
+          }
+          return false;
+        }
+
+        final File projectFile = new File(linkedProjectPath);
+        final String projectName;
+        if (projectFile.isFile()) {
+          projectName = projectFile.getParentFile().getName();
+        }
+        else {
+          projectName = projectFile.getName();
+        }
+
+        // ask a user for the project import if auto-import is disabled
+        if (!projectSettings.isUseAutoImport()) {
+          String message = String.format("Project '%s' require synchronization with %s configuration. \nImport the project?",
+                                         projectName, projectSystemId.getReadableName());
+          int returnValue = Messages.showOkCancelDialog(
+            message, "Import Project", CommonBundle.getOkButtonText(), CommonBundle.getCancelButtonText(), Messages.getQuestionIcon()
+          );
+          if (returnValue != Messages.OK) return false;
+        }
+
+        final String title = ExternalSystemBundle.message("progress.import.text", linkedProjectPath, projectSystemId.getReadableName());
+        new Task.Modal(project, title, false) {
+          @Override
+          public void run(@NotNull ProgressIndicator indicator) {
+            if (project.isDisposed()) return;
+
+            ExternalSystemNotificationManager.getInstance(project)
+              .clearNotifications(null, NotificationSource.PROJECT_SYNC, projectSystemId);
+            ExternalSystemResolveProjectTask task =
+              new ExternalSystemResolveProjectTask(projectSystemId, project, linkedProjectPath, false);
+            task.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
+            if (project.isDisposed()) return;
+
+            final Throwable error = task.getError();
+            if (error != null) {
+              ExternalSystemNotificationManager.getInstance(project)
+                .processExternalProjectRefreshError(error, projectName, projectSystemId);
+              return;
+            }
+            final DataNode<ProjectData> projectDataDataNode = task.getExternalProject();
+            if (projectDataDataNode == null) return;
+
+            final Collection<DataNode<ExternalProject>> nodes = ExternalSystemApiUtil.findAll(projectDataDataNode, KEY);
+            if (nodes.size() != 1) {
+              throw new IllegalArgumentException(
+                String.format("Expected to get a single external project but got %d: %s", nodes.size(), nodes));
+            }
+
+            ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring(new Runnable() {
+              @Override
+              public void run() {
+                myProjectDataManager.importData(KEY, nodes, project, true);
+              }
+            });
+
+            result.set(true);
+          }
+        }.queue();
+
+        return result.get();
+      }
+    });
+
+    return result ? getRootExternalProject(projectSystemId, projectRootDir) : null;
+  }
+
+  @Nullable
+  public ExternalProject getRootExternalProject(@NotNull ProjectSystemId systemId, @NotNull File projectRootDir) {
+    return myExternalRootProjects.get(Pair.create(systemId, projectRootDir));
+  }
+
+  public void saveExternalProject(@NotNull ExternalProject externalProject) {
+    myExternalRootProjects.put(
+      Pair.create(new ProjectSystemId(externalProject.getExternalSystemId()), externalProject.getProjectDir()),
+      new DefaultExternalProject(externalProject)
+    );
+  }
+
+  @Nullable
+  public ExternalProject findExternalProject(@NotNull ExternalProject parentProject, @NotNull Module module) {
+    String externalProjectId = ExternalSystemApiUtil.getExternalProjectId(module);
+    return externalProjectId != null ? findExternalProject(parentProject, externalProjectId) : null;
+  }
+
+  @Nullable
+  private static ExternalProject findExternalProject(@NotNull ExternalProject parentProject, @NotNull String externalProjectId) {
+    if (parentProject.getQName().equals(externalProjectId)) return parentProject;
+    if (parentProject.getChildProjects().containsKey(externalProjectId)) {
+      return parentProject.getChildProjects().get(externalProjectId);
+    }
+    for (ExternalProject externalProject : parentProject.getChildProjects().values()) {
+      final ExternalProject project = findExternalProject(externalProject, externalProjectId);
+      if (project != null) return project;
+    }
+    return null;
+  }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java
new file mode 100644
index 0000000..8828b9e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.service.project.data;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import com.esotericsoftware.kryo.serializers.CollectionSerializer;
+import com.esotericsoftware.kryo.serializers.DefaultSerializers;
+import com.esotericsoftware.kryo.serializers.FieldSerializer;
+import com.esotericsoftware.kryo.serializers.MapSerializer;
+import com.esotericsoftware.minlog.Log;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.*;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.objenesis.strategy.StdInstantiatorStrategy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/15/2014
+ */
+public class ExternalProjectSerializer {
+  private static final Logger LOG = Logger.getInstance(ExternalProjectSerializer.class);
+
+  private final Kryo myKryo;
+
+  public ExternalProjectSerializer() {
+    myKryo = new Kryo() {
+      @Override
+      public <T> T newInstance(Class<T> type) {
+        LOG.error("Serializing default type: " + type);
+        return super.newInstance(type);
+      }
+    };
+    configureKryo();
+  }
+
+  private void configureKryo() {
+    myKryo.setAutoReset(true);
+
+    myKryo.setRegistrationRequired(true);
+    Log.set(Log.LEVEL_WARN);
+
+    myKryo.register(ArrayList.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new ArrayList();
+      }
+    });
+    myKryo.register(HashMap.class, new MapSerializer() {
+      @Override
+      protected Map create(Kryo kryo, Input input, Class<Map> type) {
+        return new HashMap();
+      }
+    });
+    myKryo.register(HashSet.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new HashSet();
+      }
+    });
+
+    myKryo.register(File.class, new FileSerializer());
+    myKryo.register(DefaultExternalProject.class, new FieldSerializer<DefaultExternalProject>(myKryo, DefaultExternalProject.class) {
+      @Override
+      protected DefaultExternalProject create(Kryo kryo, Input input, Class<DefaultExternalProject> type) {
+        return new DefaultExternalProject();
+      }
+    });
+
+    myKryo.register(DefaultExternalTask.class, new FieldSerializer<DefaultExternalTask>(myKryo, DefaultExternalTask.class) {
+      @Override
+      protected DefaultExternalTask create(Kryo kryo, Input input, Class<DefaultExternalTask> type) {
+        return new DefaultExternalTask();
+      }
+    });
+
+    myKryo.register(DefaultExternalPlugin.class, new FieldSerializer<DefaultExternalPlugin>(myKryo, DefaultExternalPlugin.class) {
+      @Override
+      protected DefaultExternalPlugin create(Kryo kryo, Input input, Class<DefaultExternalPlugin> type) {
+        return new DefaultExternalPlugin();
+      }
+    });
+
+    myKryo.register(DefaultExternalSourceSet.class, new FieldSerializer<DefaultExternalSourceSet>(myKryo, DefaultExternalSourceSet.class) {
+      @Override
+      protected DefaultExternalSourceSet create(Kryo kryo, Input input, Class<DefaultExternalSourceSet> type) {
+        return new DefaultExternalSourceSet();
+      }
+    });
+
+    myKryo.register(
+      DefaultExternalSourceDirectorySet.class,
+      new FieldSerializer<DefaultExternalSourceDirectorySet>(myKryo, DefaultExternalSourceDirectorySet.class) {
+        @Override
+        protected DefaultExternalSourceDirectorySet create(Kryo kryo, Input input, Class<DefaultExternalSourceDirectorySet> type) {
+          return new DefaultExternalSourceDirectorySet();
+        }
+      }
+    );
+
+    myKryo.register(DefaultExternalFilter.class, new FieldSerializer<DefaultExternalFilter>(myKryo, DefaultExternalFilter.class) {
+      @Override
+      protected DefaultExternalFilter create(Kryo kryo, Input input, Class<DefaultExternalFilter> type) {
+        return new DefaultExternalFilter();
+      }
+    });
+
+    myKryo.register(ExternalSystemSourceType.class, new DefaultSerializers.EnumSerializer(ExternalSystemSourceType.class));
+
+    myKryo.register(LinkedHashSet.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new LinkedHashSet();
+      }
+    });
+    myKryo.register(HashSet.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new HashSet();
+      }
+    });
+    myKryo.register(THashSet.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new THashSet();
+      }
+    });
+    myKryo.register(Set.class, new CollectionSerializer() {
+      @Override
+      protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+        return new HashSet();
+      }
+    });
+    myKryo.register(THashMap.class, new MapSerializer() {
+      @Override
+      protected Map create(Kryo kryo, Input input, Class<Map> type) {
+        return new THashMap();
+      }
+    });
+  }
+
+
+  public void save(@NotNull ExternalProject externalProject) {
+    Output output = null;
+    try {
+      final String externalProjectPath = externalProject.getProjectDir().getPath();
+      final File configurationFile =
+        getProjectConfigurationFile(new ProjectSystemId(externalProject.getExternalSystemId()), externalProjectPath);
+      if (!FileUtil.createParentDirs(configurationFile)) return;
+
+      output = new Output(new FileOutputStream(configurationFile));
+      myKryo.writeObject(output, externalProject);
+    }
+    catch (FileNotFoundException e) {
+      LOG.error(e);
+    }
+    finally {
+      StreamUtil.closeStream(output);
+    }
+  }
+
+  @Nullable
+  public ExternalProject load(@NotNull ProjectSystemId externalSystemId, File externalProjectPath) {
+    Input input = null;
+    try {
+      final File configurationFile = getProjectConfigurationFile(externalSystemId, externalProjectPath.getPath());
+      if (!configurationFile.isFile()) return null;
+
+      input = new Input(new FileInputStream(configurationFile));
+      return myKryo.readObject(input, DefaultExternalProject.class);
+    }
+    catch (Exception e) {
+      LOG.error(e);
+    }
+    finally {
+      StreamUtil.closeStream(input);
+    }
+
+    return null;
+  }
+
+  private static File getProjectConfigurationFile(ProjectSystemId externalSystemId, String externalProjectPath) {
+    return new File(getProjectConfigurationDir(externalSystemId), Integer.toHexString(externalProjectPath.hashCode()) + "/project.dat");
+  }
+
+  private static File getProjectConfigurationDir(ProjectSystemId externalSystemId) {
+    return getPluginSystemDir(externalSystemId, "Projects");
+  }
+
+  private static File getPluginSystemDir(ProjectSystemId externalSystemId, String folder) {
+    return new File(PathManager.getSystemPath(), externalSystemId.getId().toLowerCase() + "/" + folder).getAbsoluteFile();
+  }
+
+  private static class FileSerializer extends Serializer<File> {
+    private final Kryo myStdKryo;
+
+    public FileSerializer() {
+      myStdKryo = new Kryo();
+      myStdKryo.register(File.class);
+      myStdKryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
+    }
+
+    @Override
+    public void write(Kryo kryo, Output output, File object) {
+      myStdKryo.writeObject(output, object);
+    }
+
+    @Override
+    public File read(Kryo kryo, Input input, Class<File> type) {
+      File file = myStdKryo.readObject(input, File.class);
+      return new File(file.getPath());
+    }
+  }
+
+  private static class StdSerializer<T> extends Serializer<T> {
+    private final Kryo myStdKryo;
+
+    public StdSerializer(Class<T> clazz) {
+      myStdKryo = new Kryo();
+      myStdKryo.register(clazz);
+      myStdKryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
+    }
+
+    @Override
+    public void write(Kryo kryo, Output output, T object) {
+      myStdKryo.writeObject(output, object);
+    }
+
+    @Override
+    public T read(Kryo kryo, Input input, Class<T> type) {
+      return myStdKryo.readObject(input, type);
+    }
+  }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
index 213ba84..10f766c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
@@ -16,17 +16,26 @@
 package org.jetbrains.plugins.gradle.service.project.wizard;
 
 import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
-import com.intellij.ide.util.projectWizard.ProjectBuilder;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
 import com.intellij.ide.util.projectWizard.WizardContext;
 import com.intellij.ide.wizard.Step;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.externalSystem.service.project.wizard.SelectExternalProjectStep;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.projectImport.ProjectOpenProcessorBase;
 import com.intellij.util.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
+import org.jetbrains.plugins.gradle.service.settings.GradleSystemSettingsControl;
+import org.jetbrains.plugins.gradle.service.settings.ImportFromGradleControl;
+import org.jetbrains.plugins.gradle.settings.DistributionType;
+import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
+import org.jetbrains.plugins.gradle.settings.GradleSettings;
 import org.jetbrains.plugins.gradle.util.GradleConstants;
+import static  org.jetbrains.plugins.gradle.util.GradleEnvironment.Headless.*;
 
 /**
  * @author Denis Zhdanov
@@ -61,24 +70,90 @@
 
   @Override
   protected boolean doQuickImport(VirtualFile file, WizardContext wizardContext) {
-    AddModuleWizard dialog = new AddModuleWizard(null, file.getPath(), new GradleProjectImportProvider(getBuilder()));
+    final GradleProjectImportProvider projectImportProvider = new GradleProjectImportProvider(getBuilder());
+    getBuilder().setFileToImport(file.getPath());
     getBuilder().prepare(wizardContext);
     getBuilder().getControl(null).setLinkedProjectPath(file.getPath());
-    dialog.getWizardContext().setProjectBuilder(getBuilder());
-    dialog.navigateToStep(new Function<Step, Boolean>() {
-      @Override
-      public Boolean fun(Step step) {
-        return step instanceof SelectExternalProjectStep;
-      }
-    });
 
-    boolean result = dialog.showAndGet();
+    final boolean result;
+    if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
+      result = setupGradleProjectSettingsInHeadlessMode(file, projectImportProvider, wizardContext);
+    }
+    else {
+      AddModuleWizard dialog = new AddModuleWizard(null, file.getPath(), projectImportProvider);
+      dialog.getWizardContext().setProjectBuilder(getBuilder());
+      dialog.navigateToStep(new Function<Step, Boolean>() {
+        @Override
+        public Boolean fun(Step step) {
+          return step instanceof SelectExternalProjectStep;
+        }
+      });
+      result = dialog.showAndGet();
+    }
     if (result && getBuilder().getExternalProjectNode() != null) {
       wizardContext.setProjectName(getBuilder().getExternalProjectNode().getData().getInternalName());
     }
     return result;
   }
 
+  private boolean setupGradleProjectSettingsInHeadlessMode(VirtualFile file,
+                                                           GradleProjectImportProvider projectImportProvider,
+                                                           WizardContext wizardContext) {
+    final ModuleWizardStep[] wizardSteps = projectImportProvider.createSteps(wizardContext);
+    if (wizardSteps.length > 0 && wizardSteps[0] instanceof SelectExternalProjectStep) {
+      SelectExternalProjectStep selectExternalProjectStep = (SelectExternalProjectStep)wizardSteps[0];
+      wizardContext.setProjectBuilder(getBuilder());
+      try {
+        selectExternalProjectStep.updateStep();
+        final ImportFromGradleControl importFromGradleControl = getBuilder().getControl(wizardContext.getProject());
+
+        GradleProjectSettingsControl gradleProjectSettingsControl =
+          (GradleProjectSettingsControl)importFromGradleControl.getProjectSettingsControl();
+
+        final GradleProjectSettings projectSettings = gradleProjectSettingsControl.getInitialSettings();
+
+        if (GRADLE_DISTRIBUTION_TYPE != null) {
+          for (DistributionType type : DistributionType.values()) {
+            if (type.name().equals(GRADLE_DISTRIBUTION_TYPE)) {
+              projectSettings.setDistributionType(type);
+              break;
+            }
+          }
+        }
+        if (GRADLE_HOME != null) {
+          projectSettings.setGradleHome(GRADLE_HOME);
+        }
+        gradleProjectSettingsControl.reset();
+
+        final GradleSystemSettingsControl systemSettingsControl =
+          (GradleSystemSettingsControl)importFromGradleControl.getSystemSettingsControl();
+        assert systemSettingsControl != null;
+        final GradleSettings gradleSettings = systemSettingsControl.getInitialSettings();
+        if (GRADLE_VM_OPTIONS != null) {
+          gradleSettings.setGradleVmOptions(GRADLE_VM_OPTIONS);
+        }
+        if (GRADLE_OFFLINE != null) {
+          gradleSettings.setOfflineWork(Boolean.parseBoolean(GRADLE_OFFLINE));
+        }
+        String serviceDirectory = GRADLE_SERVICE_DIRECTORY;
+        if (GRADLE_SERVICE_DIRECTORY != null) {
+          gradleSettings.setServiceDirectoryPath(serviceDirectory);
+        }
+        systemSettingsControl.reset();
+
+        if (!selectExternalProjectStep.validate()) {
+          return false;
+        }
+      }
+      catch (ConfigurationException e) {
+        Messages.showErrorDialog(wizardContext.getProject(), e.getMessage(), e.getTitle());
+        return false;
+      }
+      selectExternalProjectStep.updateDataModel();
+    }
+    return true;
+  }
+
   @Override
   public boolean lookForProjectsInDirectory() {
     return false;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
index ffdf37c..ab6454c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
@@ -173,4 +173,9 @@
   public void disposeUIResources() {
     ExternalSystemUiUtil.disposeUi(this);
   }
+
+  @NotNull
+  public GradleSettings getInitialSettings() {
+    return myInitialSettings;
+  }
 }
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
index 2c61ac6..eb780ce 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
@@ -13,6 +13,18 @@
   @NonNls public static final boolean DISABLE_ENHANCED_TOOLING_API = Boolean.getBoolean("gradle.disable.enhanced.tooling.api");
   @NonNls public static final boolean ADJUST_USER_DIR = Boolean.getBoolean("gradle.adjust.userdir");
 
+  public static class Headless {
+    @NonNls public static final String GRADLE_DISTRIBUTION_TYPE = System.getProperty("idea.gradle.distributionType");
+    @NonNls public static final String GRADLE_HOME = System.getProperty("idea.gradle.home");
+    @NonNls public static final String GRADLE_VM_OPTIONS = System.getProperty("idea.gradle.vmOptions");
+    @NonNls public static final String GRADLE_OFFLINE = System.getProperty("idea.gradle.offline");
+    @NonNls public static final String GRADLE_SERVICE_DIRECTORY = System.getProperty("idea.gradle.serviceDirectory");
+
+    private Headless() {
+    }
+  }
+
+
   private GradleEnvironment() {
   }
 }
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java
new file mode 100644
index 0000000..3b508c8
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import com.intellij.compiler.artifacts.ArtifactsTestUtil;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.packaging.impl.artifacts.ArtifactUtil;
+import com.intellij.util.io.TestFileSystemItem;
+import org.jetbrains.plugins.gradle.config.GradleResourceCompilerConfigurationGenerator;
+import org.jetbrains.plugins.gradle.importing.GradleImportingTestCase;
+
+import java.io.File;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+public abstract class GradleCompilingTestCase extends GradleImportingTestCase {
+  @Override
+  protected void setUpInWriteAction() throws Exception {
+    super.setUpInWriteAction();
+    CompilerManager.getInstance(myProject).addBeforeTask(new CompileTask() {
+      @Override
+      public boolean execute(CompileContext context) {
+        AccessToken token = ReadAction.start();
+        try {
+          new GradleResourceCompilerConfigurationGenerator(myProject, context).generateBuildConfiguration();
+        }
+        finally {
+          token.finish();
+        }
+        return true;
+      }
+    });
+  }
+
+  protected void assertCopied(String path) {
+    assertTrue(new File(myProjectConfig.getParent().getPath(), path).exists());
+  }
+
+  protected void assertCopied(String path, String content) {
+    assertCopied(path);
+    assertSameLinesWithFile(new File(myProjectConfig.getParent().getPath(), path).getPath(), content);
+  }
+
+  protected void assertNotCopied(String path) {
+    assertFalse(new File(myProjectConfig.getParent().getPath(), path).exists());
+  }
+
+  @Override
+  protected void assertArtifactOutputPath(String artifactName, String expected) {
+    final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+    assert defaultArtifactOutputPath != null;
+    final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+    super.assertArtifactOutputPath(artifactName, basePath + expected);
+  }
+
+  protected void assertArtifactOutputFile(String artifactName, String path, String content) {
+    final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+    assert defaultArtifactOutputPath != null;
+    final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+    assertSameLinesWithFile(basePath + path, content);
+  }
+
+  protected void assertArtifactOutputFile(String artifactName, String path) {
+    final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+    assert defaultArtifactOutputPath != null;
+    final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+    assertExists(new File(basePath + path));
+  }
+}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java
new file mode 100644
index 0000000..df9c6a8
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import org.junit.Test;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
+public class GradleResourceFilteringTest extends GradleCompilingTestCase {
+
+  @Test
+  public void testHeadFilter() throws Exception {
+    createProjectSubFile(
+      "src/main/resources/dir/file.txt", "1 Header\n" +
+                                         "2\n" +
+                                         "3 another text\n" +
+                                         "4\n" +
+                                         "5 another text \n" +
+                                         "6 another text @token@ another text\n" +
+                                         "7\n" +
+                                         "8 Footer");
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "import org.apache.tools.ant.filters.*\n" +
+      "processResources {\n" +
+      "  filter(HeadFilter, lines:3, skip:2)\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("build/resources/main/dir/file.txt", "3 another text\n" +
+                                                      "4\n" +
+                                                      "5 another text \n");
+  }
+
+  @Test
+  public void testReplaceTokensFilter() throws Exception {
+    createProjectSubFile(
+      "src/main/resources/dir/file.txt", "1 Header\n" +
+                                         "2\n" +
+                                         "3 #token1#another text\n" +
+                                         "4\n" +
+                                         "5 another text \n" +
+                                         "6 another text #token2# another text\n" +
+                                         "7\n" +
+                                         "8 Footer");
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "import org.apache.tools.ant.filters.*\n" +
+      "processResources {\n" +
+      "  filter(ReplaceTokens, tokens:[token1:'<11111>', token2:'<2222>'], beginToken: '#', endToken: '#')\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("build/resources/main/dir/file.txt", "1 Header\n" +
+                                                      "2\n" +
+                                                      "3 <11111>another text\n" +
+                                                      "4\n" +
+                                                      "5 another text \n" +
+                                                      "6 another text <2222> another text\n" +
+                                                      "7\n" +
+                                                      "8 Footer");
+  }
+
+  @Test
+  public void testRenameFilter() throws Exception {
+    createProjectSubFile("src/main/resources/dir/file.txt");
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "import org.apache.tools.ant.filters.*\n" +
+      "processResources {\n" +
+      "  rename 'file.txt', 'file001.txt'\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("build/resources/main/dir/file001.txt");
+  }
+
+  @Test
+  public void testFiltersChain() throws Exception {
+    createProjectSubFile(
+      "src/main/resources/dir/file.txt", "1 Header\n" +
+                                         "2\n" +
+                                         "3 another text@token1@\n" +
+                                         "4\n" +
+                                         "5 another text \n" +
+                                         "6 another text @token2@ another text\n" +
+                                         "7\n" +
+                                         "8 Footer");
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "import org.apache.tools.ant.filters.*\n" +
+      "processResources {\n" +
+      "  filter(HeadFilter, lines:4, skip:2)\n" +
+      "  filter(ReplaceTokens, tokens:[token1:'<11111>', token2:'<2222>'])\n" +
+      "  rename 'file.txt', 'file001.txt'\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("build/resources/main/dir/file001.txt", "3 another text<11111>\n" +
+                                                         "4\n" +
+                                                         "5 another text \n" +
+                                                         "6 another text <2222> another text");
+  }
+}
\ No newline at end of file
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java
new file mode 100644
index 0000000..8732344
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
+public class GradleResourceProcessingTest extends GradleCompilingTestCase {
+
+  @Test
+  public void testBasicResourceCopying() throws Exception {
+    createProjectSubFile("src/main/resources/dir/file.properties");
+    createProjectSubFile("src/test/resources/dir/file-test.properties");
+    importProject(
+      "apply plugin: 'java'"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("build/resources/main/dir/file.properties");
+    assertCopied("build/resources/test/dir/file-test.properties");
+  }
+
+  @Test
+  public void testResourceProcessingWithIdeaGradlePluginCustomization() throws Exception {
+    createProjectSubFile("src/main/resources/dir/file.properties");
+    createProjectSubFile("src/test/resources/dir/file-test.properties");
+    importProject(
+      "apply plugin: 'java'\n" +
+      "apply plugin: 'idea'\n" +
+      "idea {\n" +
+      "  module {\n" +
+      "    inheritOutputDirs = false\n" +
+      "    outputDir = file('muchBetterOutputDir')\n" +
+      "    testOutputDir = file('muchBetterTestOutputDir')\n" +
+      "  }\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopied("muchBetterOutputDir/dir/file.properties");
+    assertCopied("muchBetterTestOutputDir/dir/file-test.properties");
+  }
+
+  @Test
+  public void testIncludesAndExcludesInSourceSets() throws Exception {
+    createFilesForIncludesAndExcludesTest();
+
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "sourceSets {\n" +
+      "  main {\n" +
+      "    resources {\n" +
+      "      include '**/*.yyy'\n" +
+      "      include '**/*.xxx'\n" +
+      "      exclude 'dir/*.yyy'\n" +
+      "      exclude '*.xxx'\n" +
+      "    }\n" +
+      "  }\n" +
+      "  test {\n" +
+      "    resources {\n" +
+      "      include '**/*.yyy'\n" +
+      "      include '**/*.xxx'\n" +
+      "      exclude 'dir/*.yyy'\n" +
+      "      exclude '*.xxx'\n" +
+      "    }\n" +
+      "  }\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopiedResources();
+  }
+
+  @Test
+  public void testIncludesAndExcludesInAllSourceSets() throws Exception {
+    createFilesForIncludesAndExcludesTest();
+
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "sourceSets.all {\n" +
+      "  resources {\n" +
+      "    include '**/*.yyy'\n" +
+      "    include '**/*.xxx'\n" +
+      "    exclude 'dir/*.yyy'\n" +
+      "    exclude '*.xxx'\n" +
+      "  }\n" +
+      "}"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopiedResources();
+  }
+
+
+  @Test
+  public void testIncludesAndExcludesInResourcesTask() throws Exception {
+    createFilesForIncludesAndExcludesTest();
+
+    importProject(
+      "apply plugin: 'java'\n" +
+      "\n" +
+      "processResources {\n" +
+      "  include '**/*.yyy'\n" +
+      "  include '**/*.xxx'\n" +
+      "  exclude 'dir/*.yyy'\n" +
+      "  exclude '*.xxx'\n" +
+      "}\n" +
+      "\n" +
+      "processTestResources {\n" +
+      "  include '**/*.yyy'\n" +
+      "  include '**/*.xxx'\n" +
+      "  exclude 'dir/*.yyy'\n" +
+      "  exclude '*.xxx'\n" +
+      "}\n"
+    );
+    assertModules("project");
+    compileModules("project");
+
+    assertCopiedResources();
+  }
+
+  private void createFilesForIncludesAndExcludesTest() throws IOException {
+    createProjectSubFile("src/main/resources/dir/file.xxx");
+    createProjectSubFile("src/main/resources/dir/file.yyy");
+    createProjectSubFile("src/main/resources/file.xxx");
+    createProjectSubFile("src/main/resources/file.yyy");
+    createProjectSubFile("src/main/resources/file.zzz");
+
+    createProjectSubFile("src/test/resources/dir/file.xxx");
+    createProjectSubFile("src/test/resources/dir/file.yyy");
+    createProjectSubFile("src/test/resources/file.xxx");
+    createProjectSubFile("src/test/resources/file.yyy");
+    createProjectSubFile("src/test/resources/file.zzz");
+  }
+
+  private void assertCopiedResources() {
+    // assert production resources
+    assertCopied("build/resources/main/dir/file.xxx");
+    assertCopied("build/resources/main/file.yyy");
+    assertNotCopied("build/resources/main/dir/file.yyy");
+    assertNotCopied("build/resources/main/file.xxx");
+    assertNotCopied("build/resources/main/file.zzz");
+
+    // assert test resources
+    assertCopied("build/resources/test/dir/file.xxx");
+    assertCopied("build/resources/test/file.yyy");
+    assertNotCopied("build/resources/test/dir/file.yyy");
+    assertNotCopied("build/resources/test/file.xxx");
+    assertNotCopied("build/resources/test/file.zzz");
+  }
+}
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
index 97dfd25..91889d8 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
@@ -22,9 +22,12 @@
 import java.util.List;
 
 /**
+ * @deprecated Use {@link com.intellij.openapi.externalSystem.model.ExternalProject} model instead.
+ *
  * @author Vladislav.Soroka
  * @since 11/5/13
  */
+@Deprecated()
 public interface ModuleExtendedModel extends Serializable {
   /**
    * The group of the module.
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
index af6f4fe..5b20894 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
@@ -48,8 +48,8 @@
   @Nullable
   @Override
   public AllModels execute(final BuildController controller) {
-    Class<? extends IdeaProject> aClass1 = myIsPreviewMode ? BasicIdeaProject.class : IdeaProject.class;
-    final IdeaProject ideaProject = controller.getModel(aClass1);
+    //outer conditional is needed to be compatible with 1.8
+    final IdeaProject ideaProject = myIsPreviewMode ? controller.getModel(BasicIdeaProject.class) : controller.getModel(IdeaProject.class);
     if (ideaProject == null || ideaProject.getModules().isEmpty()) {
       return null;
     }
@@ -59,25 +59,30 @@
     // TODO ask gradle guys why there is always null got for BuildEnvironment model
     //allModels.setBuildEnvironment(controller.findModel(BuildEnvironment.class));
 
+    addExtraProject(controller, allModels, null);
     for (IdeaModule module : ideaProject.getModules()) {
-      for (Class aClass : myExtraProjectModelClasses) {
-        try {
-          Object extraProject = controller.findModel(module, aClass);
-          if (extraProject == null) continue;
-          allModels.addExtraProject(extraProject, aClass, module);
-        }
-        catch (Exception e) {
-          // do not fail project import in a preview mode
-          if (!myIsPreviewMode) {
-            throw new ExternalSystemException(e);
-          }
-        }
-      }
+      addExtraProject(controller, allModels, module);
     }
 
     return allModels;
   }
 
+  private void addExtraProject(@NotNull BuildController controller, @NotNull AllModels allModels, @Nullable IdeaModule model) {
+    for (Class aClass : myExtraProjectModelClasses) {
+      try {
+        Object extraProject = controller.findModel(model, aClass);
+        if (extraProject == null) continue;
+        allModels.addExtraProject(extraProject, aClass, model);
+      }
+      catch (Exception e) {
+        // do not fail project import in a preview mode
+        if (!myIsPreviewMode) {
+          throw new ExternalSystemException(e);
+        }
+      }
+    }
+  }
+
   public static class AllModels implements Serializable {
     @NotNull private final Map<String, Object> projectsByPath = new HashMap<String, Object>();
     @NotNull private final IdeaProject myIdeaProject;
@@ -101,9 +106,13 @@
       myBuildEnvironment = buildEnvironment;
     }
 
+    @Nullable
+    public <T> T getExtraProject(Class<T> modelClazz) {
+      return getExtraProject(null, modelClazz);
+    }
 
     @Nullable
-    public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
+    public <T> T getExtraProject(@Nullable IdeaModule module, Class<T> modelClazz) {
       Object extraProject = projectsByPath.get(extractMapKey(modelClazz, module));
       if (modelClazz.isInstance(extraProject)) {
         //noinspection unchecked
@@ -129,13 +138,17 @@
       return modules;
     }
 
-    public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @NotNull IdeaModule module) {
+    public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz) {
+      projectsByPath.put(extractMapKey(modelClazz, null), project);
+    }
+
+    public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @Nullable IdeaModule module) {
       projectsByPath.put(extractMapKey(modelClazz, module), project);
     }
 
     @NotNull
-    private static String extractMapKey(Class modelClazz, @NotNull IdeaModule module) {
-      return modelClazz.getName() + '@' + module.getGradleProject().getPath();
+    private String extractMapKey(Class modelClazz, @Nullable IdeaModule module) {
+      return modelClazz.getName() + '@' + (module != null ? module.getGradleProject().getPath() : "root" + myIdeaProject.getName().hashCode());
     }
 
     @NotNull
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
index 97e4499..da938dc 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
@@ -31,17 +31,21 @@
   public static final String EOL_TAG = "<eol>";
 
   @NotNull private final Project myProject;
-  @NotNull private final Exception myException;
+  @Nullable private final Exception myException;
   @NotNull private final String myGroup;
   @Nullable private String myDescription;
 
-  private ErrorMessageBuilder(@NotNull Project project, @NotNull Exception exception, @NotNull String group) {
+  private ErrorMessageBuilder(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
     myProject = project;
     myException = exception;
     myGroup = group;
   }
 
-  public static ErrorMessageBuilder create(@NotNull Project project, @NotNull Exception exception, @NotNull String group) {
+  public static ErrorMessageBuilder create(@NotNull Project project, @NotNull String group) {
+    return new ErrorMessageBuilder(project, null, group);
+  }
+
+  public static ErrorMessageBuilder create(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
     return new ErrorMessageBuilder(project, exception, group);
   }
 
@@ -59,7 +63,7 @@
       (
         "<i>" +
         "<b>" + myProject + ((myDescription != null) ? ": " + myDescription : "") + "</b>" +
-        "\nDetails: " + getErrorMessage(myException) +
+        (myException != null ? "\nDetails: " + getErrorMessage(myException) : "") +
         "</i>"
       ).replaceAll("\r\n|\n\r|\n|\r", EOL_TAG)
     );
diff --git a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
index 1bcde5e..ea57928 100644
--- a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
+++ b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
@@ -67,6 +67,7 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="library" name="gson" level="project" />
   </component>
 </module>
 
diff --git a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
index 244e58d..816ef05 100644
--- a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
+++ b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -17,3 +17,4 @@
 org.jetbrains.plugins.gradle.tooling.builder.ModuleExtendedModelBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ScalaModelBuilderImpl
+org.jetbrains.plugins.gradle.tooling.builder.ExternalProjectBuilderImpl
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
new file mode 100644
index 0000000..3bb6b47
--- /dev/null
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.gradle.tooling.builder
+
+import com.google.gson.GsonBuilder
+import com.intellij.openapi.externalSystem.model.*
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
+import org.gradle.api.Action
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.ContentFilterable
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceSetContainer
+import org.gradle.api.tasks.util.PatternFilterable
+import org.jetbrains.annotations.NotNull
+import org.jetbrains.annotations.Nullable
+import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
+
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+class ExternalProjectBuilderImpl implements ModelBuilderService {
+
+  private final cache = new ConcurrentHashMap<String, ExternalProject>()
+
+  @Override
+  public boolean canBuild(String modelName) {
+    return ExternalProject.name.equals(modelName)
+  }
+
+  @Nullable
+  @Override
+  public Object buildAll(final String modelName, final Project project) {
+    ExternalProject externalProject = cache[project.path]
+    if (externalProject != null) return externalProject
+
+    DefaultExternalProject defaultExternalProject = new DefaultExternalProject()
+    defaultExternalProject.externalSystemId = "GRADLE"
+    defaultExternalProject.name = project.name
+    defaultExternalProject.QName = ":".equals(project.path) ? project.name : project.path
+    defaultExternalProject.version = wrap(project.version)
+    defaultExternalProject.description = project.description
+    defaultExternalProject.buildDir = project.buildDir
+    defaultExternalProject.buildFile = project.buildFile
+    defaultExternalProject.group = wrap(project.group)
+    defaultExternalProject.projectDir = project.projectDir
+    defaultExternalProject.sourceSets = getSourceSets(project)
+    defaultExternalProject.tasks = getTasks(project)
+
+    defaultExternalProject.plugins = getPlugins(project)
+    //defaultExternalProject.setProperties(project.getProperties())
+
+
+    final Map<String, ExternalProject> childProjects = new HashMap<String, ExternalProject>(project.getChildProjects().size())
+    for (Map.Entry<String, Project> projectEntry : project.getChildProjects().entrySet()) {
+      final Object externalProjectChild = buildAll(modelName, projectEntry.getValue())
+      if (externalProjectChild instanceof ExternalProject) {
+        childProjects.put(projectEntry.getKey(), (ExternalProject)externalProjectChild)
+      }
+    }
+    defaultExternalProject.setChildProjects(childProjects)
+    cache.put(project.getPath(), defaultExternalProject)
+
+    defaultExternalProject
+  }
+
+  static Map<String, ExternalPlugin> getPlugins(Project project) {
+    def result = [:] as Map<String, ExternalPlugin>
+    project.convention.plugins.each { key, value ->
+      ExternalPlugin externalPlugin = new DefaultExternalPlugin()
+      externalPlugin.id = key
+      result.put(key, externalPlugin)
+    }
+
+    result
+  }
+
+  static Map<String, ExternalTask> getTasks(Project project) {
+    def result = [:] as Map<String, ExternalTask>
+
+    project.tasks.all { Task task ->
+      ExternalTask externalTask = new DefaultExternalTask()
+      externalTask.name = task.name
+      externalTask.description = task.description
+      externalTask.group = task.group
+      externalTask.QName = task.path
+      result.put(externalTask.QName, externalTask)
+    }
+
+    result
+  }
+
+  static Map<String, ExternalSourceSet> getSourceSets(Project project) {
+    def result = [:] as Map<String, ExternalSourceSet>
+    if (!project.hasProperty("sourceSets") || !(project.sourceSets instanceof SourceSetContainer)) {
+      return result
+    }
+    def sourceSets = project.sourceSets as SourceSetContainer
+
+    def (resourcesIncludes, resourcesExcludes, filterReaders) = getFilters(project, 'processResources')
+    def (testResourcesIncludes, testResourcesExcludes, testFilterReaders) = getFilters(project, 'processTestResources')
+    //def (javaIncludes,javaExcludes) = getFilters(project,'compileJava')
+
+    sourceSets.all { SourceSet sourceSet ->
+      ExternalSourceSet externalSourceSet = new DefaultExternalSourceSet()
+      externalSourceSet.name = sourceSet.name
+
+      def sources = [:] as Map<ExternalSystemSourceType, ExternalSourceDirectorySet>
+      ExternalSourceDirectorySet resourcesDirectorySet = new DefaultExternalSourceDirectorySet()
+      resourcesDirectorySet.name = sourceSet.resources.name
+      resourcesDirectorySet.srcDirs = sourceSet.resources.srcDirs
+      resourcesDirectorySet.outputDir = sourceSet.output.resourcesDir
+
+      ExternalSourceDirectorySet javaDirectorySet = new DefaultExternalSourceDirectorySet()
+      javaDirectorySet.name = sourceSet.allJava.name
+      javaDirectorySet.srcDirs = sourceSet.allJava.srcDirs
+      javaDirectorySet.outputDir = sourceSet.output.classesDir
+//      javaDirectorySet.excludes = javaExcludes + sourceSet.java.excludes;
+//      javaDirectorySet.includes = javaIncludes + sourceSet.java.includes;
+
+      if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.name)) {
+        resourcesDirectorySet.excludes = testResourcesExcludes + sourceSet.resources.excludes;
+        resourcesDirectorySet.includes = testResourcesIncludes + sourceSet.resources.includes;
+        resourcesDirectorySet.filters = testFilterReaders
+        sources.put(ExternalSystemSourceType.TEST, javaDirectorySet)
+        sources.put(ExternalSystemSourceType.TEST_RESOURCE, resourcesDirectorySet)
+      }
+      else {
+        resourcesDirectorySet.excludes = resourcesExcludes + sourceSet.resources.excludes;
+        resourcesDirectorySet.includes = resourcesIncludes + sourceSet.resources.includes;
+        resourcesDirectorySet.filters = filterReaders
+        sources.put(ExternalSystemSourceType.SOURCE, javaDirectorySet)
+        sources.put(ExternalSystemSourceType.RESOURCE, resourcesDirectorySet)
+      }
+
+      externalSourceSet.sources = sources
+      result[sourceSet.name] = externalSourceSet
+    }
+    result
+  }
+
+  static getFilters(Project project, String taskName) {
+    def includes = []
+    def excludes = []
+    def filterReaders = [] as List<ExternalFilter>
+    def filterableTask = project.tasks.findByName(taskName)
+    if (filterableTask instanceof PatternFilterable) {
+      includes += filterableTask.includes
+      excludes += filterableTask.excludes
+    }
+
+    if(System.getProperty('idea.disable.gradle.resource.filtering', 'false').toBoolean()) {
+      return [includes, excludes, filterReaders]
+    }
+
+    try {
+      if (filterableTask instanceof ContentFilterable && filterableTask.metaClass.respondsTo(filterableTask, "getMainSpec")) {
+        def properties = filterableTask.getMainSpec().properties
+        def copyActions = properties?.allCopyActions ?: properties?.copyActions
+
+        if(copyActions) {
+          copyActions.each { Action<? super FileCopyDetails> action ->
+            if (action.hasProperty('val$filterType') && action.hasProperty('val$properties')) {
+              def filterType = (action?.val$filterType as Class).name
+              def filter = [filterType: filterType] as DefaultExternalFilter
+              def props = action?.val$properties
+              if (props) {
+                filter.propertiesAsJsonMap = new GsonBuilder().create().toJson(props);
+              }
+              filterReaders << filter
+            }
+            else if (action.class.simpleName.equals('RenamingCopyAction') && action.hasProperty('transformer')) {
+              if (action.transformer.hasProperty('matcher') && action?.transformer.hasProperty('replacement')) {
+                String pattern = action?.transformer?.matcher.pattern().pattern
+                String replacement = action?.transformer?.replacement
+                def filter = [filterType: 'RenamingCopyFilter'] as DefaultExternalFilter
+                if(pattern && replacement){
+                  filter.propertiesAsJsonMap = new GsonBuilder().create().toJson([pattern: pattern, replacement: replacement]);
+                  filterReaders << filter
+                }
+              }
+            }
+//          else {
+//            project.logger.error(
+//              ErrorMessageBuilder.create(project, "Resource configuration errors")
+//                .withDescription("Unsupported copy action found: " + action.class.name).build())
+//          }
+          }
+        }
+      }
+    }
+    catch (Exception ignore) {
+//      project.logger.error(
+//        ErrorMessageBuilder.create(project, e, "Resource configuration errors")
+//          .withDescription("Unable to resolve resources filtering configuration").build())
+    }
+
+    return [includes, excludes, filterReaders]
+  }
+
+
+  private static String wrap(Object o) {
+    return o instanceof CharSequence ? o.toString() : ""
+  }
+
+  @NotNull
+  @Override
+  public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
+    return ErrorMessageBuilder.create(
+      project, e, "Project resolve errors"
+    ).withDescription("Unable to resolve additional project configuration.")
+  }
+}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
index 00f4c8b..2eb7137 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
@@ -88,20 +88,25 @@
 
           if (resolver.metaClass.respondsTo(resolver, 'getSourcePaths')) {
             sourcePaths = resolver.getSourcePaths()
-          } else if (resolver.this$0.metaClass.respondsTo(resolver, 'getSourcePaths')) {
+          } else if (resolver.hasProperty('sourcePaths')) {
+            sourcePaths = resolver.sourcePaths
+          } else if (resolver.hasProperty('this$0') && resolver.this$0.metaClass.respondsTo(resolver, 'getSourcePaths')) {
             sourcePaths = resolver.this$0.getSourcePaths()
-          } else {
+          } else if (resolver.hasProperty('this$0') && resolver.this$0.hasProperty('sourcePaths')) {
+            sourcePaths = resolver.this$0.sourcePaths
+          } /*else {
             throw new RuntimeException("${GradleVersion.current()} is not supported by web artifact importer")
-          }
+          }*/
 
-          (sourcePaths.flatten() as List).each { def path ->
-            if (path instanceof String) {
-              def file = new File(warTask.project.projectDir, path)
-              addPath(webResources, relativePath, "", file)
+          if(sourcePaths) {
+            (sourcePaths.flatten() as List).each { def path ->
+              if (path instanceof String) {
+                def file = new File(warTask.project.projectDir, path)
+                addPath(webResources, relativePath, "", file)
+              }
             }
           }
 
-
           resolver.source.visit(new FileVisitor() {
             @Override
             public void visitDir(FileVisitDetails dirDetails) {
diff --git a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
index d09a9b7..faf3a98 100644
--- a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
+++ b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.plugins.gradle.tooling.builder;
 
+import com.intellij.openapi.externalSystem.model.ExternalProject;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.testFramework.UsefulTestCase;
@@ -127,7 +128,7 @@
     BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
     File initScript = GradleExecutionHelper.generateInitScript(false, getToolingExtensionClasses());
     assertNotNull(initScript);
-    buildActionExecutor.withArguments(GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
+    buildActionExecutor.withArguments("--recompile-scripts", GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
     allModels = buildActionExecutor.run();
     assertNotNull(allModels);
   }
@@ -135,6 +136,7 @@
   @NotNull
   private Set<Class> getToolingExtensionClasses() {
     final Set<Class> classes = ContainerUtil.<Class>set(
+      ExternalProject.class,
       // gradle-tooling-extension-api jar
       ProjectImportAction.class,
       // gradle-tooling-extension-impl jar
diff --git a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
index dcb426a..910d211 100644
--- a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
+++ b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
@@ -50,4 +50,13 @@
     <display-name>RegExp</display-name>
     <place><![CDATA[groovyLiteralExpression().regExpOperatorArgument()]]></place>
   </injection>
+  <injection language="encoding-reference" injector-id="java">
+    <display-name>Charset Name</display-name>
+    <place><![CDATA[psiParameter().ofMethod(0, psiMethod().withName("getBytes").withParameters("java.lang.String").definedInClass("groovy.lang.GString"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newPrintWriter").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+    <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.io.File", "java.lang.String", "boolean").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+  </injection>
 </component>
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
index 855deba..03e3b54 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
@@ -18,6 +18,7 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
@@ -58,6 +59,8 @@
 import org.jetbrains.jps.service.JpsServiceManager;
 import org.jetbrains.jps.service.SharedThreadPool;
 import org.jetbrains.org.objectweb.asm.ClassReader;
+import org.jetbrains.org.objectweb.asm.ClassVisitor;
+import org.jetbrains.org.objectweb.asm.Opcodes;
 
 import java.io.File;
 import java.io.IOException;
@@ -434,9 +437,14 @@
           final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
           final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
           final File outputFile = new File(outputPath);
-          outputConsumer.registerOutputFile(target, outputFile, Collections.singleton(sourcePath));
+          final File srcFile = new File(sourcePath);
           try {
-            callback.associate(outputPath, sourcePath, new ClassReader(FileUtil.loadFileBytes(outputFile)));
+            final byte[] bytes = FileUtil.loadFileBytes(outputFile);
+            outputConsumer.registerCompiledClass(
+              target,
+              new CompiledClass(outputFile, srcFile, readClassName(bytes), new BinaryContent(bytes))
+            );
+            callback.associate(outputPath, sourcePath, new ClassReader(bytes));
           }
           catch (Throwable e) {
             // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation
@@ -446,7 +454,7 @@
               myBuilderName, BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath)
             );
           }
-          successfullyCompiledFiles.add(new File(sourcePath));
+          successfullyCompiledFiles.add(srcFile);
         }
       }
     }
@@ -454,6 +462,16 @@
     return JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, toCompile, successfullyCompiledFiles);
   }
 
+  private static String readClassName(byte[] classBytes) throws IOException{
+    final Ref<String> nameRef = Ref.create(null);
+    new ClassReader(classBytes).accept(new ClassVisitor(Opcodes.ASM5) {
+      public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+        nameRef.set(name.replace('/', '.'));
+      }
+    }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+    return nameRef.get();
+  }
+
   private static Collection<String> generateClasspath(CompileContext context, ModuleChunk chunk) {
     final Set<String> cp = new LinkedHashSet<String>();
     //groovy_rt.jar
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
index 273fd4c..c253842 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
@@ -19,23 +19,31 @@
 import com.intellij.openapi.components.Storage;
 import com.intellij.openapi.components.StoragePathMacros;
 import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
 import com.intellij.xdebugger.settings.XDebuggerSettings;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyBundle;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static java.util.Collections.singletonList;
 
 /**
  * @author ilyas
  */
 @State(
-    name = "GroovyDebuggerSettings",
-    storages = {
+  name = "GroovyDebuggerSettings",
+  storages = {
     @Storage(
-        file = StoragePathMacros.APP_CONFIG + "/groovy_debug.xml"
+      file = StoragePathMacros.APP_CONFIG + "/groovy_debug.xml"
     )}
 )
-public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSettings> {
+public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSettings> implements Getter<GroovyDebuggerSettings> {
   public Boolean DEBUG_DISABLE_SPECIFIC_GROOVY_METHODS = true;
   public boolean ENABLE_GROOVY_HOTSWAP = Registry.is("enable.groovy.hotswap");
 
@@ -43,19 +51,19 @@
     super("groovy_debugger");
   }
 
-  @Override
   @NotNull
-  public Configurable createConfigurable() {
-    return new GroovyDebuggerSettingsConfigurable(this);
-  }
-
-  @Nullable
+  @SuppressWarnings("EnumSwitchStatementWhichMissesCases")
   @Override
-  public Configurable createConfigurable(@NotNull Category category) {
-    if (category == Category.STEPPING) {
-      return new GroovySteppingConfigurable();
+  public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+    switch (category) {
+      case STEPPING:
+        return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.groovy", GroovyBundle.message("groovy.debug.caption"),
+                                                       "reference.idesettings.debugger.groovy", GroovySteppingConfigurableUi.class, this));
+      case HOTSWAP:
+        return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.groovy", GroovyBundle.message("groovy.debug.caption"),
+                                                       "reference.idesettings.debugger.groovy", GroovyHotSwapConfigurableUi.class, this));
     }
-    return null;
+    return Collections.emptyList();
   }
 
   @Override
@@ -71,4 +79,9 @@
   public static GroovyDebuggerSettings getInstance() {
     return getInstance(GroovyDebuggerSettings.class);
   }
+
+  @Override
+  public GroovyDebuggerSettings get() {
+    return this;
+  }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java
deleted file mode 100644
index 8f143d9..0000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-package org.jetbrains.plugins.groovy.debugger;
-
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.GroovyBundle;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-/**
- * @author ilyas
- */
-public class GroovyDebuggerSettingsConfigurable implements SearchableConfigurable {
-  private JPanel myPanel;
-  private JCheckBox myEnableHotSwap;
-  private boolean isModified = false;
-  private final GroovyDebuggerSettings mySettings;
-
-  public GroovyDebuggerSettingsConfigurable(final GroovyDebuggerSettings settings) {
-    mySettings = settings;
-
-    myEnableHotSwap.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(final ActionEvent e) {
-        isModified = mySettings.ENABLE_GROOVY_HOTSWAP != myEnableHotSwap.isSelected();
-      }
-    });
-  }
-
-  @Override
-  @Nls
-  public String getDisplayName() {
-    return GroovyBundle.message("groovy.debug.caption");
-  }
-
-  @Override
-  @NotNull
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.groovy";
-  }
-
-  @Override
-  @NotNull
-  public String getId() {
-    return getHelpTopic();
-  }
-
-  @Override
-  public Runnable enableSearch(String option) {
-    return null;
-  }
-
-  @Override
-  public JComponent createComponent() {
-    return myPanel;
-  }
-
-  @Override
-  public boolean isModified() {
-    return isModified;
-  }
-
-  @Override
-  public void apply() throws ConfigurationException {
-    if (isModified) {
-      mySettings.ENABLE_GROOVY_HOTSWAP = myEnableHotSwap.isSelected();
-    }
-    isModified = false;
-  }
-
-  @Override
-  public void reset() {
-    myEnableHotSwap.setSelected(mySettings.ENABLE_GROOVY_HOTSWAP);
-  }
-
-  @Override
-  public void disposeUIResources() {
-  }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form
similarity index 94%
rename from plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form
rename to plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form
index 171170b..cbe2154 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.debugger.GroovyDebuggerSettingsConfigurable">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapConfigurableUi">
   <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
@@ -19,6 +19,7 @@
         </constraints>
         <properties>
           <componentStyle value="SMALL"/>
+          <fontColor value="BRIGHTER"/>
           <text value="May cause serialization issues in the debugged application"/>
         </properties>
       </component>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java
new file mode 100644
index 0000000..400d344
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.jetbrains.plugins.groovy.debugger;
+
+import com.intellij.openapi.options.ConfigurableUi;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author ilyas
+ */
+class GroovyHotSwapConfigurableUi implements ConfigurableUi<GroovyDebuggerSettings> {
+  private JPanel myPanel;
+  private JCheckBox myEnableHotSwap;
+
+  @NotNull
+  @Override
+  public JComponent getComponent() {
+    return myPanel;
+  }
+
+  @Override
+  public boolean isModified(@NotNull GroovyDebuggerSettings settings) {
+    return settings.ENABLE_GROOVY_HOTSWAP != myEnableHotSwap.isSelected();
+  }
+
+  @Override
+  public void apply(@NotNull GroovyDebuggerSettings settings) {
+    settings.ENABLE_GROOVY_HOTSWAP = myEnableHotSwap.isSelected();
+  }
+
+  @Override
+  public void reset(@NotNull GroovyDebuggerSettings settings) {
+    myEnableHotSwap.setSelected(settings.ENABLE_GROOVY_HOTSWAP);
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java
deleted file mode 100644
index 0e5d995..0000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.jetbrains.plugins.groovy.debugger;
-
-import com.intellij.openapi.options.ConfigurableBase;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.GroovyBundle;
-
-class GroovySteppingConfigurable extends ConfigurableBase<GroovySteppingConfigurableUi, GroovyDebuggerSettings> {
-  @Override
-  protected GroovyDebuggerSettings getSettings() {
-    return GroovyDebuggerSettings.getInstance();
-  }
-
-  @Override
-  protected GroovySteppingConfigurableUi createUi() {
-    return new GroovySteppingConfigurableUi();
-  }
-
-  @NotNull
-  @Override
-  public String getId() {
-    return "debugger.stepping.groovy";
-  }
-
-  @Nls
-  @Override
-  public String getDisplayName() {
-    return GroovyBundle.message("groovy.debug.caption");
-  }
-
-  @Nullable
-  @Override
-  public String getHelpTopic() {
-    return "reference.idesettings.debugger.groovy";
-  }
-}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
index 63784b5..d4b67e1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
@@ -97,7 +97,7 @@
           }
           else {
             if (reference instanceof GrReferenceExpression) {
-              PsiElement referent = reference.resolve();
+              PsiElement referent = resolveReferenceIgnoreOverriding(reference);
               if (!(referent instanceof PsiNamedElement)
                   || !data.staticMemberName.equals(((PsiNamedElement)referent).getName())
                   || !(referent instanceof PsiMember)
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
index 84b96c3..1964957 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
@@ -23,7 +23,6 @@
 import com.intellij.ide.util.projectWizard.WizardContext;
 import com.intellij.ide.wizard.CommitStepException;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.ModifiableRootModel;
 import com.intellij.openapi.roots.libraries.Library;
 import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
@@ -51,8 +50,9 @@
 
   public GroovySdkWizardStepBase(@Nullable final MvcFramework framework, WizardContext wizardContext, String basePath) {
     myBasePath = basePath;
-    final Project project = wizardContext.getProject();
-    myLibrariesContainer = LibrariesContainerFactory.createContainer(project);
+    myLibrariesContainer = wizardContext.getModulesProvider() == null
+                           ? LibrariesContainerFactory.createContainer(wizardContext.getProject())
+                           : LibrariesContainerFactory.createContainer(wizardContext, wizardContext.getModulesProvider());
     myFramework = framework;
   }
 
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
index 2b5933f..d6363fb 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
@@ -18,16 +18,28 @@
 
 import com.intellij.compiler.CompilerConfiguration
 import com.intellij.compiler.CompilerConfigurationImpl
+import com.intellij.execution.executors.DefaultRunExecutor
+import com.intellij.execution.impl.DefaultJavaProgramRunner
+import com.intellij.execution.process.ProcessAdapter
+import com.intellij.execution.process.ProcessEvent
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.process.ProcessOutputTypes
+import com.intellij.execution.runners.ProgramRunner
 import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.PathManager
 import com.intellij.openapi.compiler.CompilerMessage
 import com.intellij.openapi.compiler.CompilerMessageCategory
 import com.intellij.openapi.compiler.options.ExcludeEntryDescription
 import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration
 import com.intellij.openapi.module.Module
 import com.intellij.openapi.roots.ModuleRootModificationUtil
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.Ref
 import com.intellij.openapi.vfs.VirtualFile
 import com.intellij.psi.PsiFile
+import com.intellij.testFramework.PsiTestUtil
 import com.intellij.testFramework.TestLoggerFactory
+import org.jetbrains.annotations.NotNull
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
 
 /**
@@ -822,4 +834,35 @@
     def messages = make()
     assert messages.find { it.message.contains("Cannot compile Groovy files: no Groovy library is defined for module 'dependent'") }
   }
+
+  public void testGroovyOutputIsInstrumented() {
+    myFixture.addFileToProject("Bar.groovy",
+       "import org.jetbrains.annotations.NotNull; " +
+       "public class Bar {" +
+         "void xxx(@NotNull String param) { println param }\n" +
+         "static void main(String[] args) { new Bar().xxx(null) }"+
+       "}"
+    );
+
+    File annotations = new File(PathManager.getJarPathForClass(NotNull.class));
+    PsiTestUtil.addLibrary(myModule, "annotations", annotations.getParent(), annotations.getName());
+
+    assertEmpty(make());
+
+    final Ref<Boolean> exceptionFound = Ref.create(Boolean.FALSE);
+    ProcessHandler process = runProcess("Bar", myModule, DefaultRunExecutor.class, new ProcessAdapter() {
+      @Override
+      public void onTextAvailable(ProcessEvent event, Key outputType) {
+        if (ProcessOutputTypes.SYSTEM != outputType) {
+          if (!exceptionFound.get()) {
+            exceptionFound.set(event.getText().contains("java.lang.IllegalArgumentException: Argument for @NotNull parameter 'param' of Bar.xxx must not be null"));
+          }
+        }
+      }
+    }, ProgramRunner.PROGRAM_RUNNER_EP.findExtension(DefaultJavaProgramRunner.class));
+    process.waitFor();
+
+    assertTrue(exceptionFound.get());
+  }
+
 }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
index 7cbf9a9..28b2e26 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
@@ -44,6 +44,7 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.testFramework.CompilerTester;
 import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.testFramework.PsiTestUtil;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
@@ -80,6 +81,13 @@
     super.tuneFixture(moduleBuilder);
   }
 
+  @Override
+  protected void runTest() throws Throwable {
+    if (PlatformTestUtil.COVERAGE_ENABLED_BUILD) return;
+
+    super.runTest();
+  }
+
   protected static void addGroovyLibrary(final Module to) {
     File jar = GroovyFacetUtil.getBundledGroovyJar();
     PsiTestUtil.addLibrary(to, "groovy", jar.getParent(), jar.getName());
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
index 2239271..ce323a1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
@@ -15,11 +15,9 @@
  */
 
 package org.jetbrains.plugins.groovy.refactoring.optimizeImports
-
 import com.intellij.codeInsight.CodeInsightSettings
 import com.intellij.openapi.application.ApplicationManager
 import com.intellij.openapi.command.CommandProcessor
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper
 import com.intellij.psi.codeStyle.CodeStyleSettings
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager
 import com.intellij.psi.impl.source.PostprocessReformattingAspect
@@ -195,7 +193,6 @@
 
       doOptimizeImports();
       PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
-      TrailingSpacesStripper.stripIfNotCurrentLine(myFixture.getEditor().getDocument(), false);
       myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
     }
     finally {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
index 7410b0e..43ef70e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
@@ -16,76 +16,21 @@
 
 package org.zmlx.hg4idea.action;
 
-import com.intellij.dvcs.DvcsUtil;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
 import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogDataKeys;
+import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.HgVcs;
+import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.repo.HgRepositoryManager;
 
-import java.util.List;
+public abstract class HgLogSingleCommitAction extends VcsLogSingleCommitAction<HgRepository> {
 
-/**
- * @author Nadya Zabrodina
- */
-public abstract class HgLogSingleCommitAction extends DumbAwareAction {
-
-  private static final Logger LOG = Logger.getInstance(HgLogSingleCommitAction.class);
-
-  protected abstract void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit);
-
+  @Nullable
   @Override
-  public void actionPerformed(AnActionEvent e) {
-    Data data = Data.collect(e);
-    if (!data.isValid()) {
-      return;
-    }
-
-    List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
-    if (details.size() != 1) {
-      return;
-    }
-    VcsFullCommitDetails commit = details.get(0);
-
-    HgRepositoryManager repositoryManager = ServiceManager.getService(data.project, HgRepositoryManager.class);
-    final HgRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
-    if (repository == null) {
-      DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, HgVcs.getInstance(data.project));
-      return;
-    }
-
-    actionPerformed(repository, commit);
+  protected HgRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+    return ServiceManager.getService(project, HgRepositoryManager.class).getRepositoryForRoot(root);
   }
 
-  @Override
-  public void update(AnActionEvent e) {
-    Data data = Data.collect(e);
-    boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1;
-    e.getPresentation().setVisible(data.isValid());
-    e.getPresentation().setEnabled(enabled);
-  }
-
-  private static class Data {
-    Project project;
-    VcsLog log;
-
-    static Data collect(AnActionEvent e) {
-      Data data = new Data();
-      data.project = e.getData(CommonDataKeys.PROJECT);
-      data.log = e.getData(VcsLogDataKeys.VSC_LOG);
-      return data;
-    }
-
-    boolean isValid() {
-      return project != null && log != null && DvcsUtil.logHasRootForVcs(log, HgVcs.getKey());
-    }
-  }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
index 1d41cdc..14f6c98 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
@@ -35,7 +35,7 @@
 class HgCommandAuthenticator {
 
   private static final Logger LOG = Logger.getInstance(HgCommandAuthenticator.class.getName());
-
+  
   private GetPasswordRunnable myGetPassword;
   private final Project myProject;
   private boolean myForceAuthorization;
@@ -71,7 +71,7 @@
   }
 
   public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) {
-    GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, state);
+    GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization);
     ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
     myGetPassword = runnable;
     return runnable.isOk();
@@ -96,21 +96,14 @@
     @Nullable private String myURL;
     private boolean myRememberPassword;
     private boolean myForceAuthorization;
-    @Nullable private ModalityState myState;
 
-    public GetPasswordRunnable(Project project,
-                               String proposedLogin,
-                               String uri,
-                               String path,
-                               boolean forceAuthorization,
-                               @Nullable ModalityState state) {
+    public GetPasswordRunnable(Project project, String proposedLogin, String uri, String path, boolean forceAuthorization) {
       this.myProject = project;
       this.myProposedLogin = proposedLogin;
       this.myURL = uri + path;
       this.myForceAuthorization = forceAuthorization;
-      myState = state;
     }
-
+    
     public void run() {
 
       // find if we've already been here
@@ -135,9 +128,11 @@
         final String key = keyForUrlAndLogin(myURL, login);
         try {
           final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
-          password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key, myState);
-        }
-        catch (PasswordSafeException e) {
+          password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
+          if (password == null) {
+            password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key);
+          }
+        } catch (PasswordSafeException e) {
           LOG.info("Couldn't get password for key [" + key + "]", e);
         }
       }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index 03c9862..4adec9d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -64,10 +64,13 @@
     return HgHistoryUtil.loadMetadata(myProject, root, requirements.getCommitCount(), Collections.<String>emptyList());
   }
 
-  @NotNull
   @Override
-  public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
-    return HgHistoryUtil.readAllHashes(myProject, root, userRegistry, Collections.<String>emptyList());
+  public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+                            @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
+    List<TimedVcsCommit> commits = HgHistoryUtil.readAllHashes(myProject, root, userRegistry, Collections.<String>emptyList());
+    for (TimedVcsCommit commit : commits) {
+      commitConsumer.consume(commit);
+    }
   }
 
   @NotNull
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
index 61d08bc..1d556a8 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
@@ -15,22 +15,13 @@
  */
 package org.zmlx.hg4idea.provider;
 
-import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogBuilder;
-import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
-import com.intellij.openapi.vcs.history.CurrentRevision;
-import com.intellij.openapi.vcs.history.DiffFromHistoryHandler;
-import com.intellij.openapi.vcs.history.VcsFileRevision;
-import com.intellij.openapi.vcs.history.VcsHistoryUtil;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
 import com.intellij.vcsUtil.VcsUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -44,111 +35,37 @@
  *
  * @author Nadya Zabrodina
  */
-public class HgDiffFromHistoryHandler implements DiffFromHistoryHandler {
+public class HgDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<HgFileRevision> {
 
   private static final Logger LOG = Logger.getInstance(HgDiffFromHistoryHandler.class);
 
-  @NotNull private final Project myProject;
-
   public HgDiffFromHistoryHandler(@NotNull Project project) {
-    myProject = project;
+    super(project);
   }
 
+  @NotNull
   @Override
-  public void showDiffForOne(@NotNull AnActionEvent e, @NotNull FilePath filePath,
-                             @NotNull VcsFileRevision previousRevision, @NotNull VcsFileRevision revision) {
-    doShowDiff(filePath, previousRevision, revision, false);
+  protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull HgFileRevision rev1, @Nullable HgFileRevision rev2) {
+    return executeDiff(path, rev1, rev2);
   }
 
-
+  @NotNull
   @Override
-  public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
-    doShowDiff(filePath, revision1, revision2, true);
+  protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull HgFileRevision rev) throws VcsException {
+    return executeDiff(path, null, rev);
   }
 
-  private void doShowDiff(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2,
-                          boolean autoSort) {
-    if (!filePath.isDirectory()) {
-      VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
-    }
-    else if (revision2 instanceof CurrentRevision) {
-      HgFileRevision left = (HgFileRevision)revision1;
-      showDiffForDirectory(filePath, left, null);
-    }
-    else if (revision1.equals(VcsFileRevision.NULL)) {
-      HgFileRevision right = (HgFileRevision)revision2;
-      showDiffForDirectory(filePath, null, right);
-    }
-    else {
-      HgFileRevision left = (HgFileRevision)revision1;
-      HgFileRevision right = (HgFileRevision)revision2;
-      if (autoSort) {
-        Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
-        left = (HgFileRevision)pair.first;
-        right = (HgFileRevision)pair.second;
-      }
-      showDiffForDirectory(filePath, left, right);
-    }
+  @NotNull
+  @Override
+  protected String getPresentableName(@NotNull HgFileRevision revision) {
+    return revision.getRevisionNumber().getChangeset();
   }
 
-  private void showDiffForDirectory(@NotNull final FilePath path,
-                                    @Nullable final HgFileRevision rev1,
-                                    @Nullable final HgFileRevision rev2) {
+  @NotNull
+  private List<Change> executeDiff(@NotNull FilePath path, @Nullable HgFileRevision rev1, @Nullable HgFileRevision rev2) {
     VirtualFile root = VcsUtil.getVcsRootFor(myProject, path);
     LOG.assertTrue(root != null, "Repository is null for " + path);
-    calculateDiffInBackground(root, path, rev1, rev2, new Consumer<List<Change>>() {
-      @Override
-      public void consume(List<Change> changes) {
-        showDirDiffDialog(path, rev1 != null ? rev1.getRevisionNumber().getChangeset() : null,
-                          rev2 != null ? rev2.getRevisionNumber().getChangeset() : null, changes);
-      }
-    });
+
+    return HgUtil.getDiff(myProject, root, path, rev1, rev2);
   }
-
-  // rev1 == null => rev2 is the initial commit
-  // rev2 == null => comparing rev1 with local
-  private void calculateDiffInBackground(@NotNull final VirtualFile root, @NotNull final FilePath path,
-                                         @Nullable final HgFileRevision rev1, @Nullable final HgFileRevision rev2,
-                                         final Consumer<List<Change>> successHandler) {
-    new Task.Backgroundable(myProject, "Comparing revisions...") {
-      private List<Change> myChanges;
-
-      @Override
-      public void run(@NotNull ProgressIndicator indicator) {
-        if (myProject != null) {
-          myChanges = HgUtil.getDiff(HgDiffFromHistoryHandler.this.myProject, root, path, rev1, rev2);
-        }
-      }
-
-      @Override
-      public void onSuccess() {
-        successHandler.consume(myChanges);
-      }
-    }.queue();
-  }
-
-  private void showDirDiffDialog(@NotNull FilePath path, @Nullable String hash1, @Nullable String hash2, @NotNull List<Change> diff) {
-    DialogBuilder dialogBuilder = new DialogBuilder(myProject);
-    String title;
-    if (hash2 != null) {
-      if (hash1 != null) {
-        title = String.format("Difference between %s and %s in %s", hash1, hash2, path.getName());
-      }
-      else {
-        title = String.format("Initial commit %s in %s", hash2, path.getName());
-      }
-    }
-    else {
-      LOG.assertTrue(hash1 != null, "hash1 and hash2 can't both be null. Path: " + path);
-      title = String.format("Difference between %s and local version in %s", hash1, path.getName());
-    }
-    dialogBuilder.setTitle(title);
-    dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[]{new DialogBuilder.CloseDialogAction()});
-    final ChangesBrowser changesBrowser = new ChangesBrowser(myProject, null, diff, null, false, true,
-                                                             null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
-    changesBrowser.setChangesToDisplay(diff);
-    dialogBuilder.setCenterPanel(changesBrowser);
-    dialogBuilder.showNotModal();
-  }
-}
-
+}
\ No newline at end of file
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
index 2a654c4..359c850 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
@@ -65,7 +65,7 @@
     List<String> split = splitCommandInParameters(command);
     split.add(0, HG_EXECUTABLE);
     debug("hg " + command);
-    return run(split, ignoreNonZeroExitCode);
+    return run(ourCurrentDir(), split, ignoreNonZeroExitCode);
   }
 
   public static void updateProject() {
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
index 592bfbc..155d837 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
@@ -39,7 +39,7 @@
     int i = 4; //some street magic
     while (element != null && i > 0) {
       final ASTNode node = element.getNode();
-      if (node != null && node.getUserData(KEY) != null) {
+      if (node != null && node.getUserData(KEY) instanceof PropertyFoldingBuilder) {
         break;
       }
       else {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
index 28c99b0..9aa2e72 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
@@ -54,7 +54,7 @@
       final PsiClass paneClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_SCENE_LAYOUT_PANE, GlobalSearchScope.allScope(project));
       if (paneClass != null) {
         final ArrayList<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();
-        ClassInheritorsSearch.search(paneClass).forEach(new Processor<PsiClass>() {
+        ClassInheritorsSearch.search(paneClass, paneClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
           @Override
           public boolean process(PsiClass psiClass) {
             result.add(new JavaFxClassBackedElementDescriptor(psiClass.getName(), psiClass));
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
index b10ebcb..617895f 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
@@ -78,7 +78,7 @@
     if (collectionItemType != null) {
       final PsiClass aClass = PsiUtil.resolveClassInType(collectionItemType);
       if (aClass != null) {
-        ClassInheritorsSearch.search(aClass).forEach(new Processor<PsiClass>() {
+        ClassInheritorsSearch.search(aClass, aClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
           @Override
           public boolean process(PsiClass aClass) {
             descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
index 6ea5c51..a0e9bd5 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
@@ -27,7 +27,7 @@
   public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
     return JavaFxFileTypeFactory.FXML_EXTENSION.equalsIgnoreCase(file.getExtension()) &&
            SystemInfo.isJavaVersionAtLeast("1.8") &&
-           Registry.is("embed.scene.builder", true);
+           Registry.is("embed.scene.builder");
   }
 
   @NotNull
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index 9a78876..cc7c0ee 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -217,7 +217,7 @@
 
     myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath());
     myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class));
-    if (Registry.is("junit_sm_runner", false)) {
+    if (Registry.is("junit_sm_runner")) {
       myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(ServiceMessageTypes.class));
     }
     myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
@@ -273,7 +273,7 @@
 
   @Override
   public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
-    final boolean smRunner = Registry.is("junit_sm_runner", false);
+    final boolean smRunner = Registry.is("junit_sm_runner");
     if (smRunner) {
       myJavaParameters.getVMParametersList().add("-Didea.junit.sm_runner");
     }
diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
index fe5a131..9f04e6a 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
@@ -172,7 +172,7 @@
     final JUnitConfiguration.Data data = configuration.getPersistentData();
     setTestType(data.TEST_OBJECT);
     setJUnitTextValue(ALL_IN_PACKAGE, data.getPackageName());
-    setJUnitTextValue(CLASS, data.getMainClassName().replaceAll("\\$", "\\."));
+    setJUnitTextValue(CLASS, data.getMainClassName() != null ? data.getMainClassName().replaceAll("\\$", "\\.") : "");
     setJUnitTextValue(METHOD, data.getMethodName());
     setJUnitTextValue(PATTERN, data.getPatternPresentation());
     setJUnitTextValue(DIR, data.getDirName());
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java
new file mode 100644
index 0000000..ed9886a
--- /dev/null
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.maven.model;
+
+import gnu.trove.THashSet;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: vladimir.dubovik
+ * Date: 4/9/2014
+ * Time: 2:30 AM
+ */
+public class MavenExplicitProfiles implements Serializable {
+  public static final MavenExplicitProfiles NONE = new MavenExplicitProfiles(Collections.<String>emptySet());
+
+  private Collection<String> myEnabledProfiles;
+  private Collection<String> myDisabledProfiles;
+
+  public MavenExplicitProfiles(Collection<String> enabledProfiles, Collection<String> disabledProfiles) {
+    myEnabledProfiles = enabledProfiles;
+    myDisabledProfiles = disabledProfiles;
+  }
+
+  public MavenExplicitProfiles(Collection<String> enabledProfiles) {
+    this(enabledProfiles, Collections.<String>emptySet());
+  }
+
+  public Collection<String> getEnabledProfiles() {
+    return myEnabledProfiles;
+  }
+
+  public Collection<String> getDisabledProfiles() {
+    return myDisabledProfiles;
+  }
+
+  @Override
+  public MavenExplicitProfiles clone() {
+    return new MavenExplicitProfiles(new THashSet<String>(myEnabledProfiles), new THashSet<String>(myDisabledProfiles));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    MavenExplicitProfiles that = (MavenExplicitProfiles)o;
+
+    if (!myEnabledProfiles.equals(that.myEnabledProfiles)) return false;
+    if (!myDisabledProfiles.equals(that.myDisabledProfiles)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myEnabledProfiles.hashCode();
+    result = 31 * result + myDisabledProfiles.hashCode();
+    return result;
+  }
+}
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
index 7c945e8..827fc28 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.idea.maven.server;
 
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenModel;
 
 import java.io.File;
@@ -35,6 +36,6 @@
 
   ProfileApplicationResult applyProfiles(MavenModel model,
                                          File basedir,
-                                         Collection<String> explicitProfiles,
+                                         MavenExplicitProfiles explicitProfiles,
                                          Collection<String> alwaysOnProfiles) throws RemoteException;
 }
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
index 0c4be99..6b3db15 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
@@ -34,12 +34,15 @@
 
   @NotNull
   MavenServerExecutionResult resolveProject(@NotNull File file,
-                                            @NotNull Collection<String> activeProfiles) throws RemoteException,
-                                                                                               MavenServerProcessCanceledException;
+                                            @NotNull Collection<String> activeProfiles,
+                                            @NotNull Collection<String> inactiveProfiles) throws RemoteException,
+                                                                                                 MavenServerProcessCanceledException;
 
   @Nullable
-  String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) throws RemoteException,
-                                                                                                 MavenServerProcessCanceledException;
+  String evaluateEffectivePom(@NotNull File file,
+                              @NotNull List<String> activeProfiles,
+                              @NotNull List<String> inactiveProfiles) throws RemoteException,
+                                                                             MavenServerProcessCanceledException;
 
   @NotNull
   MavenArtifact resolve(@NotNull MavenArtifactInfo info,
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
index f86f74c..d8283d4 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
@@ -15,16 +15,16 @@
  */
 package org.jetbrains.idea.maven.server;
 
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenModel;
 
 import java.io.Serializable;
-import java.util.Collection;
 
 public class ProfileApplicationResult implements Serializable {
   private final MavenModel myModel;
-  private final Collection<String> myActivatedProfiles;
+  private final MavenExplicitProfiles myActivatedProfiles;
 
-  public ProfileApplicationResult(MavenModel model, Collection<String> activatedProfiles) {
+  public ProfileApplicationResult(MavenModel model, MavenExplicitProfiles activatedProfiles) {
     myModel = model;
     myActivatedProfiles = activatedProfiles;
   }
@@ -33,7 +33,7 @@
     return myModel;
   }
 
-  public Collection<String> getActivatedProfiles() {
+  public MavenExplicitProfiles getActivatedProfiles() {
     return myActivatedProfiles;
   }
 }
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
index 770b952..801bae42 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.idea.maven.server;
 
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenModel;
 import org.jetbrains.idea.maven.server.embedder.Maven2ServerEmbedderImpl;
 import org.jetbrains.idea.maven.server.embedder.Maven2ServerIndexerImpl;
@@ -76,7 +77,7 @@
 
   public ProfileApplicationResult applyProfiles(MavenModel model,
                                                 File basedir,
-                                                Collection<String> explicitProfiles,
+                                                MavenExplicitProfiles explicitProfiles,
                                                 Collection<String> alwaysOnProfiles) {
     try {
       return Maven2ServerEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
index 7ed82b0..08e98de 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
@@ -127,13 +127,15 @@
 
   @NotNull
   public MavenServerExecutionResult resolveProject(@NotNull final File file,
-                                                    @NotNull final Collection<String> activeProfiles)
+                                                   @NotNull final Collection<String> activeProfiles,
+                                                   @NotNull final Collection<String> inactiveProfiles)
     throws MavenServerProcessCanceledException, RemoteException {
     return doExecute(new Executor<MavenServerExecutionResult>() {
       public MavenServerExecutionResult execute() throws Exception {
         DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
         MavenExecutionResult result = myImpl.resolveProject(file,
                                                             new ArrayList<String>(activeProfiles),
+                                                            new ArrayList<String>(inactiveProfiles),
                                                             Arrays.<ResolutionListener>asList(listener));
         return createExecutionResult(file, result, listener.getRootNode());
       }
@@ -199,7 +201,7 @@
   }
 
   @Nullable
-  public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) {
+  public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles, @NotNull List<String> inactiveProfiles) {
     throw new UnsupportedOperationException();
   }
 
@@ -422,21 +424,29 @@
 
   public static ProfileApplicationResult applyProfiles(MavenModel model,
                                                        File basedir,
-                                                       Collection<String> explicitProfiles,
+                                                       MavenExplicitProfiles explicitProfiles,
                                                        Collection<String> alwaysOnProfiles) throws RemoteException {
     Model nativeModel = Maven2ModelConverter.toNativeModel(model);
 
+    Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
+    Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
     List<Profile> activatedPom = new ArrayList<Profile>();
     List<Profile> activatedExternal = new ArrayList<Profile>();
     List<Profile> activeByDefault = new ArrayList<Profile>();
 
     List<Profile> rawProfiles = nativeModel.getProfiles();
     List<Profile> expandedProfilesCache = null;
+    List<Profile> deactivatedProfiles = new ArrayList<Profile>();
 
     for (int i = 0; i < rawProfiles.size(); i++) {
       Profile eachRawProfile = rawProfiles.get(i);
 
-      boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
+      if (disabledProfiles.contains(eachRawProfile.getId())) {
+        deactivatedProfiles.add(eachRawProfile);
+        continue;
+      }
+
+      boolean shouldAdd = enabledProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
 
       Activation activation = eachRawProfile.getActivation();
       if (activation != null) {
@@ -479,7 +489,9 @@
     }
 
     return new ProfileApplicationResult(Maven2ModelConverter.convertModel(nativeModel, null),
-                                        collectProfilesIds(activatedProfiles));
+                                        new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
+                                                                  collectProfilesIds(deactivatedProfiles))
+    );
   }
 
   private static ProfileActivator[] getProfileActivators(File basedir) throws RemoteException {
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
index 3926a3d..70a6e47 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
@@ -173,15 +173,18 @@
   }
 
   @NotNull
-  public MavenExecutionResult resolveProject(@NotNull final File file, @NotNull final List<String> activeProfiles) {
-    return resolveProject(file, activeProfiles, Collections.<ResolutionListener>emptyList());
+  public MavenExecutionResult resolveProject(@NotNull final File file,
+                                             @NotNull final List<String> activeProfiles,
+                                             @NotNull final List<String> inactiveProfiles) {
+    return resolveProject(file, activeProfiles, inactiveProfiles, Collections.<ResolutionListener>emptyList());
   }
 
   @NotNull
   public MavenExecutionResult resolveProject(@NotNull final File file,
                                              @NotNull final List<String> activeProfiles,
+                                             @NotNull final List<String> inactiveProfiles,
                                              List<ResolutionListener> listeners) {
-    MavenExecutionRequest request = createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+    MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
     ProjectBuilderConfiguration config = request.getProjectBuilderConfiguration();
 
     request.getGlobalProfileManager().loadSettingsProfiles(mySettings);
diff --git a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
index 53a6d0f..0fc588e 100644
--- a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
+++ b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
@@ -94,7 +94,8 @@
                      "<version>1</version>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.execute(myProjectPom, Collections.<String>emptyList(), Arrays.asList("compile"));
+    MavenServerExecutionResult result =
+      myEmbedder.execute(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("compile"));
 
     assertNotNull(result.projectData);
     assertNotNull(new File(getProjectPath(), "target").exists());
@@ -119,7 +120,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts);
 
@@ -135,7 +137,8 @@
                      "<version>1</version>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     MavenModel project = result.projectData.mavenModel;
     assertNotNull(project);
@@ -171,7 +174,8 @@
                      "</build>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts);
@@ -203,7 +207,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts);
@@ -264,7 +269,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
@@ -286,7 +292,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
@@ -304,7 +311,7 @@
                                     "<version>1</version>" +
                                     "<packaging>pom</packaging>");
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    myEmbedder.execute(m, Collections.<String>emptyList(), Arrays.asList("install"));
+    myEmbedder.execute(m, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("install"));
     myEmbedder.reset();
     File fooParentFile = new File(repo, "test/foo-parent/1/foo-parent-1.pom");
     assertTrue(fooParentFile.exists());
@@ -319,7 +326,7 @@
                         "  <version>1</version>" +
                         "</parent>");
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    myEmbedder.execute(m, Collections.<String>emptyList(), Arrays.asList("install"));
+    myEmbedder.execute(m, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("install"));
     myEmbedder.reset();
     assertTrue(new File(repo, "test/foo/1/foo-1.pom").exists());
 
@@ -339,7 +346,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result.projectData);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("test", "foo-parent", "1"));
@@ -361,7 +369,8 @@
                      "</dependencies>");
 
     myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
-    MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+    MavenServerExecutionResult result =
+      myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
 
     assertNotNull(result);
     assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
index 66a5943..854c099 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
@@ -300,20 +300,22 @@
 
   @NotNull
   @Override
-  public MavenServerExecutionResult resolveProject(@NotNull File file, @NotNull Collection<String> activeProfiles)
+  public MavenServerExecutionResult resolveProject(@NotNull File file,
+                                                   @NotNull Collection<String> activeProfiles,
+                                                   @NotNull Collection<String> inactiveProfiles)
     throws RemoteException, MavenServerProcessCanceledException {
     DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
 
-    MavenExecutionResult result =
-      doResolveProject(file, new ArrayList<String>(activeProfiles), Arrays.<ResolutionListener>asList(listener));
+    MavenExecutionResult result = doResolveProject(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles),
+                                                   Arrays.<ResolutionListener>asList(listener));
     return createExecutionResult(file, result, listener.getRootNode());
   }
 
   @Nullable
   @Override
-  public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles)
+  public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles, @NotNull List<String> inactiveProfiles)
     throws RemoteException, MavenServerProcessCanceledException {
-    return MavenEffectivePomDumper.evaluateEffectivePom(this, file, activeProfiles);
+    return MavenEffectivePomDumper.evaluateEffectivePom(this, file, activeProfiles, inactiveProfiles);
   }
 
   public void executeWithMavenSession(MavenExecutionRequest request, Runnable runnable) {
@@ -350,9 +352,9 @@
   @NotNull
   public MavenExecutionResult doResolveProject(@NotNull final File file,
                                                @NotNull final List<String> activeProfiles,
+                                               @NotNull final List<String> inactiveProfiles,
                                                final List<ResolutionListener> listeners) throws RemoteException {
-    final MavenExecutionRequest request =
-      createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+    final MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
 
     request.setUpdateSnapshots(myAlwaysUpdateSnapshots);
 
@@ -899,21 +901,29 @@
 
   public static ProfileApplicationResult applyProfiles(MavenModel model,
                                                        File basedir,
-                                                       Collection<String> explicitProfiles,
+                                                       MavenExplicitProfiles explicitProfiles,
                                                        Collection<String> alwaysOnProfiles) throws RemoteException {
     Model nativeModel = MavenModelConverter.toNativeModel(model);
 
+    Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
+    Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
     List<Profile> activatedPom = new ArrayList<Profile>();
     List<Profile> activatedExternal = new ArrayList<Profile>();
     List<Profile> activeByDefault = new ArrayList<Profile>();
 
     List<Profile> rawProfiles = nativeModel.getProfiles();
     List<Profile> expandedProfilesCache = null;
+    List<Profile> deactivatedProfiles = new ArrayList<Profile>();
 
     for (int i = 0; i < rawProfiles.size(); i++) {
       Profile eachRawProfile = rawProfiles.get(i);
 
-      boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
+      if (disabledProfiles.contains(eachRawProfile.getId())) {
+        deactivatedProfiles.add(eachRawProfile);
+        continue;
+      }
+
+      boolean shouldAdd = enabledProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
 
       Activation activation = eachRawProfile.getActivation();
       if (activation != null) {
@@ -955,7 +965,10 @@
       new DefaultProfileInjector().injectProfile(nativeModel, each, null, null);
     }
 
-    return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null), collectProfilesIds(activatedProfiles));
+    return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null),
+                                        new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
+                                                                  collectProfilesIds(deactivatedProfiles))
+    );
   }
 
   private static Model doInterpolate(Model result, File basedir) throws RemoteException {
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
index 0e4d468..cc33728 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.idea.maven.server;
 
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenModel;
 
 import java.io.File;
@@ -74,7 +75,7 @@
 
   public ProfileApplicationResult applyProfiles(MavenModel model,
                                                 File basedir,
-                                                Collection<String> explicitProfiles,
+                                                MavenExplicitProfiles explicitProfiles,
                                                 Collection<String> alwaysOnProfiles) {
     try {
       return Maven3ServerEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
index 2d0c90d..75d45f5 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
@@ -47,14 +47,14 @@
   @Nullable
   public static String evaluateEffectivePom(final Maven3ServerEmbedderImpl embedder,
                                             @NotNull final File file,
-                                            @NotNull List<String> activeProfiles)
+                                            @NotNull List<String> activeProfiles,
+                                            @NotNull List<String> inactiveProfiles)
     throws RemoteException, MavenServerProcessCanceledException {
 
     final StringWriter w = new StringWriter();
 
     try {
-      final MavenExecutionRequest
-        request = embedder.createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+      final MavenExecutionRequest request = embedder.createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
 
       embedder.executeWithMavenSession(request, new Runnable() {
         @Override
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
index 15899e7..a51ddfe 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
@@ -18,6 +18,7 @@
 import com.intellij.util.ReflectionUtil;
 
 import java.rmi.RemoteException;
+import java.util.Collections;
 import java.util.IdentityHashMap;
 import java.util.Map;
 
@@ -54,14 +55,14 @@
   }
 
   private Map<Thread, Thread> getShutdownHooks() {
-    Class clazz = null;
+    Class clazz;
     try {
       clazz = Class.forName("java.lang.ApplicationShutdownHooks");
     }
     catch (ClassNotFoundException e) {
       // we can ignore this one
+      return Collections.emptyMap();
     }
     return ReflectionUtil.getField(clazz, null, Map.class, "hooks");
   }
-
 }
diff --git a/plugins/maven/pom.xml b/plugins/maven/pom.xml
index 4105226..c2f0c71 100644
--- a/plugins/maven/pom.xml
+++ b/plugins/maven/pom.xml
@@ -9,7 +9,7 @@
 
   <name>Maven Integration</name>
   <description>Maven Integration plugin</description>
-  
+
   <repositories>
   </repositories>
 
@@ -17,7 +17,7 @@
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-embedder</artifactId>
-      <version>2.1-SNAPSHOT</version>
+      <version>3.0.5</version>
       <exclusions>
         <exclusion>
           <groupId>aspectj</groupId>
@@ -38,9 +38,9 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>com.sonatype.nexus</groupId>
+      <groupId>org.sonatype.nexus</groupId>
       <artifactId>nexus-indexer</artifactId>
-      <version>1.0.0-SNAPSHOT</version>
+      <version>3.0.4</version>
       <exclusions>
         <exclusion>
           <groupId>junit</groupId>
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
index ceebebb..ba3d265 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
@@ -514,11 +514,12 @@
                                              MavenProject mavenProjectOrNull,
                                              Processor<T> processor,
                                              Function<? super MavenDomProfile, T> f) {
-    Collection<String> activePropfiles = mavenProjectOrNull == null ? null : mavenProjectOrNull.getActivatedProfilesIds();
+    Collection<String> activeProfiles =
+      mavenProjectOrNull == null ? null : mavenProjectOrNull.getActivatedProfilesIds().getEnabledProfiles();
     for (MavenDomProfile each : profilesDom.getProfiles()) {
       XmlTag idTag = each.getId().getXmlTag();
       if (idTag == null) continue;
-      if (activePropfiles != null && !activePropfiles.contains(idTag.getValue().getTrimmedText())) continue;
+      if (activeProfiles != null && !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
 
       if (processProfile(each, processor, f)) return true;
     }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
index 6687589..0422898 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
@@ -81,10 +81,10 @@
                                    @Nullable Map<String, String> resolvedPropertiesParam,
                                    Appendable out) throws IOException {
     Map<String, String> resolvedProperties = resolvedPropertiesParam;
-    
+
     Matcher matcher = pattern.matcher(text);
     int groupCount = matcher.groupCount();
-    
+
     int last = 0;
     while (matcher.find()) {
       if (escapeString != null) {
@@ -116,7 +116,7 @@
       if (resolvedProperties == null) {
         resolvedProperties = new HashMap<String, String>();
       }
-      
+
       String propertyValue = resolvedProperties.get(propertyName);
       if (propertyValue == null) {
         if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
@@ -146,7 +146,7 @@
         out.append(propertyValue);
       }
     }
-    
+
     out.append(text, last, text.length());
   }
 
@@ -177,10 +177,10 @@
 
     collectPropertiesFromDOM(projectDom.getProperties(), result);
 
-    Collection<String> activePropfiles = project.getActivatedProfilesIds();
+    Collection<String> activeProfiles = project.getActivatedProfilesIds().getEnabledProfiles();
     for (MavenDomProfile each : projectDom.getProfiles().getProfiles()) {
       XmlTag idTag = each.getId().getXmlTag();
-      if (idTag == null || !activePropfiles.contains(idTag.getValue().getTrimmedText())) continue;
+      if (idTag == null || !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
       collectPropertiesFromDOM(each.getProperties(), result);
     }
 
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
index 0bf342f..13b58ca 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
@@ -29,6 +29,7 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 
 import java.util.Collection;
@@ -76,9 +77,9 @@
 
     VirtualFile f = ((PsiFile)l.getPsiElement()).getVirtualFile();
     List<String> goals = ((MavenGoalLocation)l).getGoals();
-    Collection<String> profiles = MavenProjectsManager.getInstance(l.getProject()).getExplicitProfiles();
+    MavenExplicitProfiles profiles = MavenProjectsManager.getInstance(l.getProject()).getExplicitProfiles();
 
-    return new MavenRunnerParameters(true, f.getParent().getPath(), goals, profiles);
+    return new MavenRunnerParameters(true, f.getParent().getPath(), goals, profiles.getEnabledProfiles(), profiles.getDisabledProfiles());
   }
 
   public int compareTo(Object o) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
index c04f2d3..bca71b2 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
@@ -23,6 +23,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.utils.Path;
 
 import java.io.File;
@@ -53,6 +54,13 @@
   public MavenRunnerParameters(boolean isPomExecution,
                                @NotNull String workingDirPath,
                                @Nullable List<String> goals,
+                               @NotNull MavenExplicitProfiles explicitProfiles) {
+    this(isPomExecution, workingDirPath, goals, explicitProfiles.getEnabledProfiles(), explicitProfiles.getDisabledProfiles());
+  }
+
+  public MavenRunnerParameters(boolean isPomExecution,
+                               @NotNull String workingDirPath,
+                               @Nullable List<String> goals,
                                @Nullable Collection<String> explicitEnabledProfiles,
                                @Nullable Collection<String> explicitDisabledProfiles) {
     this.isPomExecution = isPomExecution;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
index 65e1b5e..e2a313e 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
@@ -19,12 +19,15 @@
 import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.module.ModifiableModuleModel;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.*;
 import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl;
 import com.intellij.openapi.roots.libraries.Library;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.JarFileSystem;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFileManager;
@@ -45,6 +48,7 @@
 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.Set;
 
 public class MavenRootModelAdapter {
@@ -176,10 +180,7 @@
 
   public boolean isAlreadyExcluded(File f) {
     String url = toUrl(f.getPath()).getUrl();
-    for (String excludedUrl : myRootModel.getExcludeRootUrls()) {
-      if (VfsUtilCore.isEqualOrAncestor(excludedUrl, url)) return true;
-    }
-    return false;
+    return VfsUtilCore.isUnder(url, Arrays.asList(myRootModel.getExcludeRootUrls()));
   }
 
   private boolean exists(String path) {
@@ -193,6 +194,10 @@
     if (e == null) return;
     if (e.getUrl().equals(url.getUrl())) return;
     e.addExcludeFolder(url.getUrl());
+    if (!Registry.is("ide.hide.excluded.files")) {
+      Project project = myRootModel.getProject();
+      ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(toPath(path).getPath());
+    }
   }
 
   public void unregisterAll(String path, boolean under, boolean unregisterSources) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
index 8676153..04e93ac 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
@@ -39,6 +39,7 @@
 import org.jetbrains.idea.maven.execution.MavenGoalLocation;
 import org.jetbrains.idea.maven.model.MavenArtifact;
 import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 import org.jetbrains.idea.maven.utils.MavenDataKeys;
@@ -226,9 +227,9 @@
 
   private Object extractProfiles() {
     final List<MavenProjectsStructure.ProfileNode> nodes = getSelectedNodes(MavenProjectsStructure.ProfileNode.class);
-    final List<String> profiles = new ArrayList<String>();
+    final Map<String, MavenProfileKind> profiles = new THashMap<String, MavenProfileKind>();
     for (MavenProjectsStructure.ProfileNode node : nodes) {
-      profiles.add(node.getProfileName());
+      profiles.put(node.getProfileName(), node.getState());
     }
     return profiles;
   }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
index e591bb6..8c02946 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
@@ -37,6 +37,7 @@
 import javax.swing.event.HyperlinkEvent;
 import java.io.File;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 
@@ -105,7 +106,7 @@
       return;
     }
 
-    MavenRunnerParameters parameters = new MavenRunnerParameters(true, workDirectory, Arrays.asList(ParametersList.parse(goals)), null);
+    MavenRunnerParameters parameters = new MavenRunnerParameters(true, workDirectory, Arrays.asList(ParametersList.parse(goals)), Collections.<String>emptyList());
 
     MavenGeneralSettings generalSettings = new MavenGeneralSettings();
     generalSettings.setMavenHome(mavenHome.getPath());
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
index 70a8aa8..01fc838 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
@@ -19,7 +19,6 @@
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.module.StdModuleTypes;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ui.LightFilePointer;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Key;
@@ -29,13 +28,11 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
 import com.intellij.util.containers.ContainerUtil;
 import gnu.trove.THashSet;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.maven.dom.MavenDomUtil;
 import org.jetbrains.idea.maven.importing.MavenExtraArtifactType;
 import org.jetbrains.idea.maven.importing.MavenImporter;
 import org.jetbrains.idea.maven.model.*;
@@ -607,7 +604,7 @@
 
   @NotNull
   public MavenProjectChanges read(@NotNull MavenGeneralSettings generalSettings,
-                                  @NotNull Collection<String> profiles,
+                                  @NotNull MavenExplicitProfiles profiles,
                                   @NotNull MavenProjectReader reader,
                                   @NotNull MavenProjectReaderProjectLocator locator) {
     return set(reader.readProject(generalSettings, myFile, profiles, locator), generalSettings, true, false, true);
@@ -805,7 +802,7 @@
   }
 
   @NotNull
-  public Collection<String> getActivatedProfilesIds() {
+  public MavenExplicitProfiles getActivatedProfilesIds() {
     return myState.myActivatedProfilesIds;
   }
 
@@ -1089,7 +1086,7 @@
     Map<String, String> myModelMap;
 
     Collection<String> myProfilesIds;
-    Collection<String> myActivatedProfilesIds;
+    MavenExplicitProfiles myActivatedProfilesIds;
 
     Collection<MavenProjectProblem> myReadingProblems;
     Set<MavenId> myUnresolvedArtifactIds;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
index bb465f5..31f245c 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
@@ -47,9 +47,9 @@
 
   public MavenProjectReaderResult readProject(MavenGeneralSettings generalSettings,
                                               VirtualFile file,
-                                              Collection<String> explicitProfiles,
+                                              MavenExplicitProfiles explicitProfiles,
                                               MavenProjectReaderProjectLocator locator) {
-    Pair<RawModelReadResult, Collection<String>> readResult =
+    Pair<RawModelReadResult, MavenExplicitProfiles> readResult =
       doReadProjectModel(generalSettings, file, explicitProfiles, new THashSet<VirtualFile>(), locator);
 
     File basedir = getBaseDir(file);
@@ -76,11 +76,11 @@
     return new File(file.getParent().getPath());
   }
 
-  private Pair<RawModelReadResult, Collection<String>> doReadProjectModel(MavenGeneralSettings generalSettings,
-                                                                          VirtualFile file,
-                                                                          Collection<String> explicitProfiles,
-                                                                          Set<VirtualFile> recursionGuard,
-                                                                          MavenProjectReaderProjectLocator locator) {
+  private Pair<RawModelReadResult, MavenExplicitProfiles> doReadProjectModel(MavenGeneralSettings generalSettings,
+                                                                             VirtualFile file,
+                                                                             MavenExplicitProfiles explicitProfiles,
+                                                                             Set<VirtualFile> recursionGuard,
+                                                                             MavenProjectReaderProjectLocator locator) {
     RawModelReadResult cachedModel = myRawModelsCache.get(file);
     if (cachedModel == null) {
       cachedModel = doReadProjectModel(file, false);
@@ -364,7 +364,7 @@
 
   private static ProfileApplicationResult applyProfiles(MavenModel model,
                                                         File basedir,
-                                                        Collection<String> explicitProfiles,
+                                                        MavenExplicitProfiles explicitProfiles,
                                                         Collection<String> alwaysOnProfiles) {
     return MavenServerManager.getInstance().applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
   }
@@ -372,7 +372,7 @@
   private MavenModel resolveInheritance(final MavenGeneralSettings generalSettings,
                                         MavenModel model,
                                         final VirtualFile file,
-                                        final Collection<String> explicitProfiles,
+                                        final MavenExplicitProfiles explicitProfiles,
                                         final Set<VirtualFile> recursionGuard,
                                         final MavenProjectReaderProjectLocator locator,
                                         Collection<MavenProjectProblem> problems) {
@@ -456,21 +456,23 @@
   public MavenProjectReaderResult resolveProject(MavenGeneralSettings generalSettings,
                                                  MavenEmbedderWrapper embedder,
                                                  VirtualFile file,
-                                                 Collection<String> explicitProfiles,
+                                                 MavenExplicitProfiles explicitProfiles,
                                                  MavenProjectReaderProjectLocator locator) throws MavenProcessCanceledException {
     try {
-      MavenServerExecutionResult result = embedder.resolveProject(file, explicitProfiles);
-      if (result.projectData == null) {
+      MavenServerExecutionResult result =
+        embedder.resolveProject(file, explicitProfiles.getEnabledProfiles(), explicitProfiles.getDisabledProfiles());
+      MavenServerExecutionResult.ProjectData projectData = result.projectData;
+      if (projectData == null) {
         MavenProjectReaderResult temp = readProject(generalSettings, file, explicitProfiles, locator);
         temp.readingProblems.addAll(result.problems);
         temp.unresolvedArtifactIds.addAll(result.unresolvedArtifacts);
         return temp;
       }
 
-      return new MavenProjectReaderResult(result.projectData.mavenModel,
-                                          result.projectData.mavenModelMap,
-                                          result.projectData.activatedProfiles,
-                                          result.projectData.nativeMavenProject,
+      return new MavenProjectReaderResult(projectData.mavenModel,
+                                          projectData.mavenModelMap,
+                                          new MavenExplicitProfiles(projectData.activatedProfiles, explicitProfiles.getDisabledProfiles()),
+                                          projectData.nativeMavenProject,
                                           result.problems,
                                           result.unresolvedArtifacts);
     }
@@ -497,17 +499,18 @@
   public static MavenProjectReaderResult generateSources(MavenEmbedderWrapper embedder,
                                                          MavenImportingSettings importingSettings,
                                                          VirtualFile file,
-                                                         Collection<String> profiles,
+                                                         MavenExplicitProfiles profiles,
                                                          MavenConsole console) throws MavenProcessCanceledException {
     try {
       List<String> goals = Collections.singletonList(importingSettings.getUpdateFoldersOnImportPhase());
-      MavenServerExecutionResult result = embedder.execute(file, profiles, goals);
-      if (result.projectData == null) return null;
+      MavenServerExecutionResult result = embedder.execute(file, profiles.getEnabledProfiles(), profiles.getDisabledProfiles(), goals);
+      MavenServerExecutionResult.ProjectData projectData = result.projectData;
+      if (projectData == null) return null;
 
-      return new MavenProjectReaderResult(result.projectData.mavenModel,
-                                          result.projectData.mavenModelMap,
-                                          result.projectData.activatedProfiles,
-                                          result.projectData.nativeMavenProject,
+      return new MavenProjectReaderResult(projectData.mavenModel,
+                                          projectData.mavenModelMap,
+                                          new MavenExplicitProfiles(projectData.activatedProfiles, profiles.getDisabledProfiles()),
+                                          projectData.nativeMavenProject,
                                           result.problems,
                                           result.unresolvedArtifacts);
     }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
index 29ac462..cbec801 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
@@ -16,6 +16,7 @@
 package org.jetbrains.idea.maven.project;
 
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenId;
 import org.jetbrains.idea.maven.model.MavenModel;
 import org.jetbrains.idea.maven.model.MavenProjectProblem;
@@ -28,14 +29,14 @@
 public class MavenProjectReaderResult {
   public final MavenModel mavenModel;
   public final Map<String, String> nativeModelMap;
-  public final Collection<String> activatedProfiles;
+  public final MavenExplicitProfiles activatedProfiles;
   @Nullable public final NativeMavenProjectHolder nativeMavenProject;
   public final Collection<MavenProjectProblem> readingProblems;
   public final Set<MavenId> unresolvedArtifactIds;
 
   public MavenProjectReaderResult(MavenModel mavenModel,
                                   Map<String, String> nativeModelMap,
-                                  Collection<String> activatedProfiles,
+                                  MavenExplicitProfiles activatedProfiles,
                                   @Nullable NativeMavenProjectHolder nativeMavenProject,
                                   Collection<MavenProjectProblem> readingProblems,
                                   Set<MavenId> unresolvedArtifactIds) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
index 4671a26..6ff6c85 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
@@ -25,8 +25,11 @@
  */
 @State(
   name = "MavenProjectSettings",
-  storages = {@Storage(
-    file = StoragePathMacros.PROJECT_CONFIG_DIR + "/mavenProjectSettings.xml")})
+  storages = {
+    @Storage(file = StoragePathMacros.PROJECT_FILE),
+    @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/mavenProjectSettings.xml", scheme = StorageScheme.DIRECTORY_BASED)
+  }
+)
 public class MavenProjectSettings implements PersistentStateComponent<MavenProjectSettings> {
 
   private final Project myProject;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
index 37a1a47..88b92ae 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
@@ -183,9 +183,10 @@
     doInit(false);
   }
 
-  private void initNew(List<VirtualFile> files, List<String> explicitProfiles) {
+  private void initNew(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
     myState.originalFiles = MavenUtil.collectPaths(files);
-    getWorkspaceSettings().setEnabledProfiles(explicitProfiles);
+    getWorkspaceSettings().setEnabledProfiles(explicitProfiles.getEnabledProfiles());
+    getWorkspaceSettings().setDisabledProfiles(explicitProfiles.getDisabledProfiles());
     doInit(true);
   }
 
@@ -241,7 +242,9 @@
   }
 
   private void applyStateToTree() {
-    myProjectsTree.resetManagedFilesPathsAndProfiles(myState.originalFiles, getWorkspaceSettings().enabledProfiles);
+    MavenWorkspaceSettings settings = getWorkspaceSettings();
+    MavenExplicitProfiles explicitProfiles = new MavenExplicitProfiles(settings.enabledProfiles, settings.disabledProfiles);
+    myProjectsTree.resetManagedFilesPathsAndProfiles(myState.originalFiles, explicitProfiles);
     myProjectsTree.setIgnoredFilesPaths(new ArrayList<String>(myState.ignoredFiles));
     myProjectsTree.setIgnoredFilesPatterns(myState.ignoredPathMasks);
   }
@@ -474,11 +477,11 @@
   }
 
   @TestOnly
-  public void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, List<String> profiles) {
+  public void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, MavenExplicitProfiles profiles) {
     myWatcher.resetManagedFilesAndProfilesInTests(files, profiles);
   }
 
-  public void addManagedFilesWithProfiles(List<VirtualFile> files, List<String> profiles) {
+  public void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
     if (!isInitialized()) {
       initNew(files, profiles);
     }
@@ -488,7 +491,7 @@
   }
 
   public void addManagedFiles(@NotNull List<VirtualFile> files) {
-    addManagedFilesWithProfiles(files, Collections.<String>emptyList());
+    addManagedFilesWithProfiles(files, MavenExplicitProfiles.NONE);
   }
 
   public void addManagedFilesOrUnignore(@NotNull List<VirtualFile> files) {
@@ -506,12 +509,12 @@
   }
 
   @NotNull
-  public Collection<String> getExplicitProfiles() {
-    if (!isInitialized()) return Collections.emptyList();
+  public MavenExplicitProfiles getExplicitProfiles() {
+    if (!isInitialized()) return MavenExplicitProfiles.NONE;
     return myProjectsTree.getExplicitProfiles();
   }
 
-  public void setExplicitProfiles(@NotNull Collection<String> profiles) {
+  public void setExplicitProfiles(@NotNull MavenExplicitProfiles profiles) {
     myWatcher.setExplicitProfiles(profiles);
   }
 
@@ -776,8 +779,10 @@
                                                  @Override
                                                  public void run(MavenEmbedderWrapper embedder) throws MavenProcessCanceledException {
                                                    try {
+                                                     MavenExplicitProfiles profiles = mavenProject.getActivatedProfilesIds();
                                                      String res =
-                                                       embedder.evaluateEffectivePom(mavenProject.getFile(), mavenProject.getActivatedProfilesIds());
+                                                       embedder.evaluateEffectivePom(mavenProject.getFile(), profiles.getEnabledProfiles(),
+                                                                                     profiles.getDisabledProfiles());
                                                      consumer.consume(res);
                                                    }
                                                    catch (UnsupportedOperationException e) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
index 81eb778..b864499 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
@@ -51,6 +51,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue;
 import org.jetbrains.idea.maven.utils.MavenUtil;
 
@@ -247,13 +248,13 @@
     Disposer.dispose(myChangedDocumentsQueue);
   }
 
-  public synchronized void addManagedFilesWithProfiles(List<VirtualFile> files, List<String> explicitProfiles) {
+  public synchronized void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
     myProjectsTree.addManagedFilesWithProfiles(files, explicitProfiles);
     scheduleUpdateAll(false, true);
   }
 
   @TestOnly
-  public synchronized void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, List<String> explicitProfiles) {
+  public synchronized void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
     myProjectsTree.resetManagedFilesAndProfiles(files, explicitProfiles);
     scheduleUpdateAll(false, true);
   }
@@ -263,7 +264,7 @@
     scheduleUpdateAll(false, true);
   }
 
-  public synchronized void setExplicitProfiles(Collection<String> profiles) {
+  public synchronized void setExplicitProfiles(MavenExplicitProfiles profiles) {
     myProjectsTree.setExplicitProfiles(profiles);
     scheduleUpdateAll(false, false);
   }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
index 89bf697..c7adefe 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
@@ -68,8 +68,9 @@
   private volatile List<String> myIgnoredFilesPatterns = new ArrayList<String>();
   private volatile Pattern myIgnoredFilesPatternsCache;
 
-  private Set<String> myExplicitProfiles = new HashSet<String>();
-  private final Set<String> myTemporarilyRemovedExplicitProfiles = new HashSet<String>();
+  private MavenExplicitProfiles myExplicitProfiles = MavenExplicitProfiles.NONE;
+  private final MavenExplicitProfiles myTemporarilyRemovedExplicitProfiles =
+    new MavenExplicitProfiles(new HashSet<String>(), new HashSet<String>());
 
   private final List<MavenProject> myRootProjects = new ArrayList<MavenProject>();
 
@@ -100,7 +101,8 @@
         result.myManagedFilesPaths = readCollection(in, new LinkedHashSet<String>());
         result.myIgnoredFilesPaths = readCollection(in, new ArrayList<String>());
         result.myIgnoredFilesPatterns = readCollection(in, new ArrayList<String>());
-        result.myExplicitProfiles = readCollection(in, new THashSet<String>());
+        result.myExplicitProfiles = new MavenExplicitProfiles(readCollection(in, new THashSet<String>()),
+                                                              readCollection(in, new THashSet<String>()));
         result.myRootProjects.addAll(readProjectsRecursively(in, result));
       }
       catch (IOException e) {
@@ -166,7 +168,8 @@
           writeCollection(out, myManagedFilesPaths);
           writeCollection(out, myIgnoredFilesPaths);
           writeCollection(out, myIgnoredFilesPatterns);
-          writeCollection(out, myExplicitProfiles);
+          writeCollection(out, myExplicitProfiles.getEnabledProfiles());
+          writeCollection(out, myExplicitProfiles.getDisabledProfiles());
           writeProjectsRecursively(out, myRootProjects);
         }
         finally {
@@ -194,7 +197,7 @@
     }
   }
 
-  public void resetManagedFilesPathsAndProfiles(List<String> paths, Collection<String> profiles) {
+  public void resetManagedFilesPathsAndProfiles(List<String> paths, MavenExplicitProfiles profiles) {
     synchronized (myStateLock) {
       myManagedFilesPaths = new LinkedHashSet<String>(paths);
     }
@@ -202,19 +205,20 @@
   }
 
   @TestOnly
-  public void resetManagedFilesAndProfiles(List<VirtualFile> files, Collection<String> profiles) {
+  public void resetManagedFilesAndProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
     resetManagedFilesPathsAndProfiles(MavenUtil.collectPaths(files), profiles);
   }
 
-  public void addManagedFilesWithProfiles(List<VirtualFile> files, Collection<String> profiles) {
+  public void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
     List<String> newFiles;
-    Set<String> newProfiles;
+    MavenExplicitProfiles newProfiles;
     synchronized (myStateLock) {
       newFiles = new ArrayList<String>(myManagedFilesPaths);
       newFiles.addAll(MavenUtil.collectPaths(files));
 
-      newProfiles = new THashSet<String>(myExplicitProfiles);
-      newProfiles.addAll(profiles);
+      newProfiles = myExplicitProfiles.clone();
+      newProfiles.getEnabledProfiles().addAll(profiles.getEnabledProfiles());
+      newProfiles.getDisabledProfiles().addAll(profiles.getDisabledProfiles());
     }
 
     resetManagedFilesPathsAndProfiles(newFiles, newProfiles);
@@ -349,15 +353,15 @@
     }
   }
 
-  public Collection<String> getExplicitProfiles() {
+  public MavenExplicitProfiles getExplicitProfiles() {
     synchronized (myStateLock) {
-      return new THashSet<String>(myExplicitProfiles);
+      return myExplicitProfiles.clone();
     }
   }
 
-  public void setExplicitProfiles(Collection<String> explicitProfiles) {
+  public void setExplicitProfiles(MavenExplicitProfiles explicitProfiles) {
     synchronized (myStateLock) {
-      myExplicitProfiles = new THashSet<String>(explicitProfiles);
+      myExplicitProfiles = explicitProfiles.clone();
     }
     fireProfilesChanged();
   }
@@ -366,19 +370,27 @@
     Collection<String> available = getAvailableProfiles();
 
     synchronized (myStateLock) {
-      Collection<String> removedProfiles = new THashSet<String>(myExplicitProfiles);
-      removedProfiles.removeAll(available);
-      myTemporarilyRemovedExplicitProfiles.addAll(removedProfiles);
-
-      Collection<String> restoredProfiles = new THashSet<String>(myTemporarilyRemovedExplicitProfiles);
-      restoredProfiles.retainAll(available);
-      myTemporarilyRemovedExplicitProfiles.removeAll(restoredProfiles);
-
-      myExplicitProfiles.removeAll(removedProfiles);
-      myExplicitProfiles.addAll(restoredProfiles);
+      updateExplicitProfiles(myExplicitProfiles.getEnabledProfiles(), myTemporarilyRemovedExplicitProfiles.getEnabledProfiles(),
+                             available);
+      updateExplicitProfiles(myExplicitProfiles.getDisabledProfiles(), myTemporarilyRemovedExplicitProfiles.getDisabledProfiles(),
+                             available);
     }
   }
 
+  private void updateExplicitProfiles(Collection<String> explicitProfiles, Collection<String> temporarilyRemovedExplicitProfiles,
+                                      Collection<String> available) {
+    Collection<String> removedProfiles = new THashSet<String>(explicitProfiles);
+    removedProfiles.removeAll(available);
+    temporarilyRemovedExplicitProfiles.addAll(removedProfiles);
+
+    Collection<String> restoredProfiles = new THashSet<String>(temporarilyRemovedExplicitProfiles);
+    restoredProfiles.retainAll(available);
+    temporarilyRemovedExplicitProfiles.removeAll(restoredProfiles);
+
+    explicitProfiles.removeAll(removedProfiles);
+    explicitProfiles.addAll(restoredProfiles);
+  }
+
   public Collection<String> getAvailableProfiles() {
     Collection<String> res = new THashSet<String>();
 
@@ -396,17 +408,26 @@
     Collection<String> active = new THashSet<String>();
     for (MavenProject each : getProjects()) {
       available.addAll(each.getProfilesIds());
-      active.addAll(each.getActivatedProfilesIds());
+      active.addAll(each.getActivatedProfilesIds().getEnabledProfiles());
     }
 
-    Collection<String> explicitProfiles = getExplicitProfiles();
+    Collection<String> enabledProfiles = getExplicitProfiles().getEnabledProfiles();
+    Collection<String> disabledProfiles = getExplicitProfiles().getDisabledProfiles();
 
     for (String each : available) {
-      MavenProfileKind state = MavenProfileKind.NONE;
-      if (explicitProfiles.contains(each)) {
+      MavenProfileKind state;
+      if (disabledProfiles.contains(each)) {
+        state = MavenProfileKind.NONE;
+      }
+      else if (enabledProfiles.contains(each)) {
         state = MavenProfileKind.EXPLICIT;
       }
-      else if (active.contains(each)) state = MavenProfileKind.IMPLICIT;
+      else if (active.contains(each)) {
+        state = MavenProfileKind.IMPLICIT;
+      }
+      else {
+        state = MavenProfileKind.NONE;
+      }
       result.add(Pair.create(each, state));
     }
     return result;
@@ -414,7 +435,7 @@
 
   public void updateAll(boolean force, MavenGeneralSettings generalSettings, MavenProgressIndicator process) {
     List<VirtualFile> managedFiles = getExistingManagedFiles();
-    Collection<String> explicitProfiles = getExplicitProfiles();
+    MavenExplicitProfiles explicitProfiles = getExplicitProfiles();
 
     MavenProjectReader projectReader = new MavenProjectReader();
     update(managedFiles, true, force, explicitProfiles, projectReader, generalSettings, process);
@@ -434,7 +455,7 @@
   private void update(Collection<VirtualFile> files,
                       boolean recursive,
                       boolean force,
-                      Collection<String> explicitProfiles,
+                      MavenExplicitProfiles explicitProfiles,
                       MavenProjectReader projectReader,
                       MavenGeneralSettings generalSettings,
                       MavenProgressIndicator process) {
@@ -469,7 +490,7 @@
 
   private void doAdd(final VirtualFile f,
                      boolean recursuve,
-                     Collection<String> explicitProfiles,
+                     MavenExplicitProfiles explicitProfiles,
                      UpdateContext updateContext,
                      Stack<MavenProject> updateStack,
                      MavenProjectReader reader,
@@ -503,7 +524,7 @@
                         boolean isNew,
                         boolean recursive,
                         boolean force,
-                        Collection<String> explicitProfiles,
+                        MavenExplicitProfiles explicitProfiles,
                         UpdateContext updateContext,
                         Stack<MavenProject> updateStack,
                         MavenProjectReader reader,
@@ -649,7 +670,7 @@
   }
 
   private MavenProjectTimestamp calculateTimestamp(final MavenProject mavenProject,
-                                                   final Collection<String> explicitProfiles,
+                                                   final MavenExplicitProfiles explicitProfiles,
                                                    final MavenGeneralSettings generalSettings) {
     AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
     try {
@@ -712,7 +733,7 @@
 
   private void delete(MavenProjectReader projectReader,
                       List<VirtualFile> files,
-                      Collection<String> explicitProfiles,
+                      MavenExplicitProfiles explicitProfiles,
                       MavenGeneralSettings generalSettings,
                       MavenProgressIndicator process) {
     if (files.isEmpty()) return;
@@ -892,7 +913,7 @@
     try {
       final CRC32 crc = new CRC32();
 
-      Set<String> profiles = myExplicitProfiles;
+      MavenExplicitProfiles profiles = myExplicitProfiles;
       if (profiles != null) {
         updateCrc(crc, profiles.hashCode());
       }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
index 3451f0c..4b0ef28 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
@@ -24,10 +24,16 @@
   public MavenImportingSettings importingSettings = new MavenImportingSettings();
 
   public List<String> enabledProfiles = new ArrayList<String>();
+  public List<String> disabledProfiles = new ArrayList<String>();
 
   public void setEnabledProfiles(Collection<String> profiles) {
     enabledProfiles.clear();
     enabledProfiles.addAll(profiles);
   }
 
+  public void setDisabledProfiles(Collection<String> profiles) {
+    disabledProfiles.clear();
+    disabledProfiles.addAll(profiles);
+  }
+
 }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
index dc1bbdb..d5e9e2d 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.components.*;
 import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 
 @State(name = "MavenImportPreferences", storages = {@Storage( file = StoragePathMacros.WORKSPACE_FILE)})
 public class MavenWorkspaceSettingsComponent implements PersistentStateComponent<MavenWorkspaceSettings> {
@@ -35,7 +36,9 @@
 
   @NotNull
   public MavenWorkspaceSettings getState() {
-    mySettings.setEnabledProfiles(MavenProjectsManager.getInstance(myProject).getExplicitProfiles());
+    MavenExplicitProfiles profiles = MavenProjectsManager.getInstance(myProject).getExplicitProfiles();
+    mySettings.setEnabledProfiles(profiles.getEnabledProfiles());
+    mySettings.setDisabledProfiles(profiles.getDisabledProfiles());
     return mySettings;
   }
 
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
index e524530..497f29b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.actionSystem.DataContext;
 import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
 import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.utils.MavenDataKeys;
 import org.jetbrains.idea.maven.utils.actions.MavenAction;
@@ -46,10 +47,12 @@
 
     if (!perform) return true;
 
+    MavenExplicitProfiles explicitProfiles = MavenActionUtil.getProjectsManager(context).getExplicitProfiles();
     final MavenRunnerParameters params = new MavenRunnerParameters(true,
                                                                    project.getDirectory(),
                                                                    goals,
-                                                                   MavenActionUtil.getProjectsManager(context).getExplicitProfiles());
+                                                                   explicitProfiles.getEnabledProfiles(),
+                                                                   explicitProfiles.getDisabledProfiles());
     MavenRunConfigurationType.runConfiguration(MavenActionUtil.getProject(context), params, null);
 
     return true;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
index 3e9bf7f..af0fbd0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
@@ -16,15 +16,15 @@
 package org.jetbrains.idea.maven.project.actions;
 
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 import org.jetbrains.idea.maven.project.ProjectBundle;
 import org.jetbrains.idea.maven.utils.MavenDataKeys;
 import org.jetbrains.idea.maven.utils.actions.MavenAction;
 import org.jetbrains.idea.maven.utils.actions.MavenActionUtil;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class ToggleProfileAction extends MavenAction {
@@ -32,47 +32,105 @@
     super.update(e);
     if (!isAvailable(e)) return;
 
-    MavenProjectsManager projectsManager = MavenActionUtil.getProjectsManager(e.getDataContext());
-    List<String> profiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
-
-    e.getPresentation().setText(isActive(projectsManager, profiles)
-                                ? ProjectBundle.message("maven.profile.deactivate")
-                                : ProjectBundle.message("maven.profile.activate"));
+    MavenProfileKind targetState = getTargetState(e);
+    String text;
+    switch (targetState) {
+      case NONE:
+        text = ProjectBundle.message("maven.profile.deactivate");
+        break;
+      case EXPLICIT:
+        text = ProjectBundle.message("maven.profile.activate");
+        break;
+      case IMPLICIT:
+      default:
+        text = ProjectBundle.message("maven.profile.default");
+        break;
+    }
+    e.getPresentation().setText(text);
   }
 
   @Override
   protected boolean isAvailable(AnActionEvent e) {
     if (!super.isAvailable(e)) return false;
 
-    List<String> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
-    if (selectedProfiles == null || selectedProfiles.isEmpty()) return false;
-
-    Collection<String> activeProfiles = MavenActionUtil.getProjectsManager(e.getDataContext()).getExplicitProfiles();
-    int activeCount = 0;
-    for (String profile : selectedProfiles) {
-      if (activeProfiles.contains(profile)) {
-        activeCount++;
-      }
-    }
-    return activeCount == 0 || activeCount == selectedProfiles.size();
+    return getTargetState(e) != null;
   }
 
-  private static boolean isActive(MavenProjectsManager projectsManager, List<String> profiles) {
-    return projectsManager.getExplicitProfiles().contains(profiles.get(0));
+  private static MavenProfileKind getTargetState(AnActionEvent e) {
+    Map<String, MavenProfileKind> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+    if (selectedProfiles == null || selectedProfiles.isEmpty()) return null;
+
+    MavenProjectsManager projectsManager = MavenActionUtil.getProjectsManager(e.getDataContext());
+    return getTargetState(projectsManager, selectedProfiles);
+  }
+
+  private static MavenProfileKind getTargetState(MavenProjectsManager projectsManager, Map<String, MavenProfileKind> profiles) {
+    MavenExplicitProfiles explicitProfiles = projectsManager.getExplicitProfiles();
+    MavenProfileKind targetState = null;
+    // all profiles should target to the same state
+    for (Map.Entry<String, MavenProfileKind> profile : profiles.entrySet()) {
+      MavenProfileKind profileTargetState = getTargetState(profile, explicitProfiles);
+      if (targetState == null) {
+        targetState = profileTargetState;
+      }
+      else if (!targetState.equals(profileTargetState)) {
+        targetState = null;
+        break;
+      }
+    }
+    return targetState;
+  }
+
+  private static MavenProfileKind getTargetState(Map.Entry<String, MavenProfileKind> profile, MavenExplicitProfiles explicitProfiles) {
+    MavenProfileKind targetState;
+    if (explicitProfiles.getDisabledProfiles().contains(profile.getKey())) {
+      // explicitly disabled -> explicitly enabled
+      targetState = MavenProfileKind.EXPLICIT;
+    }
+    else if (explicitProfiles.getEnabledProfiles().contains(profile.getKey())) {
+      // explicitly enabled -> default
+      targetState = MavenProfileKind.IMPLICIT;
+    }
+    else {
+      // default
+      if (MavenProfileKind.NONE.equals(profile.getValue())) {
+        // default inactive -> explicitly enabled
+        targetState = MavenProfileKind.EXPLICIT;
+      }
+      else {
+        // default active -> explicitly disabled
+        targetState = MavenProfileKind.NONE;
+      }
+    }
+    return targetState;
   }
 
   @Override
   public void actionPerformed(AnActionEvent e) {
     MavenProjectsManager manager = MavenActionUtil.getProjectsManager(e.getDataContext());
-    List<String> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+    Map<String, MavenProfileKind> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+    Set<String> selectedProfileIds = selectedProfiles.keySet();
 
-    Set<String> activeProfiles = new HashSet<String>(manager.getExplicitProfiles());
-    if (isActive(manager, selectedProfiles)) {
-      activeProfiles.removeAll(selectedProfiles);
+    MavenProfileKind targetState = getTargetState(manager, selectedProfiles);
+    MavenExplicitProfiles newExplicitProfiles = manager.getExplicitProfiles().clone();
+    switch (targetState) {
+      case NONE:
+        // disable explicitly
+        newExplicitProfiles.getEnabledProfiles().removeAll(selectedProfileIds);
+        newExplicitProfiles.getDisabledProfiles().addAll(selectedProfileIds);
+        break;
+      case EXPLICIT:
+        // enable explicitly
+        newExplicitProfiles.getDisabledProfiles().removeAll(selectedProfileIds);
+        newExplicitProfiles.getEnabledProfiles().addAll(selectedProfileIds);
+        break;
+      case IMPLICIT:
+      default:
+        // reset to default state
+        newExplicitProfiles.getEnabledProfiles().removeAll(selectedProfileIds);
+        newExplicitProfiles.getDisabledProfiles().removeAll(selectedProfileIds);
+        break;
     }
-    else {
-      activeProfiles.addAll(selectedProfiles);
-    }
-    manager.setExplicitProfiles(activeProfiles);
+    manager.setExplicitProfiles(newExplicitProfiles);
   }
 }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
index a0882e7..006f4ca 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
@@ -93,22 +93,26 @@
 
   @NotNull
   public MavenServerExecutionResult resolveProject(@NotNull final VirtualFile file,
-                                                    @NotNull final Collection<String> activeProfiles) throws MavenProcessCanceledException {
+                                                   @NotNull final Collection<String> activeProfiles,
+                                                   @NotNull final Collection<String> inactiveProfiles)
+    throws MavenProcessCanceledException {
     return perform(new RetriableCancelable<MavenServerExecutionResult>() {
       @Override
       public MavenServerExecutionResult execute() throws RemoteException, MavenServerProcessCanceledException {
-        return getOrCreateWrappee().resolveProject(new File(file.getPath()), activeProfiles);
+        return getOrCreateWrappee().resolveProject(new File(file.getPath()), activeProfiles, inactiveProfiles);
       }
     });
   }
 
   @Nullable
-  public String evaluateEffectivePom(@NotNull final VirtualFile file, @NotNull final Collection<String> activeProfiles)
-    throws MavenProcessCanceledException {
+  public String evaluateEffectivePom(@NotNull final VirtualFile file,
+                                     @NotNull final Collection<String> activeProfiles,
+                                     @NotNull final Collection<String> inactiveProfiles) throws MavenProcessCanceledException {
     return perform(new RetriableCancelable<String>() {
       @Override
       public String execute() throws RemoteException, MavenServerProcessCanceledException {
-        return getOrCreateWrappee().evaluateEffectivePom(new File(file.getPath()), new ArrayList<String>(activeProfiles));
+        return getOrCreateWrappee()
+          .evaluateEffectivePom(new File(file.getPath()), new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles));
       }
     });
   }
@@ -165,14 +169,14 @@
 
   @NotNull
   public MavenServerExecutionResult execute(@NotNull final VirtualFile file,
-                                             @NotNull final Collection<String> activeProfiles,
-                                             @NotNull final List<String> goals) throws MavenProcessCanceledException {
+                                            @NotNull final Collection<String> activeProfiles,
+                                            @NotNull final Collection<String> inactiveProfiles,
+                                            @NotNull final List<String> goals) throws MavenProcessCanceledException {
     return perform(new RetriableCancelable<MavenServerExecutionResult>() {
       @Override
       public MavenServerExecutionResult execute() throws RemoteException, MavenServerProcessCanceledException {
         return getOrCreateWrappee()
-          .execute(new File(file.getPath()), activeProfiles, Collections.<String>emptyList(), goals, Collections.<String>emptyList(), false,
-                   false);
+          .execute(new File(file.getPath()), activeProfiles, inactiveProfiles, goals, Collections.<String>emptyList(), false, false);
       }
     });
   }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
index 5777e24..7ef16bd 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
@@ -45,6 +45,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenId;
 import org.jetbrains.idea.maven.model.MavenModel;
 import org.jetbrains.idea.maven.project.MavenConsole;
@@ -409,7 +410,7 @@
 
   public ProfileApplicationResult applyProfiles(final MavenModel model,
                                                 final File basedir,
-                                                final Collection<String> explicitProfiles,
+                                                final MavenExplicitProfiles explicitProfiles,
                                                 final Collection<String> alwaysOnProfiles) {
     return perform(new Retriable<ProfileApplicationResult>() {
       @Override
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
index b98fff5..d128dac 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
@@ -39,6 +39,7 @@
 import org.jetbrains.idea.maven.execution.MavenEditGoalDialog;
 import org.jetbrains.idea.maven.execution.MavenRunner;
 import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 import org.jetbrains.idea.maven.utils.MavenLog;
@@ -162,7 +163,7 @@
 
             FileDocumentManager.getInstance().saveAllDocuments();
 
-            final Collection<String> explicitProfiles = MavenProjectsManager.getInstance(project).getExplicitProfiles();
+            final MavenExplicitProfiles explicitProfiles = MavenProjectsManager.getInstance(project).getExplicitProfiles();
             final MavenRunner mavenRunner = MavenRunner.getInstance(project);
 
             targetDone.down();
@@ -173,7 +174,8 @@
                     true,
                     mavenProject.getDirectory(),
                     ParametersListUtil.parse(task.getGoal()),
-                    explicitProfiles);
+                    explicitProfiles.getEnabledProfiles(),
+                    explicitProfiles.getDisabledProfiles());
 
                   result[0] = mavenRunner.runBatch(Collections.singletonList(params),
                                                 null,
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
index 7bde42d..25db4aa 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
@@ -27,6 +27,7 @@
 import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
 import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
 import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenPlugin;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
@@ -176,10 +177,12 @@
 
     public void actionPerformed(AnActionEvent e) {
       final DataContext context = e.getDataContext();
+      MavenExplicitProfiles explicitProfiles = MavenActionUtil.getProjectsManager(context).getExplicitProfiles();
       MavenRunnerParameters params = new MavenRunnerParameters(true,
                                                                myMavenProject.getDirectory(),
                                                                Arrays.asList(myGoal),
-                                                               MavenActionUtil.getProjectsManager(context).getExplicitProfiles());
+                                                               explicitProfiles.getEnabledProfiles(),
+                                                               explicitProfiles.getDisabledProfiles());
       MavenRunConfigurationType.runConfiguration(MavenActionUtil.getProject(context), params, null);
     }
 
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
index 3dabc5a..c085e18 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
@@ -33,6 +33,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.maven.execution.MavenRunner;
 import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 import org.jetbrains.idea.maven.utils.MavenSimpleProjectComponent;
@@ -133,10 +134,12 @@
       for (MavenCompilerTask each : tasks) {
         VirtualFile file = LocalFileSystem.getInstance().findFileByPath(each.getProjectPath());
         if (file == null) continue;
+        MavenExplicitProfiles explicitProfiles = myProjectsManager.getExplicitProfiles();
         parametersList.add(new MavenRunnerParameters(true,
                                                      file.getParent().getPath(),
                                                      Arrays.asList(each.getGoal()),
-                                                     myProjectsManager.getExplicitProfiles()));
+                                                     explicitProfiles.getEnabledProfiles(),
+                                                     explicitProfiles.getDisabledProfiles()));
       }
     }
     return myRunner.runBatch(parametersList, null, null, TasksBundle.message("maven.tasks.executing"), context.getProgressIndicator());
@@ -194,4 +197,4 @@
   public interface Listener {
     void compileTasksChanged();
   }
-}
\ No newline at end of file
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
index 397447c..aff34a1 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
@@ -18,16 +18,18 @@
 import com.intellij.execution.RunnerAndConfigurationSettings;
 import com.intellij.openapi.actionSystem.DataKey;
 import org.jetbrains.idea.maven.model.MavenArtifact;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
 
 import javax.swing.*;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 
 public class MavenDataKeys {
   public static final DataKey<List<String>> MAVEN_GOALS = DataKey.create("MAVEN_GOALS");
   public static final DataKey<RunnerAndConfigurationSettings> RUN_CONFIGURATION = DataKey.create("MAVEN_RUN_CONFIGURATION");
-  public static final DataKey<List<String>> MAVEN_PROFILES = DataKey.create("MAVEN_PROFILES");
+  public static final DataKey<Map<String, MavenProfileKind>> MAVEN_PROFILES = DataKey.create("MAVEN_PROFILES");
   public static final DataKey<Collection<MavenArtifact>> MAVEN_DEPENDENCIES = DataKey.create("MAVEN_DEPENDENCIES");
   public static final DataKey<JTree> MAVEN_PROJECTS_TREE = DataKey.create("MAVEN_PROJECTS_TREE");
 
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
index 30755ff..1f0190a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
@@ -194,7 +194,9 @@
     }
 
     MavenRunnerParameters params = new MavenRunnerParameters(
-      false, workingDir.getPath(), Collections.singletonList("org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate"), null);
+      false, workingDir.getPath(),
+      Collections.singletonList("org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate"),
+      Collections.<String>emptyList());
 
     MavenRunner runner = MavenRunner.getInstance(project);
     MavenRunnerSettings settings = runner.getState().clone();
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
index 53a486f..7302848 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
@@ -36,6 +36,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider;
 import org.jetbrains.idea.maven.importing.MavenUIModifiableModelsProvider;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.model.MavenId;
 import org.jetbrains.idea.maven.project.*;
 import org.jetbrains.idea.maven.utils.*;
@@ -53,7 +54,8 @@
     private VirtualFile myImportRoot;
     private List<VirtualFile> myFiles;
     private List<String> myProfiles = new ArrayList<String>();
-    private List<String> mySelectedProfiles = new ArrayList<String>();
+    private List<String> myActivatedProfiles = new ArrayList<String>();
+    private MavenExplicitProfiles mySelectedProfiles = MavenExplicitProfiles.NONE;
 
     private MavenProjectsTree myMavenProjectTree;
     private List<MavenProject> mySelectedProjects;
@@ -109,20 +111,14 @@
       settings.generalSettings.setUserSettingsFile(settingsFile.trim());
     }
 
-    List<String> selectedProfiles = getSelectedProfiles();
+    MavenExplicitProfiles selectedProfiles = getSelectedProfiles();
 
-    String profilesList = System.getProperty("idea.maven.import.enabled.profiles");
-    if (profilesList != null) {
-      Set<String> selectedProfilesSet = new LinkedHashSet<String>(selectedProfiles);
-
-      for (String profile : StringUtil.split(profilesList, ",")) {
-        String trimmedProfileName = profile.trim();
-        if (!trimmedProfileName.isEmpty()) {
-          selectedProfilesSet.add(trimmedProfileName);
-        }
-      }
-
-      selectedProfiles = new ArrayList<String>(selectedProfilesSet);
+    String enabledProfilesList = System.getProperty("idea.maven.import.enabled.profiles");
+    String disabledProfilesList = System.getProperty("idea.maven.import.disabled.profiles");
+    if (enabledProfilesList != null || disabledProfilesList != null) {
+      selectedProfiles = selectedProfiles.clone();
+      appendProfilesFromString(selectedProfiles.getEnabledProfiles(), enabledProfilesList);
+      appendProfilesFromString(selectedProfiles.getDisabledProfiles(), disabledProfilesList);
     }
 
     MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
@@ -138,9 +134,21 @@
                                   : new MavenDefaultModifiableModelsProvider(project));
   }
 
+  private void appendProfilesFromString(Collection<String> selectedProfiles, String profilesList) {
+    if (profilesList == null) return;
+
+    for (String profile : StringUtil.split(profilesList, ",")) {
+      String trimmedProfileName = profile.trim();
+      if (!trimmedProfileName.isEmpty()) {
+        selectedProfiles.add(trimmedProfileName);
+      }
+    }
+  }
+
   public boolean setRootDirectory(@Nullable Project projectToUpdate, final String root) throws ConfigurationException {
     getParameters().myFiles = null;
     getParameters().myProfiles.clear();
+    getParameters().myActivatedProfiles.clear();
     getParameters().myMavenProjectTree = null;
 
     getParameters().myProjectToUpdate = projectToUpdate; // We cannot determinate project in non-EDT thread.
@@ -174,7 +182,8 @@
   private void collectProfiles(MavenProgressIndicator process) {
     process.setText(ProjectBundle.message("maven.searching.profiles"));
 
-    Set<String> uniqueProfiles = new LinkedHashSet<String>();
+    Set<String> availableProfiles = new LinkedHashSet<String>();
+    Set<String> activatedProfiles = new LinkedHashSet<String>();
     MavenProjectReader reader = new MavenProjectReader();
     MavenGeneralSettings generalSettings = getGeneralSettings();
     MavenProjectReaderProjectLocator locator = new MavenProjectReaderProjectLocator() {
@@ -185,21 +194,27 @@
     for (VirtualFile f : getParameters().myFiles) {
       MavenProject project = new MavenProject(f);
       process.setText2(ProjectBundle.message("maven.reading.pom", f.getPath()));
-      project.read(generalSettings, Collections.<String>emptyList(), reader, locator);
-      uniqueProfiles.addAll(project.getProfilesIds());
+      project.read(generalSettings, MavenExplicitProfiles.NONE, reader, locator);
+      availableProfiles.addAll(project.getProfilesIds());
+      activatedProfiles.addAll(project.getActivatedProfilesIds().getEnabledProfiles());
     }
-    getParameters().myProfiles = new ArrayList<String>(uniqueProfiles);
+    getParameters().myProfiles = new ArrayList<String>(availableProfiles);
+    getParameters().myActivatedProfiles = new ArrayList<String>(activatedProfiles);
   }
 
   public List<String> getProfiles() {
     return getParameters().myProfiles;
   }
 
-  public List<String> getSelectedProfiles() {
+  public List<String> getActivatedProfiles() {
+    return getParameters().myActivatedProfiles;
+  }
+
+  public MavenExplicitProfiles getSelectedProfiles() {
     return getParameters().mySelectedProfiles;
   }
 
-  public boolean setSelectedProfiles(List<String> profiles) {
+  public boolean setSelectedProfiles(MavenExplicitProfiles profiles) {
     getParameters().myMavenProjectTree = null;
     getParameters().mySelectedProfiles = profiles;
 
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
index 0ba88d7..db9b556 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
@@ -26,9 +26,9 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProject;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -45,7 +45,7 @@
   public boolean doQuickImport(VirtualFile file, WizardContext wizardContext) {
     getBuilder().setFiles(Arrays.asList(file));
 
-    if (!getBuilder().setSelectedProfiles(new ArrayList<String>())) return false;
+    if (!getBuilder().setSelectedProfiles(MavenExplicitProfiles.NONE)) return false;
 
     List<MavenProject> projects = getBuilder().getList();
     if (projects.size() != 1) return false;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
index 4f0238c..3fc7fb4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
@@ -15,14 +15,21 @@
  */
 package org.jetbrains.idea.maven.wizards;
 
-import com.intellij.ide.util.ElementsChooser;
+import com.intellij.ide.util.MultiStateElementsChooser;
 import com.intellij.ide.util.projectWizard.WizardContext;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.projectImport.ProjectImportWizardStep;
+import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
 
 import javax.swing.*;
-import java.util.ArrayList;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+import java.util.*;
 import java.util.List;
 
 /**
@@ -30,7 +37,8 @@
  */
 public class SelectProfilesStep extends ProjectImportWizardStep {
   private JPanel panel;
-  private ElementsChooser<String> profileChooser;
+  private MultiStateElementsChooser<String, MavenProfileKind> profileChooser;
+  private MavenProfileKindMarkStateDescriptor myMarkStateDescriptor;
 
   public SelectProfilesStep(final WizardContext context) {
     super(context);
@@ -52,7 +60,8 @@
   }
 
   public void createUIComponents() {
-    profileChooser = new ElementsChooser<String>(true);
+    myMarkStateDescriptor = new MavenProfileKindMarkStateDescriptor();
+    profileChooser = new MultiStateElementsChooser<String, MavenProfileKind>(true, myMarkStateDescriptor);
   }
 
   public JComponent getComponent() {
@@ -61,15 +70,39 @@
 
   public void updateStep() {
     List<String> allProfiles = getBuilder().getProfiles();
-    List<String> markedProfiles = new ArrayList<String>(getBuilder().getSelectedProfiles());
-    markedProfiles.retainAll(allProfiles); // mark only existing profiles
+    List<String> activatedProfiles = getBuilder().getActivatedProfiles();
+    MavenExplicitProfiles selectedProfiles = getBuilder().getSelectedProfiles();
+    List<String> enabledProfiles = new ArrayList<String>(selectedProfiles.getEnabledProfiles());
+    List<String> disabledProfiles = new ArrayList<String>(selectedProfiles.getDisabledProfiles());
+    enabledProfiles.retainAll(allProfiles); // mark only existing profiles
+    disabledProfiles.retainAll(allProfiles); // mark only existing profiles
 
-    profileChooser.setElements(allProfiles, false);
-    profileChooser.markElements(markedProfiles);
+    myMarkStateDescriptor.setActivatedProfiles(activatedProfiles);
+    profileChooser.setElements(allProfiles, null);
+    profileChooser.markElements(enabledProfiles, MavenProfileKind.EXPLICIT);
+    profileChooser.markElements(disabledProfiles, MavenProfileKind.NONE);
   }
 
   public boolean validate() throws ConfigurationException {
-    return getBuilder().setSelectedProfiles(profileChooser.getMarkedElements());
+    Collection<String> activatedProfiles = myMarkStateDescriptor.getActivatedProfiles();
+    MavenExplicitProfiles newSelectedProfiles = MavenExplicitProfiles.NONE.clone();
+    for (Map.Entry<String, MavenProfileKind> entry : profileChooser.getElementMarkStates().entrySet()) {
+      String profile = entry.getKey();
+      MavenProfileKind profileKind = entry.getValue();
+      switch (profileKind) {
+        case NONE:
+          if (activatedProfiles.contains(profile)) {
+            newSelectedProfiles.getDisabledProfiles().add(profile);
+          }
+          break;
+        case EXPLICIT:
+          newSelectedProfiles.getEnabledProfiles().add(profile);
+          break;
+        case IMPLICIT:
+          break;
+      }
+    }
+    return getBuilder().setSelectedProfiles(newSelectedProfiles);
   }
 
   public void updateDataModel() {
@@ -79,4 +112,100 @@
   public String getHelpId() {
     return "reference.dialogs.new.project.import.maven.page2";
   }
+
+  private static class MavenProfileKindMarkStateDescriptor
+    implements MultiStateElementsChooser.MarkStateDescriptor<String, MavenProfileKind> {
+    private Collection<String> myActivatedProfiles = Collections.emptySet();
+
+    public Collection<String> getActivatedProfiles() {
+      return myActivatedProfiles;
+    }
+
+    public void setActivatedProfiles(Collection<String> activatedProfiles) {
+      myActivatedProfiles = new THashSet<String>(activatedProfiles);
+    }
+
+    @NotNull
+    @Override
+    public MavenProfileKind getDefaultState(@NotNull String element) {
+      return myActivatedProfiles.contains(element) ? MavenProfileKind.IMPLICIT : MavenProfileKind.NONE;
+    }
+
+    @NotNull
+    @Override
+    public MavenProfileKind getNextState(@NotNull String element, @NotNull MavenProfileKind state) {
+      MavenProfileKind nextState;
+      switch (state) {
+        case NONE:
+          nextState = MavenProfileKind.EXPLICIT;
+          break;
+        case EXPLICIT:
+          nextState = getDefaultState(element);
+          break;
+        case IMPLICIT:
+        default:
+          nextState = MavenProfileKind.NONE;
+          break;
+      }
+      return nextState;
+    }
+
+    @Nullable
+    @Override
+    public MavenProfileKind getNextState(@NotNull Map<String, MavenProfileKind> elementsWithStates) {
+      MavenProfileKind nextState = null;
+      for (Map.Entry<String, MavenProfileKind> entry : elementsWithStates.entrySet()) {
+        MavenProfileKind nextElementState = getNextState(entry.getKey(), entry.getValue());
+        if (nextState == null) {
+          nextState = nextElementState;
+        }
+        else if (!nextState.equals(nextElementState)) {
+          nextState = null;
+          break;
+        }
+      }
+      return nextState;
+    }
+
+    @Override
+    public boolean isMarked(@NotNull MavenProfileKind state) {
+      return state != MavenProfileKind.NONE;
+    }
+
+    @Nullable
+    @Override
+    public MavenProfileKind getMarkState(@Nullable Object value) {
+      return value instanceof MavenProfileKind ? (MavenProfileKind)value : null;
+    }
+
+    @Nullable
+    @Override
+    public TableCellRenderer getMarkRenderer() {
+      return new CheckboxTableCellRenderer();
+    }
+  }
+
+  private static class CheckboxTableCellRenderer extends JCheckBox implements TableCellRenderer {
+    public CheckboxTableCellRenderer() {
+      setHorizontalAlignment(SwingConstants.CENTER);
+      setBorder(null);
+    }
+
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+      if (isSelected) {
+        setForeground(table.getSelectionForeground());
+        super.setBackground(table.getSelectionBackground());
+      }
+      else {
+        setForeground(table.getForeground());
+        setBackground(table.getBackground());
+      }
+
+      MavenProfileKind state = (MavenProfileKind)value;
+      setSelected(state != MavenProfileKind.NONE);
+      setEnabled(state != MavenProfileKind.IMPLICIT);
+
+      return this;
+    }
+  }
 }
diff --git a/plugins/maven/src/main/resources/ProjectBundle.properties b/plugins/maven/src/main/resources/ProjectBundle.properties
index 926720c..6ceac4f 100644
--- a/plugins/maven/src/main/resources/ProjectBundle.properties
+++ b/plugins/maven/src/main/resources/ProjectBundle.properties
@@ -66,6 +66,7 @@
 maven.ignore.edit=Edit Ignored Files...
 maven.profile.activate=Activate
 maven.profile.deactivate=Deactivate
+maven.profile.default=Use default
 
 maven.project.problem.recursiveInheritance=Recursive inheritance found
 maven.project.problem.selfInheritance=Self-inheritance found
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
index 6cc0966..79639e9 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
@@ -42,6 +42,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.maven.execution.*;
 import org.jetbrains.idea.maven.model.MavenArtifact;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenArtifactDownloader;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
@@ -402,7 +403,7 @@
   }
 
   protected void readProjects(List<VirtualFile> files, String... profiles) {
-    myProjectsManager.resetManagedFilesAndProfilesInTests(files, Arrays.asList(profiles));
+    myProjectsManager.resetManagedFilesAndProfilesInTests(files, new MavenExplicitProfiles(Arrays.asList(profiles)));
     waitForReadingCompletion();
   }
 
@@ -502,7 +503,7 @@
   protected void executeGoal(String relativePath, String goal) {
     VirtualFile dir = myProjectRoot.findFileByRelativePath(relativePath);
 
-    MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), null);
+    MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), Collections.<String>emptyList());
     MavenRunnerSettings rs = new MavenRunnerSettings();
     MavenExecutor e = new MavenExternalExecutor(myProject, rp, getMavenGeneralSettings(), rs, new SoutMavenConsole());
 
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
index 24b6e5f..38fc7e2 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 
 import java.util.Arrays;
 
@@ -658,7 +659,7 @@
     compileModules("project");
     assertResult("target/classes/file.properties", "value=val1");
 
-    myProjectsManager.setExplicitProfiles(Arrays.asList("two"));
+    myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList("two")));
     scheduleResolveAll();
     resolveDependenciesAndImport();
     compileModules("project");
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
index dc3fb09..f9c648c 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
@@ -27,6 +27,7 @@
 import org.jetbrains.idea.maven.dom.model.MavenDomProfiles;
 import org.jetbrains.idea.maven.dom.model.MavenDomProfilesModel;
 import org.jetbrains.idea.maven.dom.model.MavenDomSettingsModel;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem;
 
 import java.util.Arrays;
@@ -933,7 +934,7 @@
     assertContain(variants, "project.groupId");
     assertDoNotContain(variants, "groupId");
   }
-  
+
   public void testCompletingAfterOpenBraceAndSomeTextWithDot() throws Exception {
     createProjectPom("<groupId>test</groupId>" +
                      "<artifactId>project</artifactId>" +
@@ -955,7 +956,7 @@
   }
 
   private void readWithProfiles(String... profiles) {
-    myProjectsManager.setExplicitProfiles(Arrays.asList(profiles));
+    myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList(profiles)));
     waitForReadingCompletion();
   }
 }
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
index 4a0f5e2..f8c019c 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
@@ -30,6 +30,7 @@
 import javax.swing.*;
 import java.io.File;
 import java.util.Arrays;
+import java.util.Collections;
 
 @SuppressWarnings({"ConstantConditions"})
 public class MavenExecutionTest extends MavenImportingTestCase {
@@ -59,7 +60,7 @@
 
     assertFalse(new File(getProjectPath(), "target").exists());
 
-    execute(new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), null));
+    execute(new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), Collections.<String>emptyList()));
 
     assertTrue(new File(getProjectPath(), "target").exists());
   }
@@ -84,7 +85,7 @@
     assertModules("project");
     assertExcludes("project", "target");
 
-    MavenRunnerParameters params = new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), null);
+    MavenRunnerParameters params = new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), Collections.<String>emptyList());
     execute(params);
 
     SwingUtilities.invokeAndWait(new Runnable() {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
index e98fe82..008fc9c 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.project.MavenProject;
 
 import java.util.Calendar;
@@ -34,7 +35,7 @@
     super.setUp();
     VirtualFile file = LocalFileSystem.getInstance().findFileByPath("C:\\projects\\mvn\\_projects\\geronimo\\pom.xml");
     initProjectsManager(false);
-    myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(file), Collections.<String>emptyList());
+    myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(file), MavenExplicitProfiles.NONE);
   }
 
   public void testReading() throws Exception {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
index 86a80e0..a04fe5b 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -50,7 +51,7 @@
     createModulePom("m", "<groupId>test</groupId>" +
                          "<artifactId>m</artifactId>" +
                          "<version>1</version>");
-    myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(myProjectPom), Collections.<String>emptyList());
+    myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(myProjectPom), MavenExplicitProfiles.NONE);
     waitForReadingCompletion();
 
     myProjectsManager.fireActivatedInTests();
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
index e6e946e..cea4ea2 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
@@ -18,6 +18,8 @@
 import com.intellij.ProjectTopics;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.Consumer;
 import org.jetbrains.idea.maven.MavenImportingTestCase;
@@ -49,6 +51,23 @@
     assertNull(myProjectRoot.findChild("target"));
   }
 
+  public void testIgnoreTargetFolder() throws Exception {
+    importProject("<groupId>test</groupId>" +
+                  "<artifactId>project</artifactId>" +
+                  "<version>1</version>");
+
+    new File(myProjectRoot.getPath(), "target/classes").mkdirs();
+    updateProjectFolders();
+
+    assertExcludes("project", "target");
+    myProjectRoot.refresh(false, true);
+    VirtualFile target = myProjectRoot.findChild("target");
+    assertNotNull(target);
+    if (!Registry.is("ide.hide.excluded.files")) {
+      assertTrue(ChangeListManager.getInstance(myProject).isIgnoredFile(target));
+    }
+  }
+
   public void testUpdatingFoldersForAllTheProjects() throws Exception {
     createProjectPom("<groupId>test</groupId>" +
                      "<artifactId>project</artifactId>" +
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
index 770196b..8fc251a 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
@@ -1586,7 +1586,7 @@
                                                String... profiles) {
     MavenProjectReaderResult result = new MavenProjectReader().readProject(getMavenGeneralSettings(),
                                                                            file,
-                                                                           Arrays.asList(profiles),
+                                                                           new MavenExplicitProfiles(Arrays.asList(profiles)),
                                                                            locator);
     return result;
   }
@@ -1629,7 +1629,7 @@
   private void assertActiveProfiles(List<String> explicitProfiles, String... expected) {
     MavenProjectReaderResult result =
       readProject(myProjectPom, new NullProjectLocator(), ArrayUtil.toStringArray(explicitProfiles));
-    assertUnorderedElementsAreEqual(result.activatedProfiles, expected);
+    assertUnorderedElementsAreEqual(result.activatedProfiles.getEnabledProfiles(), expected);
   }
 
   private static class NullProjectLocator implements MavenProjectReaderProjectLocator {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
index 6c9bc1c..dc7f549 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
@@ -29,6 +29,7 @@
 import com.intellij.util.FileContentUtil;
 import org.jetbrains.idea.maven.MavenImportingTestCase;
 import org.jetbrains.idea.maven.importing.MavenRootModelAdapter;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
 
 import java.io.File;
@@ -686,7 +687,7 @@
                                      "<version>1</version>");
 
     importProjects(p1, p2);
-    myProjectsManager.setExplicitProfiles(Arrays.asList("one", "two"));
+    myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList("one", "two")));
     myProjectsManager.setIgnoredFilesPaths(Arrays.asList(p1.getPath()));
     myProjectsManager.setIgnoredFilesPatterns(Arrays.asList("*.xxx"));
 
@@ -707,7 +708,7 @@
 
     assertUnorderedPathsAreEqual(myProjectsManager.getProjectsTreeForTests().getManagedFilesPaths(),
                                  Arrays.asList(p1.getPath(), p3.getPath()));
-    assertUnorderedElementsAreEqual(myProjectsManager.getExplicitProfiles(), "three");
+    assertUnorderedElementsAreEqual(myProjectsManager.getExplicitProfiles().getEnabledProfiles(), "three");
     assertUnorderedPathsAreEqual(myProjectsManager.getIgnoredFilesPaths(), Arrays.asList(p1.getPath()));
     assertUnorderedElementsAreEqual(myProjectsManager.getIgnoredFilesPatterns(), "*.zzz");
 
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
index 842b609..c3a322c 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.util.Function;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
 import org.jetbrains.idea.maven.utils.MavenUtil;
 
@@ -1539,7 +1540,7 @@
     MyLoggingListener l = new MyLoggingListener();
     myTree.addListener(l);
 
-    myTree.addManagedFilesWithProfiles(Collections.singletonList(myProjectPom), Collections.<String>emptyList());
+    myTree.addManagedFilesWithProfiles(Collections.singletonList(myProjectPom), MavenExplicitProfiles.NONE);
     myTree.updateAll(false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS);
 
     assertEquals("updated: parent m1 m2 deleted: <none> ", l.log);
@@ -2022,7 +2023,7 @@
               myProjectPom);
 
     MavenProject project = myTree.findProject(myProjectPom);
-    assertUnorderedElementsAreEqual(project.getActivatedProfilesIds(),
+    assertUnorderedElementsAreEqual(project.getActivatedProfilesIds().getEnabledProfiles(),
                                     "projectProfileXml",
                                     "projectProfile",
                                     "parent1Profile",
@@ -2044,7 +2045,7 @@
       embeddersManager.releaseInTests();
     }
 
-    assertUnorderedElementsAreEqual(project.getActivatedProfilesIds(),
+    assertUnorderedElementsAreEqual(project.getActivatedProfilesIds().getEnabledProfiles(),
                                     "projectProfileXml",
                                     "projectProfile",
                                     "parent1Profile",
@@ -2069,24 +2070,24 @@
                       "</profile>");
 
     updateAll(Arrays.asList("one", "two"), myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
 
     deleteProfilesXml();
     update(myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one");
 
     createProjectPom("<groupId>test</groupId>" +
                      "<artifactId>project</artifactId>" +
                      "<version>1</version>");
 
     update(myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles());
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles());
 
     createProfilesXml("<profile>" +
                       "  <id>two</id>" +
                       "</profile>");
     update(myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "two");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "two");
 
     createProjectPom("<groupId>test</groupId>" +
                      "<artifactId>project</artifactId>" +
@@ -2097,7 +2098,7 @@
                      "  </profile>" +
                      "</profiles>");
     update(myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
   }
 
   public void testDeletingAndRestoringActiveProfilesWhenProjectDeletes() throws Exception {
@@ -2128,7 +2129,7 @@
                                     "</profiles>");
 
     updateAll(Arrays.asList("one", "two"), myProjectPom);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
 
     final VirtualFile finalM = m;
     new WriteCommandAction.Simple(myProject) {
@@ -2139,7 +2140,7 @@
       }
     }.execute().throwException();
 
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one");
 
     m = createModulePom("m",
                         "<groupId>test</groupId>" +
@@ -2152,7 +2153,7 @@
                         "  </profile>" +
                         "</profiles>");
     update(m);
-    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+    assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
   }
 
   public void testFindRootWithMultiLevelAggregator() throws Exception {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
index 3688a2d..8d73c5f 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
 import org.jetbrains.idea.maven.utils.MavenProcessCanceledException;
 
 import java.io.IOException;
@@ -33,7 +34,7 @@
   }
 
   protected void updateAll(List<String> profiles, VirtualFile... files) throws MavenProcessCanceledException {
-    myTree.resetManagedFilesAndProfiles(asList(files), profiles);
+    myTree.resetManagedFilesAndProfiles(asList(files), new MavenExplicitProfiles(profiles));
     myTree.updateAll(false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS);
   }
 
@@ -50,4 +51,4 @@
       each.setBinaryContent(each.contentsToByteArray());
     }
   }
-}
\ No newline at end of file
+}
diff --git a/plugins/properties/resources/icons/xmlProperties.png b/plugins/properties/properties-psi-api/resources/icons/xmlProperties.png
similarity index 100%
rename from plugins/properties/resources/icons/xmlProperties.png
rename to plugins/properties/properties-psi-api/resources/icons/xmlProperties.png
Binary files differ
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
index b29fc4f..8f5084b 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
@@ -115,21 +115,18 @@
 
   @Nullable
   public static ResourceBundle createByUrl(final @NotNull String url, final @NotNull Project project) {
-    if (!url.startsWith(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX)) return null;
-
-    final String defaultPropertiesUrl = url.substring(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX.length());
-    final int idx = defaultPropertiesUrl.lastIndexOf('/');
+    final int idx = url.lastIndexOf('/');
     if (idx == -1) return null;
-    final String baseDirectoryName = defaultPropertiesUrl.substring(0, idx);
-    final String baseName = defaultPropertiesUrl.substring(idx + 1);
+    final String baseDirectoryName = url.substring(0, idx);
+    final String baseName = url.substring(idx + 1);
     final VirtualFile baseDirectoryVirtualFile = VirtualFileManager.getInstance().findFileByUrl(baseDirectoryName);
     if (baseDirectoryVirtualFile == null) {
       return null;
     }
-    final PsiFile baseDirectory = PsiManager.getInstance(project).findFile(baseDirectoryVirtualFile);
-    if (baseDirectory == null || !(baseDirectory instanceof PsiDirectory)) {
+    final PsiDirectory baseDirectory = PsiManager.getInstance(project).findDirectory(baseDirectoryVirtualFile);
+    if (baseDirectory == null) {
       return null;
     }
-    return getResourceBundle(baseName, (PsiDirectory)baseDirectory);
+    return getResourceBundle(baseName, baseDirectory);
   }
 }
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
index d257824..ca5c8aa 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
@@ -23,16 +23,13 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDirectory;
 import com.intellij.psi.PsiFile;
 import com.intellij.util.SmartList;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 
 public class ResourceBundleImpl extends ResourceBundle {
-  @NonNls public static final String RESOURCE_BUNDLE_PREFIX = "resourceBundle:";
   @NotNull private final PropertiesFile myDefaultPropertiesFile;
 
   public ResourceBundleImpl(@NotNull final PropertiesFile defaultPropertiesFile) {
@@ -106,6 +103,6 @@
   }
 
   public String getUrl() {
-    return RESOURCE_BUNDLE_PREFIX + getBaseDirectory() + "/" + getBaseName();
+    return getBaseDirectory() + "/" + getBaseName();
   }
 }
\ No newline at end of file
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
index cb60de0..398b9ae 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
@@ -23,11 +23,13 @@
 import com.intellij.lang.properties.psi.PropertiesFile;
 import com.intellij.openapi.components.*;
 import com.intellij.openapi.project.Project;
-import gnu.trove.THashMap;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.SoftFactoryMap;
+import com.intellij.util.xmlb.annotations.MapAnnotation;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Transient;
 import gnu.trove.TIntLongHashMap;
 import gnu.trove.TIntProcedure;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -41,17 +43,22 @@
       file = StoragePathMacros.PROJECT_FILE
     )}
 )
-public class PropertiesSeparatorManager implements PersistentStateComponent<Element> {
-  @NonNls private static final String FILE_ELEMENT = "file";
-  @NonNls private static final String URL_ELEMENT = "url";
-  @NonNls private static final String SEPARATOR_ATTR = "separator";
+public class PropertiesSeparatorManager implements PersistentStateComponent<PropertiesSeparatorManager.PropertiesSeparatorManagerState> {
   private final Project myProject;
 
   public static PropertiesSeparatorManager getInstance(final Project project) {
     return ServiceManager.getService(project, PropertiesSeparatorManager.class);
   }
 
-  private final Map<String, String> mySeparators = new THashMap<String, String>();
+  private PropertiesSeparatorManagerState myUserDefinedSeparators = new PropertiesSeparatorManagerState();
+  @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
+  private final SoftFactoryMap<ResourceBundleImpl, String> myGuessedSeparators = new SoftFactoryMap<ResourceBundleImpl, String>() {
+    @Nullable
+    @Override
+    protected String create(ResourceBundleImpl resourceBundle) {
+      return guessSeparator(resourceBundle);
+    }
+  };
 
   public PropertiesSeparatorManager(final Project project) {
     myProject = project;
@@ -62,12 +69,9 @@
     if (!(resourceBundle instanceof ResourceBundleImpl)) {
       return ".";
     }
-    String separator = mySeparators.get(((ResourceBundleImpl)resourceBundle).getUrl());
-    if (separator == null) {
-      separator = guessSeparator((ResourceBundleImpl)resourceBundle);
-      setSeparator(resourceBundle, separator);
-    }
-    return separator;
+    final ResourceBundleImpl resourceBundleImpl = (ResourceBundleImpl)resourceBundle;
+    String separator = myUserDefinedSeparators.getSeparators().get(resourceBundleImpl.getUrl());
+    return separator == null ? myGuessedSeparators.get(resourceBundleImpl) : separator;
   }
 
   //returns most probable separator in properties files
@@ -108,23 +112,68 @@
 
   public void setSeparator(ResourceBundle resourceBundle, String separator) {
     if (resourceBundle instanceof ResourceBundleImpl) {
-      mySeparators.put(((ResourceBundleImpl)resourceBundle).getUrl(), separator);
+      myUserDefinedSeparators.getSeparators().put(((ResourceBundleImpl)resourceBundle).getUrl(), separator);
     }
   }
 
-  public void loadState(final Element element) {
-    List<Element> files = element.getChildren(FILE_ELEMENT);
-    for (Element fileElement : files) {
-      String url = fileElement.getAttributeValue(URL_ELEMENT, "");
-      String separator = fileElement.getAttributeValue(SEPARATOR_ATTR,"");
-      separator = decodeSeparator(separator);
-      if (separator == null) {
-        continue;
+  public void loadState(final PropertiesSeparatorManagerState state) {
+    myUserDefinedSeparators = state.decode(myProject);
+  }
+
+  @Nullable
+  @Override
+  public PropertiesSeparatorManagerState getState() {
+    return myUserDefinedSeparators.isEmpty() ? null : myUserDefinedSeparators.encode();
+  }
+
+  public static class PropertiesSeparatorManagerState {
+    @Property(surroundWithTag = false)
+    @MapAnnotation(surroundWithTag = false,
+                   surroundKeyWithTag = false,
+                   surroundValueWithTag = false,
+                   keyAttributeName = "url",
+                   valueAttributeName = "separator",
+                   entryTagName = "file")
+    public Map<String, String> mySeparators = new HashMap<String, String>();
+
+    public Map<String, String> getSeparators() {
+      return mySeparators;
+    }
+
+    public boolean isEmpty() {
+      return mySeparators.isEmpty();
+    }
+
+    public PropertiesSeparatorManagerState encode() {
+      PropertiesSeparatorManagerState encodedState = new PropertiesSeparatorManagerState();
+      for (final Map.Entry<String, String> entry : mySeparators.entrySet()) {
+        String separator = entry.getValue();
+        StringBuilder encoded = new StringBuilder(separator.length());
+        for (int i=0;i<separator.length();i++) {
+          char c = separator.charAt(i);
+          encoded.append("\\u");
+          encoded.append(String.format("%04x", (int) c));
+        }
+        encodedState.getSeparators().put(entry.getKey(), encoded.toString());
       }
-      ResourceBundle resourceBundle = PropertiesImplUtil.createByUrl(url, myProject);
-      if (resourceBundle != null) {
-        mySeparators.put(url, separator);
+      return encodedState;
+    }
+
+    public PropertiesSeparatorManagerState decode(final Project project) {
+      PropertiesSeparatorManagerState decoded = new PropertiesSeparatorManagerState();
+      for (final Map.Entry<String, String> entry : mySeparators.entrySet()) {
+        String separator = entry.getValue();
+        separator = decodeSeparator(separator);
+        if (separator == null) {
+          continue;
+        }
+        final String url = entry.getKey();
+        ResourceBundle resourceBundle = PropertiesImplUtil.createByUrl(url, project);
+        if (resourceBundle != null) {
+          decoded.getSeparators().put(url, separator);
+        }
       }
+      return decoded;
     }
   }
 
@@ -140,42 +189,10 @@
       if (!encodedCharacter.startsWith("\\u")) {
         return null;
       }
-      int d1 = Character.digit(encodedCharacter.charAt(2), 16);      
-      int d2 = Character.digit(encodedCharacter.charAt(3), 16);      
-      int d3 = Character.digit(encodedCharacter.charAt(4), 16);      
-      int d4 = Character.digit(encodedCharacter.charAt(5), 16);
-      if (d1 == -1 || d2 == -1 || d3 == -1 || d4 == -1) {
-        return null;
-      }
-      int b1 = (d1 << 12) & 0xF000;
-      int b2 = (d2 << 8) & 0x0F00;
-      int b3 = (d3 << 4) & 0x00F0;
-      int b4 = (d4 << 0) & 0x000F;
-      char code = (char) (b1 | b2 | b3 | b4);
+      char code = (char) Integer.parseInt(encodedCharacter.substring(2), 16);
       result.append(code);
       pos += 6;
     }
     return result.toString();
   }
-
-  public Element getState() {
-    Element element = new Element("PropertiesSeparatorManager");
-    for (final String url: mySeparators.keySet()) {
-      String separator = mySeparators.get(url);
-      StringBuilder encoded = new StringBuilder(separator.length());
-      for (int i=0;i<separator.length();i++) {
-        char c = separator.charAt(i);
-        encoded.append("\\u");
-        encoded.append(Character.forDigit(c >> 12, 16));
-        encoded.append(Character.forDigit((c >> 8) & 0xf, 16));
-        encoded.append(Character.forDigit((c >> 4) & 0xf, 16));
-        encoded.append(Character.forDigit(c & 0xf, 16));
-      }
-      Element fileElement = new Element(FILE_ELEMENT);
-      fileElement.setAttribute(URL_ELEMENT, url);
-      fileElement.setAttribute(SEPARATOR_ATTR, encoded.toString());
-      element.addContent(fileElement);
-    }
-    return element;
-  }
 }
diff --git a/plugins/properties/resources/icons/PropertiesIcons.java b/plugins/properties/resources/icons/PropertiesIcons.java
deleted file mode 100644
index 156d144..0000000
--- a/plugins/properties/resources/icons/PropertiesIcons.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2000-2013 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 icons;
-
-import com.intellij.openapi.util.IconLoader;
-
-import javax.swing.*;
-
-/**
- * NOTE THIS FILE IS AUTO-GENERATED
- * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
- */
-public class PropertiesIcons {
-  private static Icon load(String path) {
-    return IconLoader.getIcon(path, PropertiesIcons.class);
-  }
-
-  public static final Icon XmlProperties = load("/icons/xmlProperties.png"); // 16x16
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
index d0eafb7..062666f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
@@ -86,6 +86,10 @@
     }
   }
 
+  @Override
+  public void finish() {
+  }
+
   public Set<NestedCopyInfo> getCopies() {
     return mySet;
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
index ac165c4..f6515de 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
@@ -29,4 +29,5 @@
   void processUnversioned(final VirtualFile vFile);
   void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format, SVNURL rootURL);
   void bewareRoot(VirtualFile vf, SVNURL url);
+  void finish();
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
index 367ae1b..690eb1e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
@@ -15,12 +15,11 @@
  */
 package org.jetbrains.idea.svn;
 
-import com.intellij.lifecycle.PeriodicalTasksCloser;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
@@ -34,14 +33,14 @@
 public class StatusWalkerPartner {
   private final SvnVcs myVcs;
   private final ChangeListManager myClManager;
-  private final FileIndexFacade myExcludedFileIndex;
+  private final ProjectLevelVcsManager myVcsManager;
   private final ProgressIndicator myIndicator;
   private ISVNStatusFileProvider myFileProvider;
 
   public StatusWalkerPartner(final SvnVcs vcs, final ProgressIndicator pi) {
     myVcs = vcs;
     myClManager = ChangeListManager.getInstance(myVcs.getProject());
-    myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(myVcs.getProject(), FileIndexFacade.class);
+    myVcsManager = ProjectLevelVcsManager.getInstance(myVcs.getProject());
     myIndicator = pi;
   }
 
@@ -75,12 +74,12 @@
     }
   }
 
-  public boolean isExcluded(final VirtualFile vFile) {
+  public boolean isIgnoredByVcs(final VirtualFile vFile) {
     return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
       @Override
       public Boolean compute() {
         if (myVcs.getProject().isDisposed()) throw new ProcessCanceledException();
-        return myExcludedFileIndex.isExcludedFile(vFile);
+        return myVcsManager.isIgnored(vFile);
       }
     });
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
index 073826f..41461ed 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
@@ -95,6 +95,8 @@
         walker.go(item.getDir(), Depth.IMMEDIATES);
       }
 
+      statusReceiver.getMulticaster().finish();
+
       processCopiedAndDeleted(context, dirtyScope);
       processUnsaved(dirtyScope, addGate, context);
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
index 716abbe..9ae90c7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction;
@@ -48,6 +49,7 @@
   private Map<FilePath, String> myCopyFromURLs = null;
   private final SvnVcs myVcs;
   private final SvnBranchConfigurationManager myBranchConfigurationManager;
+  private final List<File> filesToRefresh = ContainerUtil.newArrayList();
 
   private final ProgressIndicator myProgress;
 
@@ -79,6 +81,11 @@
   public void bewareRoot(VirtualFile vf, SVNURL url) {
   }
 
+  @Override
+  public void finish() {
+    LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh, true, false, null);
+  }
+
   public ChangelistBuilder getBuilder() {
     return myChangelistBuilder;
   }
@@ -302,7 +309,7 @@
    *
    * @param filePath the path of a changed file.
    */
-  private static void loadEntriesFile(final FilePath filePath) {
+  private void loadEntriesFile(final FilePath filePath) {
     final FilePath parentPath = filePath.getParentPath();
     if (parentPath == null) {
       return;
@@ -313,9 +320,11 @@
     }
   }
 
-  private static void refreshDotSvnAndEntries(FilePath filePath) {
+  private void refreshDotSvnAndEntries(FilePath filePath) {
     final File svn = new File(filePath.getPath(), SvnUtil.SVN_ADMIN_DIR_NAME);
-    LocalFileSystem.getInstance().refreshIoFiles(Arrays.asList(svn, new File(svn, SvnUtil.ENTRIES_FILE_NAME)), true, false, null);
+
+    filesToRefresh.add(svn);
+    filesToRefresh.add(new File(svn, SvnUtil.ENTRIES_FILE_NAME));
   }
 
   // seems here we can only have a tree conflict; which can be marked on either path (?)
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
index 49ea87d..5f5edd1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
@@ -34,14 +34,14 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.commandLine.SvnBindException;
 import org.jetbrains.idea.svn.history.LatestExistentSearcher;
-import org.jetbrains.idea.svn.info.InfoConsumer;
 import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.info.InfoConsumer;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.jetbrains.idea.svn.status.Status;
 import org.jetbrains.idea.svn.status.StatusType;
 import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
 import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.File;
@@ -162,11 +162,12 @@
     }
   }
 
+  @Nullable
   private String getCommitMessage(File path) throws VcsException {
-    SVNPropertyData property =
+    PropertyValue property =
       myVcs.getFactory(path).createPropertyClient().getProperty(SvnTarget.fromFile(path), COMMIT_MESSAGE, true, SVNRevision.BASE);
 
-    return property != null ? SVNPropertyValue.getPropertyAsString(property.getValue()) : null;
+    return PropertyValue.toString(property);
   }
 
   private static ItemLatestState defaultResult() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
index 6424889..c8b47aa 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
@@ -19,7 +19,7 @@
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -42,10 +42,10 @@
       ioFiles[i] = new File(files[i].getPath());
 
       PropertyClient client = myVCS.getFactory(ioFiles[i]).createPropertyClient();
-      SVNPropertyData property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK,
+      PropertyValue property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK,
                                                     false, SVNRevision.WORKING);
 
-      if (property == null || property.getValue() == null) {
+      if (property == null) {
         throw new VcsException(SvnBundle.message("exception.text.file.miss.svn", ioFiles[i].getName()));
       }
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
index 1719f78..977c6ad 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
@@ -15,122 +15,15 @@
  */
 package org.jetbrains.idea.svn;
 
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNErrorCode;
-import org.tmatesoft.svn.core.SVNErrorMessage;
 import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector;
 import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
 import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
 import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
 
-public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
-
-  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFormatSelector");
-
-  public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
-    if (ApplicationManager.getApplication().isUnitTestMode()) {
-      return factories;
-    }
-
-    if (! writeAccess) {
-      return factories;
-    }
-
-    Collection result = null;
-    final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat();
-    if (presetFormat != null) {
-      result = format2Factories(presetFormat, factories);
-    }
-
-    if (result == null) {
-      final WorkingCopyFormat format = getWorkingCopyFormat(path);
-      result = format2Factories(format, factories);
-    }
-
-    if (result == null) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
-    }
-    return result;
-  }
-
-  @Nullable
-  static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) {
-    if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
-      return factories;
-    } else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
-      return factoriesFor16(factories);
-    } else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) {
-      return factoriesFor15(factories);
-    } else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) {
-      return factoriesFor14(factories);
-    } else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) {
-      return factoriesFor13(factories);
-    }
-    return null;
-  }
-
-  private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) {
-    for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
-      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
-      final int supportedVersion = factory.getSupportedVersion();
-      if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) {
-        return Collections.singletonList(factory);
-      }
-    }
-    return Collections.emptyList();
-  }
-
-  private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) {
-    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
-    for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
-      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
-      final int supportedVersion = factory.getSupportedVersion();
-      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
-          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) {
-        result.add(factory);
-      }
-    }
-    return result;
-  }
-
-  private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) {
-    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
-    for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
-      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
-      final int supportedVersion = factory.getSupportedVersion();
-      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
-          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
-           (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) {
-        result.add(factory);
-      }
-    }
-    return result;
-  }
-
-  private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) {
-    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
-    for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
-      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
-      final int supportedVersion = factory.getSupportedVersion();
-      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
-          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
-           (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) ||
-           (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) {
-        result.add(factory);
-      }
-    }
-    return result;
-  }
+public class SvnFormatSelector {
 
   @NotNull
   public static WorkingCopyFormat findRootAndGetFormat(final File path) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
index 1b1cd00..13c15b2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
@@ -103,7 +103,7 @@
     if (e.contains(SVNErrorCode.WC_NOT_DIRECTORY) || e.contains(SVNErrorCode.WC_NOT_FILE)) {
       final VirtualFile virtualFile = path.getVirtualFile();
       if (virtualFile != null) {
-        if (! myPartner.isExcluded(virtualFile)) {
+        if (! myPartner.isIgnoredByVcs(virtualFile)) {
           // self is unversioned
           myReceiver.processUnversioned(virtualFile);
 
@@ -184,15 +184,20 @@
       }
     };
     if (Depth.EMPTY.equals(newDepth)) {
-      directoryFilter = Processor.TRUE;
+      // just process immediate children - so only root directory itself should satisfy filter
+      directoryFilter = new Processor<File>() {
+        @Override
+        public boolean process(File file) {
+          return FileUtil.filesEqual(ioFile, file);
+        }
+      };
       processor = new Processor<File>() {
         @Override
         public boolean process(File file) {
-          // here we deal only with immediate children - so ignored on IDEA level for children is not important - we nevertheless do not go into
-          // other levels
-          if (! FileUtil.filesEqual(ioFile, file)) return true;
-          if (! FileUtil.filesEqual(ioFile, file.getParentFile())) return false;
-          return checkDirProcessor.process(file);
+          // TODO: check if we should still call checkDirProcessor() here - or we really could not check ignore settings but just call
+          // TODO: myReceiver.processUnversioned() for all immediate children
+          // here we deal only with immediate children - so ignored on IDEA level for children is not important
+          return FileUtil.filesEqual(ioFile, file) || checkDirProcessor.process(file);
         }
       };
     } else {
@@ -278,7 +283,7 @@
           @Override
           public Boolean compute() {
             if (myProject.isDisposed()) return null;
-            return myPartner.isExcluded(vFile);
+            return myPartner.isIgnoredByVcs(vFile);
           }
         });
         if (Boolean.TRUE.equals(excluded)) return;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index 5010ac5..b44fd16 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -81,6 +81,8 @@
 import org.jetbrains.idea.svn.info.Info;
 import org.jetbrains.idea.svn.info.InfoConsumer;
 import org.jetbrains.idea.svn.properties.PropertyClient;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
 import org.jetbrains.idea.svn.status.Status;
 import org.jetbrains.idea.svn.status.StatusType;
@@ -89,7 +91,6 @@
 import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -108,8 +109,8 @@
 
   private static final VcsKey ourKey = createKey(VCS_NAME);
   public static final Topic<Runnable> WC_CONVERTED = new Topic<Runnable>("WC_CONVERTED", Runnable.class);
-  private final Map<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
-    new SoftHashMap<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>>();
+  private final Map<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
+    new SoftHashMap<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>>();
 
   private final SvnConfiguration myConfiguration;
   private final SvnEntriesFileListener myEntriesFileListener;
@@ -567,9 +568,9 @@
   }
 
   @Nullable
-  public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException {
-    Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file));
-    final Pair<SVNPropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName);
+  public PropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException {
+    Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file));
+    final Pair<PropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName);
 
     final File ioFile = new File(file.getPath());
     final Trinity<Long, Long, Long> tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory());
@@ -582,17 +583,16 @@
     }
 
     PropertyClient client = getFactory(ioFile).createPropertyClient();
-    final SVNPropertyData value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING);
-    final SVNPropertyValue propValue = value == null ? null : value.getValue();
+    final PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING);
 
     if (cachedMap == null) {
-      cachedMap = new HashMap<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>();
+      cachedMap = new HashMap<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>();
       myPropertyCache.put(keyForVf(file), cachedMap);
     }
 
-    cachedMap.put(propName, Pair.create(propValue, tsTrinity));
+    cachedMap.put(propName, Pair.create(value, tsTrinity));
 
-    return propValue;
+    return value;
   }
 
   @Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
index 97e6a61..395dc36 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
@@ -19,12 +19,15 @@
 import com.intellij.openapi.diff.DiffManager;
 import com.intellij.openapi.diff.SimpleContent;
 import com.intellij.openapi.diff.SimpleDiffRequest;
+import com.intellij.openapi.progress.PerformInBackgroundOption;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.AbstractVcs;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.VcsDataKeys;
@@ -34,17 +37,20 @@
 import com.intellij.openapi.vcs.changes.ContentRevision;
 import com.intellij.openapi.vcs.changes.MarkerVcsContentRevision;
 import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnBundle;
-import org.jetbrains.idea.svn.SvnRevisionNumber;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNErrorMessage;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -69,8 +75,6 @@
   @Override
   public void update(final AnActionEvent e) {
     final DataContext dataContext = e.getDataContext();
-    final Project project = CommonDataKeys.PROJECT.getData(dataContext);
-
     final Presentation presentation = e.getPresentation();
     final Change[] data = VcsDataKeys.CHANGES.getData(dataContext);
     boolean showAction = checkThatChangesAreUnderSvn(data);
@@ -78,38 +82,23 @@
     presentation.setEnabled(showAction);
   }
 
-  private boolean checkThatChangesAreUnderSvn(Change[] data) {
-    boolean showAction = false;
-    if (data != null) {
-      for (Change change : data) {
-        final ContentRevision before = change.getBeforeRevision();
-        if (before != null) {
-          showAction = showAction || before instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)before).getVcsKey());
+  private static boolean checkThatChangesAreUnderSvn(@Nullable Change[] changes) {
+    boolean result = false;
+
+    if (changes != null) {
+      result = ContainerUtil.or(changes, new Condition<Change>() {
+        @Override
+        public boolean value(Change change) {
+          return isUnderSvn(change.getBeforeRevision()) || isUnderSvn(change.getAfterRevision());
         }
-        final ContentRevision after = change.getAfterRevision();
-        if (after != null) {
-          showAction = showAction || after instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)after).getVcsKey());
-        }
-        if (showAction) break;
-      }
+      });
     }
-    return showAction;
+
+    return result;
   }
 
-  private boolean enabled(final Project project, final Change[] changes) {
-    final boolean noChange = (project == null) || (changes == null) || (changes.length != 1);
-    if (noChange) {
-      return false;
-    } else {
-      final Change change = changes[0];
-
-      final ContentRevision revision = (change.getBeforeRevision() != null) ? change.getBeforeRevision() : change.getAfterRevision();
-      if ((revision == null) || (! (revision.getRevisionNumber() instanceof SvnRevisionNumber))) {
-        return false;
-      }
-
-      return checkVcs(project, change);
-    }
+  private static boolean isUnderSvn(@Nullable ContentRevision revision) {
+    return revision instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)revision).getVcsKey());
   }
 
   protected boolean checkVcs(final Project project, final Change change) {
@@ -146,7 +135,7 @@
     private final String myErrorTitle;
 
     private CalculateAndShow(@Nullable final Project project, final Change change, final String errorTitle) {
-      super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, Backgroundable.DEAF);
+      super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, PerformInBackgroundOption.DEAF);
       myChange = change;
       myErrorTitle = errorTitle;
     }
@@ -179,7 +168,7 @@
           }
           if (myBeforeContent != null && myAfterContent != null && myBeforeRevisionValue != null && myAfterRevision != null) {
             final SimpleDiffRequest diffRequest = new SimpleDiffRequest(myProject, getDiffWindowTitle(myChange));
-            if (compareRevisions(myBeforeRevisionValue, myAfterRevision) >= 0) {
+            if (compareRevisions(myBeforeRevisionValue, myAfterRevision) > 0) {
               // before ahead
               diffRequest.setContents(new SimpleContent(myAfterContent), new SimpleContent(myBeforeContent));
               diffRequest.setContentTitles(revisionToString(myAfterRevision), revisionToString(myBeforeRevisionValue));
@@ -194,7 +183,8 @@
     }
   }
 
-  private String getDiffWindowTitle(final Change change) {
+  @NotNull
+  private static String getDiffWindowTitle(@NotNull Change change) {
     if (change.isMoved() || change.isRenamed()) {
       final FilePath beforeFilePath = ChangesUtil.getBeforePath(change);
       final FilePath afterFilePath = ChangesUtil.getAfterPath(change);
@@ -207,7 +197,7 @@
     }
   }
 
-  private int compareRevisions(@NonNls final SVNRevision revision1, @NonNls final SVNRevision revision2) {
+  private static int compareRevisions(@NotNull SVNRevision revision1, @NotNull SVNRevision revision2) {
     if (revision1.equals(revision2)) {
       return 0;
     }
@@ -227,11 +217,9 @@
     return revision1.getNumber() > revision2.getNumber() ? 1 : -1;
   }
 
-  private String revisionToString(final SVNRevision revision) {
-    if (revision == null) {
-      return "not exists";
-    }
-    return revision.toString();
+  @NotNull
+  private static String revisionToString(@Nullable SVNRevision revision) {
+    return revision == null ? "not exists" : revision.toString();
   }
 
   private final static String ourPropertiesDelimiter = "\n";
@@ -273,35 +261,35 @@
 
   private static String getPropertyList(@NotNull SvnVcs vcs, @NotNull SvnTarget target, @Nullable SVNRevision revision)
     throws VcsException {
-    final List<SVNPropertyData> lines = new ArrayList<SVNPropertyData>();
-    final ISVNPropertyHandler propertyHandler = createHandler(revision, lines);
+    final List<PropertyData> lines = new ArrayList<PropertyData>();
+    final PropertyConsumer propertyHandler = createHandler(revision, lines);
 
     vcs.getFactory(target).createPropertyClient().list(target, revision, Depth.EMPTY, propertyHandler);
 
     return toSortedStringPresentation(lines);
   }
 
-  private static ISVNPropertyHandler createHandler(SVNRevision revision, final List<SVNPropertyData> lines) {
+  private static PropertyConsumer createHandler(SVNRevision revision, final List<PropertyData> lines) {
     final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
     if (indicator != null) {
       indicator.checkCanceled();
       indicator.setText(SvnBundle.message("show.properties.diff.progress.text.revision.information", revision.toString()));
     }
 
-    return new ISVNPropertyHandler() {
-      public void handleProperty(final File path, final SVNPropertyData property) throws SVNException {
+    return new PropertyConsumer() {
+      public void handleProperty(final File path, final PropertyData property) throws SVNException {
         registerProperty(property);
       }
 
-      public void handleProperty(final SVNURL url, final SVNPropertyData property) throws SVNException {
+      public void handleProperty(final SVNURL url, final PropertyData property) throws SVNException {
         registerProperty(property);
       }
 
-      public void handleProperty(final long revision, final SVNPropertyData property) throws SVNException {
+      public void handleProperty(final long revision, final PropertyData property) throws SVNException {
         // revision properties here
       }
 
-      private void registerProperty(@NotNull SVNPropertyData property) {
+      private void registerProperty(@NotNull PropertyData property) {
         if (indicator != null) {
           indicator.checkCanceled();
           indicator.setText2(SvnBundle.message("show.properties.diff.progress.text2.property.information", property.getName()));
@@ -311,26 +299,26 @@
     };
   }
 
-  private static String toSortedStringPresentation(List<SVNPropertyData> lines) {
+  private static String toSortedStringPresentation(List<PropertyData> lines) {
     StringBuilder sb = new StringBuilder();
 
-    Collections.sort(lines, new Comparator<SVNPropertyData>() {
-      public int compare(final SVNPropertyData o1, final SVNPropertyData o2) {
+    Collections.sort(lines, new Comparator<PropertyData>() {
+      public int compare(final PropertyData o1, final PropertyData o2) {
         return o1.getName().compareTo(o2.getName());
       }
     });
 
-    for (SVNPropertyData line : lines) {
+    for (PropertyData line : lines) {
       addPropertyPresentation(line, sb);
     }
 
     return sb.toString();
   }
 
-  private static void addPropertyPresentation(final SVNPropertyData property, final StringBuilder sb) {
+  private static void addPropertyPresentation(final PropertyData property, final StringBuilder sb) {
     if (sb.length() != 0) {
       sb.append(ourPropertiesDelimiter);
     }
-    sb.append(property.getName()).append("=").append((property.getValue() == null) ? "" : SVNPropertyValue.getPropertyAsString(property.getValue()));
+    sb.append(property.getName()).append("=").append(StringUtil.notNullize(PropertyValue.toString(property.getValue())));
   }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
index 31206ee..d6d9c31 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
@@ -24,7 +24,6 @@
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.*;
 import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
@@ -42,15 +41,16 @@
 import org.jetbrains.idea.svn.api.ProgressTracker;
 import org.jetbrains.idea.svn.commandLine.CommandUtil;
 import org.jetbrains.idea.svn.dialogs.SelectCreateExternalTargetDialog;
+import org.jetbrains.idea.svn.properties.ExternalsDefinitionParser;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.jetbrains.idea.svn.update.UpdateClient;
 import org.tmatesoft.svn.core.SVNCancelException;
 import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.internal.wc.SVNExternal;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.File;
+import java.util.Map;
 
 /**
  * Created with IntelliJ IDEA.
@@ -132,25 +132,24 @@
   public static boolean addToExternalProperty(@NotNull SvnVcs vcs, @NotNull File ioFile, String target, String url)
     throws SVNException, VcsException {
     ClientFactory factory = vcs.getFactory(ioFile);
-    SVNPropertyData propertyData = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS,
+    PropertyValue propertyValue = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS,
                                                                               false, SVNRevision.UNDEFINED);
     String newValue;
-    if (propertyData != null && propertyData.getValue() != null && ! StringUtil.isEmptyOrSpaces(propertyData.getValue().getString())) {
-      final SVNExternal[] externals = SVNExternal.parseExternals("Create External", propertyData.getValue().getString());
-      for (SVNExternal external : externals) {
-        if (Comparing.equal(external.getPath(), target)) {
-          AbstractVcsHelper
-            .getInstance(vcs.getProject()).showError(new VcsException("Selected destination conflicts with existing: " + external.toString()), "Create External");
-          return true;
-        }
+    if (propertyValue != null && !StringUtil.isEmptyOrSpaces(propertyValue.toString())) {
+      Map<String, String> externalsMap = ExternalsDefinitionParser.parseExternalsProperty(propertyValue.toString());
+      String externalsForTarget = externalsMap.get(target);
+
+      if (externalsForTarget != null) {
+        AbstractVcsHelper.getInstance(vcs.getProject()).showError(
+          new VcsException("Selected destination conflicts with existing: " + externalsForTarget), "Create External");
+        return true;
       }
       final String string = createExternalDefinitionString(url, target);
-      newValue = propertyData.getValue().getString().trim() + "\n" + string;
+      newValue = propertyValue.toString().trim() + "\n" + string;
     } else {
       newValue = createExternalDefinitionString(url, target);
     }
-    factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, SVNPropertyValue.create(newValue), Depth.EMPTY,
-                                               false);
+    factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, PropertyValue.create(newValue), Depth.EMPTY, false);
     return false;
   }
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
index cdc738c..5e53cc9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
@@ -30,7 +30,7 @@
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.dialogs.SetPropertyDialog;
 import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.SVNPropertyValue;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 
 import java.io.File;
 
@@ -79,7 +79,7 @@
 
         // TODO: most likely SVNDepth.getInfinityOrEmptyDepth should be used instead of SVNDepth.fromRecursive - to have either "infinity"
         // TODO: or "empty" depth, and not "infinity" or "files" depth. But previous logic used SVNDepth.fromRecursive implicitly
-        client.setProperty(ioFile, name, SVNPropertyValue.create(value), Depth.allOrFiles(recursive), false);
+        client.setProperty(ioFile, name, PropertyValue.create(value), Depth.allOrFiles(recursive), false);
       }
       for(int i = 0; i < file.length; i++) {
         if (recursive && file[i].isDirectory()) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
index c206cd3..94fc2e1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
@@ -15,11 +15,10 @@
  */
 package org.jetbrains.idea.svn.actions;
 
-import com.intellij.lifecycle.PeriodicalTasksCloser;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.VfsUtilCore;
@@ -42,39 +41,36 @@
 
   public static class Filter {
     private final Project myProject;
-    private final FileIndexFacade myIndex;
+    private final ProjectLevelVcsManager myVcsManager;
     private final ChangeListManager myClManager;
 
     public Filter(final Project project) {
       myProject = project;
 
       if (!project.isDefault()) {
-        myIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
+        myVcsManager = ProjectLevelVcsManager.getInstance(project);
         myClManager = ChangeListManager.getInstance(project);
       }
       else {
-        myIndex = null;
+        myVcsManager = null;
         myClManager = null;
       }
     }
 
     public boolean accept(final VirtualFile file) {
       if (!myProject.isDefault()) {
-        if (isExcluded(file)) {
-          return false;
-        }
-        if (myClManager.isIgnoredFile(file)) {
+        if (isIgnoredByVcs(file) || myClManager.isIgnoredFile(file)) {
           return false;
         }
       }
       return true;
     }
 
-    private boolean isExcluded(final VirtualFile file) {
+    private boolean isIgnoredByVcs(final VirtualFile file) {
       return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
         @Override
         public Boolean compute() {
-          return myIndex.isExcludedFile(file);
+          return myVcsManager.isIgnored(file);
         }
       });
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
index 912bd97..ddd9bd5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
@@ -32,9 +32,9 @@
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.info.Info;
 import org.jetbrains.idea.svn.properties.PropertyClient;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.SVNProperty;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.ByteArrayOutputStream;
@@ -162,8 +162,8 @@
       File ioFile = new File(file.getPath());
       PropertyClient client = vcs.getFactory(ioFile).createPropertyClient();
 
-      SVNPropertyData svnPropertyData = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING);
-      if (svnPropertyData != null && SVNProperty.isBinaryMimeType(SVNPropertyValue.getPropertyAsString(svnPropertyData.getValue()))) {
+      PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING);
+      if (value != null && SVNProperty.isBinaryMimeType(value.toString())) {
         return true;
       }
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
index 33e0673..0b484e4 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.CharsetToolkit;
 import com.intellij.util.EventDispatcher;
@@ -36,6 +37,7 @@
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -152,9 +154,20 @@
 
   protected void beforeCreateProcess() throws SvnBindException {
     EncodingEnvironmentUtil.fixDefaultEncodingIfMac(myCommandLine, null);
+    setupLocale();
     ensureMessageFile();
   }
 
+  private void setupLocale() {
+    String locale = Registry.stringValue("svn.executable.locale");
+    Map<String, String> environment = myCommandLine.getEnvironment();
+
+    // TODO: check if we need to set LC_ALL to configured locale or just clear it
+    environment.put("LC_ALL", "");
+    environment.put("LC_MESSAGES", locale);
+    environment.put("LANG", locale);
+  }
+
   private void ensureMessageFile() throws SvnBindException {
     if (myMessage != null) {
       myMessageFile = createTempFile("commit-message", ".txt");
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
index eee7987..eb2e6cf 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
@@ -58,8 +58,7 @@
     boolean hasPegRevision = pegRevision != null &&
                              !SVNRevision.UNDEFINED.equals(pegRevision) &&
                              !SVNRevision.WORKING.equals(pegRevision) &&
-                             pegRevision.isValid() &&
-                             pegRevision.getNumber() != 0;
+                             pegRevision.isValid();
 
     if (hasPegRevision || hasAtSymbol) {
       // add '@' to correctly handle paths that contain '@' symbol
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
index a70a4f2..40e3c80 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
@@ -63,16 +63,10 @@
 
   public void onError(final String text, final JComponent component, final boolean forbidSave) {
     myTabbedPane.setSelectedComponent(component);
-    String prefixString = "";
-    for (int i = 0; i < myTabbedPane.getComponentCount(); i++) {
-      final Component currentComponent = myTabbedPane.getComponentAt(i);
-      // compare referencies - same objects
-      if (currentComponent == component) {
-        prefixString = myTabbedPane.getTitleAt(i) + ": ";
-      }
-    }
+    String errorPrefix = myTabbedPane.getTitleAt(myTabbedPane.indexOfComponent(component)) + ": ";
+
     setOKActionEnabled(! forbidSave);
-    setInvalid(prefixString + text);
+    setInvalid(errorPrefix + text);
   }
 
   public void onSuccess() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
index 6bd08c1..50ddd96 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
@@ -22,10 +22,12 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.MultiLineLabelUI;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.*;
 import com.intellij.ui.components.JBList;
+import com.intellij.util.ObjectUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -100,16 +102,23 @@
     myListPanel.add(
       ToolbarDecorator.createDecorator(myLocationList)
         .setAddAction(new AnActionButtonRunnable() {
+
+          @Nullable private SVNURL usedRootUrl;
+
           @Override
           public void run(AnActionButton button) {
-            final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString());
-            if (selectedUrl != null) {
-              if (!configuration.getBranchUrls().contains(selectedUrl)) {
-                configuration
-                  .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
-                mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null);
-                listModel.fireItemAdded();
-                myLocationList.setSelectedIndex(listModel.getSize() - 1);
+            Pair<String, SVNURL> result = SelectLocationDialog.selectLocation(project, ObjectUtils.notNull(usedRootUrl, rootUrl));
+            if (result != null) {
+              String selectedUrl = result.getFirst();
+              usedRootUrl = result.getSecond();
+              if (selectedUrl != null) {
+                if (!configuration.getBranchUrls().contains(selectedUrl)) {
+                  configuration
+                    .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
+                  mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null);
+                  listModel.fireItemAdded();
+                  myLocationList.setSelectedIndex(listModel.getSize() - 1);
+                }
               }
             }
           }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
index 860c524..cd504be 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
@@ -37,9 +37,12 @@
 import org.jetbrains.idea.svn.SvnPropertyKeys;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.api.Depth;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNProperty;
+import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -151,20 +154,20 @@
     }
   }
 
-  private void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) {
+  private static void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) {
     try {
-      ISVNPropertyHandler handler = new ISVNPropertyHandler() {
-        public void handleProperty(File path, SVNPropertyData property) throws SVNException {
-          final SVNPropertyValue value = property.getValue();
+      PropertyConsumer handler = new PropertyConsumer() {
+        public void handleProperty(File path, PropertyData property) throws SVNException {
+          final PropertyValue value = property.getValue();
           if (value != null) {
-            props.put(property.getName(), SVNPropertyValue.getPropertyAsString(property.getValue()));
+            props.put(property.getName(), PropertyValue.toString(property.getValue()));
           }
         }
 
-        public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+        public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
         }
 
-        public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+        public void handleProperty(long revision, PropertyData property) throws SVNException {
         }
       };
       vcs.getFactory(file).createPropertyClient().list(SvnTarget.fromFile(file, SVNRevision.UNDEFINED), SVNRevision.WORKING, Depth.EMPTY,
@@ -229,10 +232,12 @@
       String url = "file://" + myFile.getPath().replace(File.separatorChar, '/');
       VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
       if (file != null) {
+        VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(myVcs.getProject());
+
         if (recursive && file.isDirectory()) {
-          VcsDirtyScopeManager.getInstance(myVcs.getProject()).dirDirtyRecursively(file, true);
+          dirtyScopeManager.dirDirtyRecursively(file);
         } else {
-          VcsDirtyScopeManager.getInstance(myVcs.getProject()).fileDirty(file);
+          dirtyScopeManager.fileDirty(file);
         }
       }
     }
@@ -272,8 +277,7 @@
       if (!StringUtil.isEmpty(property)) {
         try {
           myVcs.getFactory(myFile).createPropertyClient()
-            .setProperty(myFile, property, value != null ? SVNPropertyValue.create(value) : null,
-                         Depth.allOrEmpty(recursive), force);
+            .setProperty(myFile, property, PropertyValue.create(value), Depth.allOrEmpty(recursive), force);
         }
         catch (VcsException error) {
           VcsBalloonProblemNotifier
@@ -302,7 +306,7 @@
 
     public void actionPerformed(AnActionEvent e) {
       Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
-      SVNPropertyData propValue = null;
+      PropertyValue propValue = null;
       try {
         propValue = myVcs.getFactory(myFile).createPropertyClient()
           .getProperty(SvnTarget.fromFile(myFile), SVNProperty.KEYWORDS, false, SVNRevision.WORKING);
@@ -311,8 +315,7 @@
         // show erorr message
       }
 
-      SetKeywordsDialog dialog = new SetKeywordsDialog(project,
-                                                       propValue != null ? SVNPropertyValue.getPropertyAsString(propValue.getValue()) : null);
+      SetKeywordsDialog dialog = new SetKeywordsDialog(project, PropertyValue.toString(propValue));
       dialog.show();
       if (dialog.isOK()) {
         setProperty(SvnPropertyKeys.SVN_KEYWORDS, dialog.getKeywords(), false, false);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
index 0fd1f06..163be49 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
@@ -76,10 +76,26 @@
   }
 
   public void setRepositoryURLs(SVNURL[] urls, final boolean showFiles) {
+    setRepositoryURLs(urls, showFiles, null, false);
+  }
+
+  public void setRepositoryURLs(SVNURL[] urls,
+                                final boolean showFiles,
+                                @Nullable NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory,
+                                boolean expandFirst) {
     RepositoryTreeModel model = new RepositoryTreeModel(myVCS, showFiles, this);
+
+    if (defaultExpanderFactory != null) {
+      model.setDefaultExpanderFactory(defaultExpanderFactory);
+    }
+
     model.setRoots(urls);
     Disposer.register(this, model);
     myRepositoryTree.setModel(model);
+
+    if (expandFirst) {
+      myRepositoryTree.expandRow(0);
+    }
   }
 
   public void setRepositoryURL(SVNURL url, boolean showFiles, final NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
index 191acf3..83d895b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
@@ -93,7 +93,7 @@
 
   private final boolean myShowFiles;
 
-  @NonNls private static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar";
+  @NonNls public static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar";
   @NonNls private static final String PLACE_MENU = "RepositoryBrowser.Menu";
   private final String myRepositoriesLabelText;
   protected JLabel myRepositoriesLabel;
@@ -138,7 +138,7 @@
     DefaultActionGroup group = new DefaultActionGroup();
     final RepositoryBrowserComponent browser = getRepositoryBrowser();
     group.add(new AddLocationAction(browser));
-    group.add(new EditLocationAction());
+    group.add(new EditLocationAction(browser));
     group.add(new DiscardLocationAction(browser));
     group.add(new DetailsAction());
     group.addSeparator();
@@ -216,7 +216,7 @@
     group.add(copyUrlAction);
     group.addSeparator();
     group.add(new RefreshAction(browser));
-    group.add(new EditLocationAction());
+    group.add(new EditLocationAction(browser));
     group.add(new DiscardLocationAction(browser));
     ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(PLACE_MENU, group);
     return menu.getComponent();
@@ -413,13 +413,17 @@
     }
   }
 
-  protected class EditLocationAction extends AnAction {
-    public EditLocationAction() {
+  protected static class EditLocationAction extends AnAction {
+
+    @NotNull private final RepositoryBrowserComponent myBrowserComponent;
+
+    public EditLocationAction(@NotNull RepositoryBrowserComponent browserComponent) {
       super(SvnBundle.message("repository.browser.edit.location.menu.item"));
+      myBrowserComponent = browserComponent;
     }
 
     public void update(AnActionEvent e) {
-      RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode();
+      RepositoryTreeNode node = myBrowserComponent.getSelectedNode();
       if (e.getPlace().equals(PLACE_TOOLBAR)) {
         e.getPresentation().setDescription(SvnBundle.message("repository.browser.edit.location.menu.item"));
         e.getPresentation().setText(SvnBundle.message("repository.browser.edit.location.menu.item"));
@@ -429,13 +433,14 @@
     }
 
     public void actionPerformed(AnActionEvent e) {
-      RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode();
+      RepositoryTreeNode node = myBrowserComponent.getSelectedNode();
       if (node == null || (! (node.getParent() instanceof RepositoryTreeRootNode))) {
         return;
       }
       final String oldUrl = node.getURL().toString();
       final SvnApplicationSettings settings = SvnApplicationSettings.getInstance();
-      final AddRepositoryLocationDialog dialog = new AddRepositoryLocationDialog(myProject, settings.getTypedUrlsListCopy()) {
+      final AddRepositoryLocationDialog dialog =
+        new AddRepositoryLocationDialog(myBrowserComponent.getProject(), settings.getTypedUrlsListCopy()) {
         @Override
         protected String initText() {
           return oldUrl;
@@ -453,9 +458,9 @@
           settings.addTypedUrl(url);
           settings.removeCheckoutURL(oldUrl);
           settings.addCheckoutURL(url);
-          final RepositoryBrowserComponent browser = getRepositoryBrowser();
-          browser.removeURL(oldUrl);
-          browser.addURL(url);
+
+          myBrowserComponent.removeURL(oldUrl);
+          myBrowserComponent.addURL(url);
         }
       }
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
index a6ca6ad..bcbbe79 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
@@ -15,12 +15,15 @@
  */
 package org.jetbrains.idea.svn.dialogs;
 
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.help.HelpManager;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -52,21 +55,30 @@
   private final String myDstLabel;
   private JTextField myDstText;
   private final boolean myIsShowFiles;
+  private final boolean myAllowActions;
 
   @NonNls private static final String HELP_ID = "vcs.subversion.common";
 
   // todo check that works when authenticated
   @Nullable
   public static String selectLocation(Project project, String url) {
-    SelectLocationDialog dialog = openDialog(project, url, null, null, true, null);
+    SelectLocationDialog dialog = openDialog(project, url, null, null, true, false, null);
 
     return dialog == null || !dialog.isOK() ? null : dialog.getSelectedURL();
   }
 
   @Nullable
+  public static Pair<String, SVNURL> selectLocation(Project project, @NotNull SVNURL url) {
+    SelectLocationDialog dialog = new SelectLocationDialog(project, url, null, null, true, true);
+    dialog.show();
+
+    return dialog.isOK() ? Pair.create(dialog.getSelectedURL(), dialog.getRootUrl()) : null;
+  }
+
+  @Nullable
   public static String selectCopyDestination(Project project, String url, String dstLabel, String dstName, boolean showFiles) {
     SelectLocationDialog dialog =
-      openDialog(project, url, dstLabel, dstName, showFiles, SvnBundle.message("select.location.invalid.url.message", url));
+      openDialog(project, url, dstLabel, dstName, showFiles, false, SvnBundle.message("select.location.invalid.url.message", url));
 
     return dialog == null || !dialog.isOK() ? null : SVNPathUtil.append(dialog.getSelectedURL(), dialog.getDestinationName());
   }
@@ -77,6 +89,7 @@
                                                  String dstLabel,
                                                  String dstName,
                                                  boolean showFiles,
+                                                 boolean allowActions,
                                                  String errorMessage) {
     try {
       SVNURL svnUrl = SvnUtil.createUrl(url);
@@ -86,8 +99,7 @@
                                  SvnBundle.message("dialog.title.select.repository.location"));
         return null;
       }
-
-      SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles);
+      SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles, allowActions);
       dialog.show();
       return dialog;
     }
@@ -98,13 +110,14 @@
     }
   }
 
-  private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles) {
+  private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles, boolean allowActions) {
     super(project, true);
     myProject = project;
     myDstLabel = dstLabel;
     myDstName = dstName;
     myURL = url;
     myIsShowFiles = showFiles;
+    myAllowActions = allowActions;
     setTitle(SvnBundle.message("dialog.title.select.repository.location"));
     getHelpAction().setEnabled(true);
     init();
@@ -146,7 +159,13 @@
   protected void init() {
     super.init();
     final String urlString = myURL.toString();
-    myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString));
+    if (myAllowActions) {
+      // initialize repo browser this way - to make actions work correctly
+      myRepositoryBrowser.setRepositoryURLs(new SVNURL[]{myURL}, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString), true);
+    }
+    else {
+      myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString));
+    }
     myRepositoryBrowser.addChangeListener(new TreeSelectionListener() {
       public void valueChanged(TreeSelectionEvent e) {
         getOKAction().setEnabled(isOKActionEnabled());
@@ -162,7 +181,10 @@
 
   protected JComponent createCenterPanel() {
     JPanel panel = new JPanel();
-    panel.setLayout(new GridBagLayout());
+    panel.setLayout(new BorderLayout());
+
+    JPanel browserPanel = new JPanel();
+    browserPanel.setLayout(new GridBagLayout());
 
     GridBagConstraints gc = new GridBagConstraints();
     gc.insets = new Insets(2, 2, 2, 2);
@@ -177,7 +199,7 @@
 
 
     myRepositoryBrowser = new RepositoryBrowserComponent(SvnVcs.getInstance(myProject));
-    panel.add(myRepositoryBrowser, gc);
+    browserPanel.add(myRepositoryBrowser, gc);
     if (myDstName != null) {
       gc.gridy += 1;
       gc.gridwidth = 1;
@@ -187,7 +209,7 @@
       gc.weighty = 0;
 
       JLabel dstLabel = new JLabel(myDstLabel);
-      panel.add(dstLabel, gc);
+      browserPanel.add(dstLabel, gc);
 
       gc.gridx += 1;
       gc.weightx = 1;
@@ -196,7 +218,7 @@
       myDstText = new JTextField();
       myDstText.setText(myDstName);
       myDstText.selectAll();
-      panel.add(myDstText, gc);
+      browserPanel.add(myDstText, gc);
 
       myDstText.getDocument().addDocumentListener(new DocumentListener() {
         public void insertUpdate(DocumentEvent e) {
@@ -217,12 +239,25 @@
       gc.gridy += 1;
       gc.gridwidth = 2;
 
-      panel.add(new JSeparator(), gc);
+      browserPanel.add(new JSeparator(), gc);
     }
 
+    if (myAllowActions) {
+      panel.add(createToolbar(), BorderLayout.NORTH);
+    }
+    panel.add(browserPanel, BorderLayout.CENTER);
+
     return panel;
   }
 
+  @NotNull
+  private JComponent createToolbar() {
+    DefaultActionGroup group = new DefaultActionGroup();
+    group.add(new RepositoryBrowserDialog.EditLocationAction(myRepositoryBrowser));
+
+    return ActionManager.getInstance().createActionToolbar(RepositoryBrowserDialog.PLACE_TOOLBAR, group, true).getComponent();
+  }
+
   public JComponent getPreferredFocusedComponent() {
     return (JComponent)myRepositoryBrowser.getPreferredFocusedComponent();
   }
@@ -246,4 +281,16 @@
   public String getSelectedURL() {
     return myRepositoryBrowser.getSelectedURL();
   }
+
+  @Nullable
+  public SVNURL getRootUrl() {
+    RepositoryTreeNode node = myRepositoryBrowser.getSelectedNode();
+
+    // find the most top parent of type RepositoryTreeNode
+    while (node != null && node.getParent() instanceof RepositoryTreeNode) {
+      node = (RepositoryTreeNode)node.getParent();
+    }
+
+    return node != null ? node.getURL() : null;
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
index 28375d2..f2a58a0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
@@ -24,15 +24,16 @@
 import com.intellij.ui.DocumentAdapter;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnBundle;
 import org.jetbrains.idea.svn.SvnPropertyKeys;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.SVNPropertyValue;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -154,10 +155,10 @@
       return;
     }
     File file = myFiles[0];
-    SVNPropertyData property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null;
+    PropertyValue property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null;
 
     if (property != null) {
-      myValueText.setText(SVNPropertyValue.getPropertyAsString(property.getValue()));
+      myValueText.setText(property.toString());
       myValueText.selectAll();
     }
     else {
@@ -165,19 +166,20 @@
     }
   }
 
-  private SVNPropertyData getProperty(@NotNull File file, @NotNull String name) {
-    SVNPropertyData property;
+  @Nullable
+  private PropertyValue getProperty(@NotNull File file, @NotNull String name) {
+    PropertyValue result;
 
     try {
       PropertyClient client = myVCS.getFactory(file).createPropertyClient();
-      property = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING);
+      result = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING);
     }
     catch (VcsException e) {
       LOG.info(e);
-      property = null;
+      result = null;
     }
 
-    return property;
+    return result;
   }
 
   protected JComponent createCenterPanel() {
@@ -205,18 +207,18 @@
     if (files.length == 1) {
       File file = files[0];
       try {
-        ISVNPropertyHandler handler = new ISVNPropertyHandler() {
-          public void handleProperty(File path, SVNPropertyData property) {
+        PropertyConsumer handler = new PropertyConsumer() {
+          public void handleProperty(File path, PropertyData property) {
             String name = property.getName();
             if (name != null) {
               names.add(name);
             }
           }
 
-          public void handleProperty(SVNURL url, SVNPropertyData property) {
+          public void handleProperty(SVNURL url, PropertyData property) {
           }
 
-          public void handleProperty(long revision, SVNPropertyData property) {
+          public void handleProperty(long revision, PropertyData property) {
           }
         };
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
index 4971347..be084b0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
@@ -52,13 +52,14 @@
  */
 public class CmdDiffClient extends BaseSvnClient implements DiffClient {
 
+  @NotNull
   @Override
   public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
-    assertUrl(target2);
-    if (target1.isFile()) {
+    assertUrl(target1);
+    if (target2.isFile()) {
       // Such combination (file and url) with "--summarize" option is supported only in svn 1.8.
       // For svn 1.7 "--summarize" is only supported when both targets are repository urls.
-      assertDirectory(target1);
+      assertDirectory(target2);
 
       WorkingCopyFormat format = WorkingCopyFormat.from(myFactory.createVersionClient().getVersion());
       if (format.less(WorkingCopyFormat.ONE_DOT_EIGHT)) {
@@ -95,6 +96,7 @@
     }
   }
 
+  @NotNull
   private List<Change> parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor)
     throws SvnBindException {
     try {
@@ -114,16 +116,30 @@
     }
   }
 
-  private ContentRevision createRemoteRevision(@NotNull FilePath remotePath, @NotNull FilePath localPath, @NotNull FileStatus status) {
+  @NotNull
+  private ContentRevision createRevision(@NotNull FilePath path,
+                                         @NotNull FilePath localPath,
+                                         @NotNull SVNRevision revision,
+                                         @NotNull FileStatus status) {
+    ContentRevision result;
+
+    if (path.isNonLocal()) {
     // explicitly use local path for deleted items - so these items will be correctly displayed as deleted under local working copy node
     // and not as deleted under remote branch node (in ChangesBrowser)
     // NOTE, that content is still retrieved using remotePath.
-    return SvnRepositoryContentRevision
-      .create(myVcs, remotePath, status == FileStatus.DELETED ? localPath : null, SVNRevision.HEAD.getNumber());
+      result = SvnRepositoryContentRevision.create(myVcs, path, status == FileStatus.DELETED ? localPath : null, revision.getNumber());
+    }
+    else {
+      result = CurrentContentRevision.create(path);
   }
 
-  private static ContentRevision createLocalRevision(@NotNull FilePath path) {
-    return CurrentContentRevision.create(path);
+    return result;
+  }
+
+  private static FilePath createFilePath(@NotNull SvnTarget target, boolean isDirectory) {
+    return target.isFile()
+           ? VcsUtil.getFilePath(target.getFile(), isDirectory)
+           : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(target), isDirectory);
   }
 
   @NotNull
@@ -134,9 +150,7 @@
     // TODO: 3) Properties change is currently not added as part of result change like in SvnChangeProviderContext.patchWithPropertyChange
 
     SvnTarget subTarget1 = SvnUtil.append(target1, diffPath.path, true);
-    String relativePath = target1.isFile()
-                          ? FileUtil.getRelativePath(target1.getFile(), subTarget1.getFile())
-                          : SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1));
+    String relativePath = SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1));
 
     if (relativePath == null) {
       throw new SvnBindException("Could not get relative path for " + target1 + " and " + subTarget1);
@@ -144,27 +158,19 @@
 
     SvnTarget subTarget2 = SvnUtil.append(target2, FileUtil.toSystemIndependentName(relativePath));
 
-    FilePath target1Path = target1.isFile()
-                           ? VcsUtil.getFilePath(subTarget1.getFile(), diffPath.isDirectory())
-                           : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget1), diffPath.isDirectory());
-    FilePath target2Path = VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget2), diffPath.isDirectory());
+    FilePath target1Path = createFilePath(subTarget1, diffPath.isDirectory());
+    FilePath target2Path = createFilePath(subTarget2, diffPath.isDirectory());
 
     FileStatus status = SvnStatusConvertor
       .convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus));
 
-    // for "file + url" pair - statuses determine changes needs to be done to "url" to get "file" state
-    // for "url1 + url2" pair - statuses determine changes needs to be done to "url1" to get "url2" state
+    // statuses determine changes needs to be done to "target1" to get "target2" state
     ContentRevision beforeRevision = status == FileStatus.ADDED
                                      ? null
-                                     : target1.isFile()
-                                       ? createRemoteRevision(target2Path, target1Path, status)
-                                       : createRemoteRevision(target1Path, target2Path, status);
+                                     : createRevision(target1Path, target2Path, target1.getPegRevision(), status);
     ContentRevision afterRevision = status == FileStatus.DELETED
                                     ? null
-                                    : target1.isFile()
-                                      ? createLocalRevision(target1Path)
-                                      : createRemoteRevision(target2Path, target1Path, status);
-
+                                    : createRevision(target2Path, target1Path, target2.getPegRevision(), status);
 
     return createChange(status, beforeRevision, afterRevision);
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
index 35c35e9..dfa43dd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
@@ -29,6 +29,11 @@
  */
 public interface DiffClient extends SvnClient {
 
+  /**
+   * @param target1 Should always be url.
+   * @param target2 Could be either url or file. And should be directory if file.
+   */
+  @NotNull
   List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException;
 
   void unifiedDiff(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull OutputStream output) throws VcsException;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
index 0f0e6a7..784548d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
@@ -24,6 +24,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.WorkingCopyFormat;
 import org.jetbrains.idea.svn.api.ClientFactory;
 import org.tmatesoft.svn.core.SVNException;
@@ -53,19 +54,24 @@
     titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl,
                                           FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl())));
 
-    SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath()));
-    SvnTarget target2 = SvnTarget.fromURL(myElementUrl);
+    SvnTarget target1 = SvnTarget.fromURL(myElementUrl);
+    SvnTarget target2 = SvnTarget.fromFile(new File(myVirtualFile.getPath()));
 
     changes.addAll(getClientFactory().createDiffClient().compare(target1, target2));
   }
 
   @NotNull
   private ClientFactory getClientFactory() {
-    WorkingCopyFormat format = myVcs.getWorkingCopyFormat(VfsUtilCore.virtualToIoFile(myVirtualFile));
+    return getClientFactory(myVcs, VfsUtilCore.virtualToIoFile(myVirtualFile));
+  }
+
+  @NotNull
+  public static ClientFactory getClientFactory(@NotNull SvnVcs vcs, @NotNull File file) {
+    WorkingCopyFormat format = vcs.getWorkingCopyFormat(file);
 
     // svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository
     // directories - that is why command line is only used explicitly for svn 1.8
-    return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? myVcs.getCommandLineFactory() : myVcs.getSvnKitFactory();
+    return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? vcs.getCommandLineFactory() : vcs.getSvnKitFactory();
   }
 
   @Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
index 0a1b148..ec4c512 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
@@ -54,6 +54,7 @@
  */
 public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
 
+  @NotNull
   @Override
   public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
     DiffExecutor executor = new DiffExecutor(target1, target2);
@@ -99,12 +100,12 @@
     }
 
     public void run() throws SVNException {
-      assertUrl(myTarget2);
+      assertUrl(myTarget1);
 
-      if (myTarget1.isFile()) {
-        assertDirectory(myTarget1);
+      if (myTarget2.isFile()) {
+        assertDirectory(myTarget2);
 
-        WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget1.getFile());
+        WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget2.getFile());
         myChanges.addAll(WorkingCopyFormat.ONE_DOT_SIX.equals(format) ? run16Diff() : run17Diff());
       }
       else {
@@ -142,20 +143,20 @@
     }
 
     private Collection<Change> run17Diff() throws SVNException {
-      final Info info1 = myVcs.getInfo(myTarget1.getFile(), SVNRevision.HEAD);
+      final Info info1 = myVcs.getInfo(myTarget2.getFile(), SVNRevision.HEAD);
 
       if (info1 == null) {
         SVNErrorMessage err =
-          SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget1);
+          SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget2);
         SVNErrorManager.error(err, SVNLogType.WC);
       }
       else if (info1.getURL() == null) {
-        SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget1);
+        SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget2);
         SVNErrorManager.error(err, SVNLogType.WC);
       }
 
       final SVNReporter17 reporter17 =
-        new SVNReporter17(myTarget1.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() {
+        new SVNReporter17(myTarget2.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() {
           @Override
           public void handleEvent(SVNEvent event, double progress) throws SVNException {
           }
@@ -169,9 +170,9 @@
       try {
         repository = myVcs.getSvnKitManager().createRepository(info1.getURL());
         long rev = repository.getLatestRevision();
-        repository2 = myVcs.getSvnKitManager().createRepository(myTarget2.getURL());
-        SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget1.getFile(), repository2, rev, true);
-        repository.diff(myTarget2.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
+        repository2 = myVcs.getSvnKitManager().createRepository(myTarget1.getURL());
+        SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget2.getFile(), repository2, rev, true);
+        repository.diff(myTarget1.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
                         SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null));
 
         return diffEditor.getChangesMap().values();
@@ -193,7 +194,7 @@
       SVNRepository repository = null;
       SVNRepository repository2 = null;
       try {
-        SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget1.getFile(), false, SVNWCAccess.INFINITE_DEPTH);
+        SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget2.getFile(), false, SVNWCAccess.INFINITE_DEPTH);
         File anchorPath = info.getAnchor().getRoot();
         String target = "".equals(info.getTargetName()) ? null : info.getTargetName();
 
@@ -215,10 +216,10 @@
         repository = myVcs.getSvnKitManager().createRepository(anchorURL.toString());
         long rev = repository.getLatestRevision();
         repository2 =
-          myVcs.getSvnKitManager().createRepository((target == null) ? myTarget2.getURL() : myTarget2.getURL().removePathTail());
+          myVcs.getSvnKitManager().createRepository((target == null) ? myTarget1.getURL() : myTarget1.getURL().removePathTail());
         SvnDiffEditor diffEditor =
-          new SvnDiffEditor(target == null ? myTarget1.getFile() : myTarget1.getFile().getParentFile(), repository2, rev, true);
-        repository.diff(myTarget2.getURL(), rev, rev, target, true, true, false, reporter,
+          new SvnDiffEditor(target == null ? myTarget2.getFile() : myTarget2.getFile().getParentFile(), repository2, rev, true);
+        repository.diff(myTarget1.getURL(), rev, rev, target, true, true, false, reporter,
                         SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null));
 
         return diffEditor.getChangesMap().values();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java
new file mode 100644
index 0000000..be11212
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.api.ClientFactory;
+import org.jetbrains.idea.svn.diff.DirectoryWithBranchComparer;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<SvnFileRevision> {
+
+  @NotNull private final SvnVcs myVcs;
+
+  public SvnDiffFromHistoryHandler(@NotNull SvnVcs vcs) {
+    super(vcs.getProject());
+    myVcs = vcs;
+  }
+
+  @NotNull
+  @Override
+  protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull SvnFileRevision rev1, @Nullable SvnFileRevision rev2)
+    throws VcsException {
+    File file = path.getIOFile();
+    SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev1.getURL()), rev1.getRevision());
+    SvnTarget target2 = rev2 != null ? SvnTarget.fromURL(SvnUtil.createUrl(rev2.getURL()), rev2.getRevision()) : SvnTarget.fromFile(file);
+
+    return executeDiff(path, target1, target2);
+  }
+
+  @NotNull
+  @Override
+  protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull SvnFileRevision rev) throws VcsException {
+    // Diff with zero revision is used here to get just affected changes under the path, and not all affected changes of the revision.
+    SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), SVNRevision.create(0));
+    SvnTarget target2 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), rev.getRevision());
+
+    return executeDiff(path, target1, target2);
+  }
+
+  @NotNull
+  @Override
+  protected String getPresentableName(@NotNull SvnFileRevision revision) {
+    return revision.getRevisionNumber().asString();
+  }
+
+  @NotNull
+  private List<Change> executeDiff(@NotNull FilePath path, @NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
+    File file = path.getIOFile();
+    ClientFactory factory = target2.isURL() ? myVcs.getFactory(file) : DirectoryWithBranchComparer.getClientFactory(myVcs, file);
+
+    return factory.createDiffClient().compare(target1, target2);
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
index d2b8206..8d18307 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
@@ -40,8 +40,8 @@
 import org.jetbrains.idea.svn.SvnPropertyKeys;
 import org.jetbrains.idea.svn.SvnUtil;
 import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
 import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -145,7 +145,7 @@
         }
         SvnTarget target = SvnTarget.fromURL(root);
         myVcs.getFactory(target).createPropertyClient()
-          .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), SVNPropertyValue.create(myNewMessage), false);
+          .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), PropertyValue.create(myNewMessage), false);
       }
       catch (SVNException e) {
         myException = new VcsException(e);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
index 9e9dd7e..b23b577 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -73,7 +73,7 @@
 
   @Override
   public DiffFromHistoryHandler getHistoryDiffHandler() {
-    return null;
+    return new SvnDiffFromHistoryHandler(myVcs);
   }
 
   @Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
index f2f91bc..8ae2da7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
@@ -77,11 +77,6 @@
     return myCommittedPath;
   }
 
-  @Override
-  public boolean isContentAvailable(final VcsFileRevision revision) {
-    return !myCommittedPath.isDirectory();
-  }
-
   public boolean isHaveMergeSources() {
     return myHaveMergeSources;
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
index 8a9dbf7..e0bdc15 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
@@ -24,8 +24,7 @@
 import org.jetbrains.idea.svn.SvnPropertyKeys;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.api.Depth;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -68,7 +67,7 @@
     protected final boolean myCanUseCachedProperty;
     
     protected abstract void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data,
-                                          final SVNPropertyValue propertyValue) throws VcsException;
+                                          final PropertyValue propertyValue) throws VcsException;
 
     protected abstract void onAfterProcessing(final VirtualFile[] file) throws VcsException;
 
@@ -92,14 +91,12 @@
         }
         final File dir = new File(entry.getKey().getPath());
         try {
-          final SVNPropertyValue value;
+          final PropertyValue value;
           if (myCanUseCachedProperty) {
             value = myVcs.getPropertyWithCaching(entry.getKey(), SvnPropertyKeys.SVN_IGNORE);
           } else {
-            final SVNPropertyData data =
-              myVcs.getFactory(dir).createPropertyClient()
-                .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING);
-            value = data == null ? null : data.getValue();
+            value = myVcs.getFactory(dir).createPropertyClient()
+              .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING);
           }
           processFolder(entry.getKey(), dir, entry.getValue(), value);
         }
@@ -127,7 +124,7 @@
       return (! myFilesOk) && (! myExtensionOk);
     }
 
-    protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue)
+    protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue)
       throws VcsException {
       if (propertyValue == null) {
         myFilesOk = false;
@@ -135,7 +132,7 @@
         return;
       }
       final Set<String> ignorePatterns = new HashSet<String>();
-      final StringTokenizer st = new StringTokenizer(SVNPropertyValue.getPropertyAsString(propertyValue), "\r\n ");
+      final StringTokenizer st = new StringTokenizer(PropertyValue.toString(propertyValue), "\r\n ");
       while (st.hasMoreElements()) {
         final String ignorePattern = (String)st.nextElement();
         ignorePatterns.add(ignorePattern);
@@ -180,14 +177,14 @@
       return false;
     }
 
-    protected abstract String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue);
+    protected abstract String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue);
 
-    protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue)
+    protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue)
       throws VcsException {
       String newValue = getNewPropertyValue(data, propertyValue);
       newValue = (newValue.trim().isEmpty()) ? null : newValue;
       myVcs.getFactory(folderDir).createPropertyClient()
-        .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, SVNPropertyValue.create(newValue), Depth.EMPTY, false);
+        .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, PropertyValue.create(newValue), Depth.EMPTY, false);
 
       if (myUseCommonExtension) {
         dirtyScopeManager.dirDirtyRecursively(folder);
@@ -216,9 +213,9 @@
       super(activeVcs, project, useCommonExtension);
     }
 
-    protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) {
+    protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) {
       if (propertyValue != null) {
-        return getNewPropertyValueForRemove(data, SVNPropertyValue.getPropertyAsString(propertyValue));
+        return getNewPropertyValueForRemove(data, PropertyValue.toString(propertyValue));
       }
       return "";
     }
@@ -241,7 +238,7 @@
       super(activeVcs, project, useCommonExtension);
     }
 
-    protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) {
+    protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) {
       final String ignoreString;
       if (data.size() == 1) {
         ignoreString = data.iterator().next();
@@ -252,7 +249,7 @@
         }
         ignoreString = sb.toString();
       }
-      return (propertyValue == null) ? ignoreString : (SVNPropertyValue.getPropertyAsString(propertyValue) + '\n' + ignoreString);
+      return (propertyValue == null) ? ignoreString : (PropertyValue.toString(propertyValue) + '\n' + ignoreString);
     }
   }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
index b6228fc..1e031e2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
@@ -20,7 +20,10 @@
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.VcsKey;
-import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeList;
+import com.intellij.openapi.vcs.changes.ChangesUtil;
+import com.intellij.openapi.vcs.changes.EmptyChangelistBuilder;
 import com.intellij.openapi.vcs.update.UpdatedFilesReverseSide;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.containers.ContainerUtil;
@@ -28,12 +31,14 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnPropertyKeys;
 import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.File;
-import java.util.*;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
 public class GatheringChangelistBuilder extends EmptyChangelistBuilder {
 
@@ -92,13 +97,13 @@
     SvnTarget target = SvnTarget.fromFile(file);
 
     try {
-      SVNPropertyData current =
+      PropertyValue current =
         myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING);
-      SVNPropertyData base =
+      PropertyValue base =
         myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.BASE);
 
       if (current != null) {
-        return base == null || !Comparing.equal(current.getValue(), base.getValue());
+        return base == null || !Comparing.equal(current, base);
       }
     }
     catch (VcsException e) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
index 6263829..701bb25 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
@@ -22,10 +22,10 @@
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.history.SvnChangeList;
 import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
 import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -205,7 +205,7 @@
       return SvnMergeInfoCache.MergeCheckResult.getInstance(mergeInfo.contains(revisionAsked));
     }
 
-    final SVNPropertyData mergeinfoProperty;
+    final PropertyValue mergeinfoProperty;
     SvnTarget target = SvnTarget.fromURL(branchUrl);
 
     try {
@@ -235,7 +235,7 @@
       return goUpInRepo(revisionAsked, targetRevision, newBranchUrl, newTrunkUrl);
     }
     // process
-    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, false);
+    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, false);
   }
 
   private Info getInfo(final File pathFile) {
@@ -277,7 +277,7 @@
       return SvnMergeInfoCache.MergeCheckResult.getInstance(merged);
     }
 
-    final SVNPropertyData mergeinfoProperty;
+    final PropertyValue mergeinfoProperty;
     try {
       if (actualRevision == targetRevisionCorrected) {
         // look in WC
@@ -302,11 +302,11 @@
       return goUp(revisionAsked, targetRevisionCorrected, branchRootPath, path, trunkUrl);
     }
     // process
-    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, self);
+    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, self);
   }
 
   private SvnMergeInfoCache.MergeCheckResult processMergeinfoProperty(final String pathWithRevisionNumber, final long revisionAsked,
-                                                                      final SVNPropertyValue value, final String trunkRelativeUrl,
+                                                                      final PropertyValue value, final String trunkRelativeUrl,
                                                                       final boolean self) {
     final String valueAsString = value.toString().trim();
 
@@ -318,7 +318,7 @@
 
     final Map<String, SVNMergeRangeList> map;
     try {
-      map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.getString())), null);
+      map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.toString())), null);
     }
     catch (SVNException e) {
       LOG.info(e);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
index 0ea95c9..225bc6a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
@@ -23,11 +23,12 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.dialogs.MergeContext;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
 import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -63,19 +64,19 @@
   
   public void prepare() throws VcsException {
     final Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge());
-    ISVNPropertyHandler handler = new ISVNPropertyHandler() {
-      public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+    PropertyConsumer handler = new PropertyConsumer() {
+      public void handleProperty(File path, PropertyData property) throws SVNException {
         final String key = keyFromFile(path);
         synchronized (myLock) {
           myDataMap.put(key, SVNMergeInfoUtil
-            .parseMergeInfo(new StringBuffer(replaceSeparators(SVNPropertyValue.getPropertyAsString(property.getValue()))), null));
+            .parseMergeInfo(new StringBuffer(replaceSeparators(PropertyValue.toString(property.getValue()))), null));
         }
       }
 
-      public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+      public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
       }
 
-      public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+      public void handleProperty(long revision, PropertyData property) throws SVNException {
       }
     };
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
index e855abe..e053776 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
@@ -10,9 +10,8 @@
 import org.jetbrains.idea.svn.commandLine.CommandUtil;
 import org.jetbrains.idea.svn.commandLine.SvnCommandName;
 import org.jetbrains.idea.svn.info.Info;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -24,6 +23,7 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author Konstantin Kolosovsky.
@@ -32,10 +32,10 @@
 
   @Nullable
   @Override
-  public SVNPropertyData getProperty(@NotNull SvnTarget target,
-                                     @NotNull String property,
-                                     boolean revisionProperty,
-                                     @Nullable SVNRevision revision)
+  public PropertyValue getProperty(@NotNull SvnTarget target,
+                                   @NotNull String property,
+                                   boolean revisionProperty,
+                                   @Nullable SVNRevision revision)
     throws VcsException {
     List<String> parameters = new ArrayList<String>();
 
@@ -57,7 +57,9 @@
     parameters.add("--xml");
 
     CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null);
-    return parseSingleProperty(target, command.getOutput());
+    PropertyData data = parseSingleProperty(target, command.getOutput());
+
+    return data != null ? data.getValue() : null;
   }
 
   @Override
@@ -65,7 +67,7 @@
                           @NotNull String property,
                           @Nullable SVNRevision revision,
                           @Nullable Depth depth,
-                          @Nullable ISVNPropertyHandler handler) throws VcsException {
+                          @Nullable PropertyConsumer handler) throws VcsException {
     List<String> parameters = new ArrayList<String>();
 
     parameters.add(property);
@@ -79,7 +81,7 @@
   public void list(@NotNull SvnTarget target,
                    @Nullable SVNRevision revision,
                    @Nullable Depth depth,
-                   @Nullable ISVNPropertyHandler handler) throws VcsException {
+                   @Nullable PropertyConsumer handler) throws VcsException {
     List<String> parameters = new ArrayList<String>();
     fillListParameters(target, revision, depth, parameters, true);
 
@@ -90,39 +92,39 @@
   @Override
   public void setProperty(@NotNull File file,
                           @NotNull String property,
-                          @Nullable SVNPropertyValue value,
+                          @Nullable PropertyValue value,
                           @Nullable Depth depth,
                           boolean force) throws VcsException {
     runSetProperty(SvnTarget.fromFile(file), property, null, depth, value, force);
   }
 
   @Override
-  public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
-    SVNProperties currentProperties = collectPropertiesToDelete(file);
+  public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException {
+    PropertiesMap currentProperties = collectPropertiesToDelete(file);
     currentProperties.putAll(properties);
 
-    for (String propertyName : currentProperties.nameSet()) {
-      setProperty(file, propertyName, currentProperties.getSVNPropertyValue(propertyName), Depth.EMPTY, true);
+    for (Map.Entry<String, PropertyValue> entry : currentProperties.entrySet()) {
+      setProperty(file, entry.getKey(), entry.getValue(), Depth.EMPTY, true);
     }
   }
 
   @NotNull
-  private SVNProperties collectPropertiesToDelete(@NotNull File file) throws VcsException {
-    final SVNProperties result = new SVNProperties();
+  private PropertiesMap collectPropertiesToDelete(@NotNull File file) throws VcsException {
+    final PropertiesMap result = new PropertiesMap();
 
-    list(SvnTarget.fromFile(file), null, Depth.EMPTY, new ISVNPropertyHandler() {
+    list(SvnTarget.fromFile(file), null, Depth.EMPTY, new PropertyConsumer() {
       @Override
-      public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+      public void handleProperty(File path, PropertyData property) throws SVNException {
         // null indicates property will be deleted
-        result.put(property.getName(), (SVNPropertyValue)null);
+        result.put(property.getName(), null);
       }
 
       @Override
-      public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+      public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
       }
 
       @Override
-      public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+      public void handleProperty(long revision, PropertyData property) throws SVNException {
       }
     });
 
@@ -133,7 +135,7 @@
   public void setRevisionProperty(@NotNull SvnTarget target,
                                   @NotNull String property,
                                   @NotNull SVNRevision revision,
-                                  @Nullable SVNPropertyValue value,
+                                  @Nullable PropertyValue value,
                                   boolean force) throws VcsException {
     runSetProperty(target, property, revision, null, value, force);
   }
@@ -142,7 +144,7 @@
                               @NotNull String property,
                               @Nullable SVNRevision revision,
                               @Nullable Depth depth,
-                              @Nullable SVNPropertyValue value,
+                              @Nullable PropertyValue value,
                               boolean force) throws VcsException {
     List<String> parameters = new ArrayList<String>();
     boolean isDelete = value == null;
@@ -153,7 +155,7 @@
       CommandUtil.put(parameters, revision);
     }
     if (!isDelete) {
-      parameters.add(SVNPropertyValue.getPropertyAsString(value));
+      parameters.add(PropertyValue.toString(value));
       // --force could only be used in "propset" command, but not in "propdel" command
       CommandUtil.put(parameters, force, "--force");
     }
@@ -180,21 +182,22 @@
     CommandUtil.put(parameters, verbose, "--verbose");
   }
 
-  private SVNPropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException {
-    final SVNPropertyData[] data = new SVNPropertyData[1];
-    ISVNPropertyHandler handler = new ISVNPropertyHandler() {
+  @Nullable
+  private PropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException {
+    final PropertyData[] data = new PropertyData[1];
+    PropertyConsumer handler = new PropertyConsumer() {
       @Override
-      public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+      public void handleProperty(File path, PropertyData property) throws SVNException {
         data[0] = property;
       }
 
       @Override
-      public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+      public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
         data[0] = property;
       }
 
       @Override
-      public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+      public void handleProperty(long revision, PropertyData property) throws SVNException {
         data[0] = property;
       }
     };
@@ -204,7 +207,7 @@
     return data[0];
   }
 
-  private static void parseOutput(SvnTarget target, String output, ISVNPropertyHandler handler) throws VcsException {
+  private static void parseOutput(SvnTarget target, String output, PropertyConsumer handler) throws VcsException {
     try {
       Properties properties = CommandUtil.parse(output, Properties.class);
 
@@ -231,7 +234,7 @@
     }
   }
 
-  private static void invokeHandler(@NotNull SvnTarget target, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler)
+  private static void invokeHandler(@NotNull SvnTarget target, @Nullable PropertyData data, @Nullable PropertyConsumer handler)
     throws SVNException {
     if (handler != null && data != null) {
       if (target.isFile()) {
@@ -242,7 +245,7 @@
     }
   }
 
-  private static void invokeHandler(long revision, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler)
+  private static void invokeHandler(long revision, @Nullable PropertyData data, @Nullable PropertyConsumer handler)
     throws SVNException {
     if (handler != null && data != null) {
       handler.handleProperty(revision, data);
@@ -250,13 +253,13 @@
   }
 
   @Nullable
-  private static SVNPropertyData create(@NotNull String property, @Nullable String value) {
-    SVNPropertyData result = null;
+  private static PropertyData create(@NotNull String property, @Nullable String value) {
+    PropertyData result = null;
 
     // such behavior is required to compatibility with SVNKit as some logic in merge depends on
     // whether null property data or property data with empty string value is returned
     if (value != null) {
-      result = new SVNPropertyData(property, SVNPropertyValue.create(value.trim()), LF_SEPARATOR_OPTIONS);
+      result = new PropertyData(property, PropertyValue.create(value.trim()));
     }
 
     return result;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java
new file mode 100644
index 0000000..b3ec74e
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class ExternalsDefinitionParser {
+
+  /**
+   * Parses "svn:externals" property in format starting from svn 1.5.
+   *
+   * @return map of externals definitions: key - relative directory, value - corresponding complete externals definition.
+   */
+  @NotNull
+  public static Map<String, String> parseExternalsProperty(@NotNull String externals) throws SvnBindException {
+    HashMap<String, String> map = ContainerUtil.newHashMap();
+
+    for (String external : StringUtil.splitByLines(externals, true)) {
+      map.put(parseRelativeDirectory(external), external);
+    }
+
+    return map;
+  }
+
+  /**
+   * Parses relative directory from externals definition (in format starting from svn 1.5). Restrictions for relative directory:
+   * - is at the end of externals definition separated from other parameters by ' ' char
+   * - could be quoted with '"' char
+   * - certain chars could be escaped with '\' char
+   */
+  @NotNull
+  public static String parseRelativeDirectory(@NotNull String s) throws SvnBindException {
+    s = s.trim();
+
+    int length = s.length();
+    String result;
+
+    if (isUnescapedQuote(s, length - 1)) {
+      int index = lastUnescapedIndexOf(s, length - 1, '"');
+      assertIndex(s, index, "Could not find start quote");
+      result = s.substring(index + 1, length - 1);
+    }
+    else {
+      int index = lastUnescapedIndexOf(s, length, ' ');
+      assertIndex(s, index, "Could not find separating space");
+      result = s.substring(index + 1);
+    }
+
+    return unescape(result);
+  }
+
+  private static void assertIndex(@NotNull String s, int index, @NotNull String message) throws SvnBindException {
+    if (index < 0) {
+      throw new SvnBindException(message + " - " + s);
+    }
+  }
+
+  @NotNull
+  private static String unescape(@NotNull String s) {
+    return s.replace("\\", "");
+  }
+
+  /**
+   * "from" index is excluded.
+   */
+  private static int lastUnescapedIndexOf(@NotNull String s, int from, char c) {
+    int result = from;
+
+    do {
+      result = s.lastIndexOf(c, result - 1);
+    }
+    while (result != -1 && !isUnescaped(s, result, c));
+
+    return result;
+  }
+
+  private static boolean isUnescapedQuote(@NotNull String s, int index) {
+    return isUnescaped(s, index, '"');
+  }
+
+  private static boolean isUnescaped(@NotNull String s, int index, char c) {
+    return StringUtil.isChar(s, index, c) && !StringUtil.isChar(s, index - 1, '\\');
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java
new file mode 100644
index 0000000..c5857aa
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.util.containers.HashMap;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertiesMap extends HashMap<String, PropertyValue> {
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
index 1b61d59..42acfc8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
@@ -1,18 +1,10 @@
 package org.jetbrains.idea.svn.properties;
 
 import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.util.LineSeparator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.api.SvnClient;
-import org.tmatesoft.svn.core.SVNProperties;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
-import org.tmatesoft.svn.core.wc.ISVNOptions;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
@@ -23,40 +15,33 @@
  */
 public interface PropertyClient extends SvnClient {
 
-  ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() {
-    @Override
-    public byte[] getNativeEOL() {
-      return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString());
-    }
-  };
-
   @Nullable
-  SVNPropertyData getProperty(@NotNull final SvnTarget target,
-                              @NotNull final String property,
-                              boolean revisionProperty,
-                              @Nullable SVNRevision revision) throws VcsException;
+  PropertyValue getProperty(@NotNull final SvnTarget target,
+                            @NotNull final String property,
+                            boolean revisionProperty,
+                            @Nullable SVNRevision revision) throws VcsException;
 
   void getProperty(@NotNull SvnTarget target, @NotNull String property,
                    @Nullable SVNRevision revision,
                    @Nullable Depth depth,
-                   @Nullable ISVNPropertyHandler handler) throws VcsException;
+                   @Nullable PropertyConsumer handler) throws VcsException;
 
   void list(@NotNull SvnTarget target,
             @Nullable SVNRevision revision,
             @Nullable Depth depth,
-            @Nullable ISVNPropertyHandler handler) throws VcsException;
+            @Nullable PropertyConsumer handler) throws VcsException;
 
   void setProperty(@NotNull File file,
                    @NotNull String property,
-                   @Nullable SVNPropertyValue value,
+                   @Nullable PropertyValue value,
                    @Nullable Depth depth,
                    boolean force) throws VcsException;
 
-  void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException;
+  void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException;
 
   void setRevisionProperty(@NotNull SvnTarget target,
                            @NotNull String property,
                            @NotNull SVNRevision revision,
-                           @Nullable SVNPropertyValue value,
+                           @Nullable PropertyValue value,
                            boolean force) throws VcsException;
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java
new file mode 100644
index 0000000..f45e09d
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface PropertyConsumer {
+
+  void handleProperty(File path, PropertyData property) throws SVNException;
+
+  void handleProperty(SVNURL url, PropertyData property) throws SVNException;
+
+  void handleProperty(long revision, PropertyData property) throws SVNException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java
new file mode 100644
index 0000000..3953636
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.wc.SVNPropertyData;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertyData {
+
+  private final PropertyValue myValue;
+
+  private final String myName;
+
+  public PropertyData(String name, PropertyValue value) {
+    myName = name;
+    myValue = value;
+  }
+
+  public String getName() {
+    return myName;
+  }
+
+  public PropertyValue getValue() {
+    return myValue;
+  }
+
+  @Nullable
+  public static PropertyData create(@Nullable SVNPropertyData data) {
+    PropertyData result = null;
+
+    if (data != null) {
+      result = new PropertyData(data.getName(), PropertyValue.create(data.getValue()));
+    }
+
+    return result;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java
new file mode 100644
index 0000000..62cb7cb
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.SVNPropertyValue;
+
+/**
+ * TODO: Add correct support of binary properties - support in api, diff, etc.
+ *
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertyValue {
+
+  @NotNull private final String myValue;
+
+  @Nullable
+  public static PropertyValue create(@Nullable SVNPropertyValue value) {
+    return create(SVNPropertyValue.getPropertyAsString(value));
+  }
+
+  private PropertyValue(@NotNull String propertyValue) {
+    myValue = propertyValue;
+  }
+
+  @Nullable
+  public static PropertyValue create(@Nullable String propertyValue) {
+    return propertyValue == null ? null : new PropertyValue(propertyValue);
+  }
+
+  @Nullable
+  public static String toString(@Nullable PropertyValue value) {
+    return value == null ? null : value.myValue;
+  }
+
+  public String toString() {
+    return myValue;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
index 4ad3f10..23fedd3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
@@ -1,42 +1,57 @@
 package org.jetbrains.idea.svn.properties;
 
 import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.LineSeparator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.api.BaseSvnClient;
 import org.jetbrains.idea.svn.api.Depth;
 import org.jetbrains.idea.svn.commandLine.SvnBindException;
 import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
 import org.tmatesoft.svn.core.wc.*;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.File;
+import java.util.Map;
 
 /**
  * @author Konstantin Kolosovsky.
  */
 public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClient {
 
+  public static final ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() {
+    @Override
+    public byte[] getNativeEOL() {
+      return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString());
+    }
+  };
+
   @Nullable
   @Override
-  public SVNPropertyData getProperty(@NotNull SvnTarget target,
-                                     @NotNull String property,
-                                     boolean revisionProperty,
-                                     @Nullable SVNRevision revision) throws VcsException {
+  public PropertyValue getProperty(@NotNull SvnTarget target,
+                                   @NotNull String property,
+                                   boolean revisionProperty,
+                                   @Nullable SVNRevision revision) throws VcsException {
+    PropertyData resultData;
+
     try {
       if (!revisionProperty) {
         if (target.isFile()) {
-          return createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision);
+          resultData = PropertyData.create(createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision));
         } else {
-          return createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision);
+          resultData = PropertyData.create(createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision));
         }
       } else {
-        return getRevisionProperty(target, property, revision);
+        resultData = getRevisionProperty(target, property, revision);
       }
     }
     catch (SVNException e) {
       throw new VcsException(e);
     }
+
+    return resultData != null ? resultData.getValue() : null;
   }
 
   @NotNull
@@ -52,7 +67,7 @@
                           @NotNull String property,
                           @Nullable SVNRevision revision,
                           @Nullable Depth depth,
-                          @Nullable ISVNPropertyHandler handler) throws VcsException {
+                          @Nullable PropertyConsumer handler) throws VcsException {
     runGetProperty(target, property, revision, depth, handler);
   }
 
@@ -60,18 +75,18 @@
   public void list(@NotNull SvnTarget target,
                    @Nullable SVNRevision revision,
                    @Nullable Depth depth,
-                   @Nullable ISVNPropertyHandler handler) throws VcsException {
+                   @Nullable PropertyConsumer handler) throws VcsException {
     runGetProperty(target, null, revision, depth, handler);
   }
 
   @Override
   public void setProperty(@NotNull File file,
                           @NotNull String property,
-                          @Nullable SVNPropertyValue value,
+                          @Nullable PropertyValue value,
                           @Nullable Depth depth,
                           boolean force) throws VcsException {
     try {
-      createClient().doSetProperty(file, property, value, force, toDepth(depth), null, null);
+      createClient().doSetProperty(file, property, toPropertyValue(value), force, toDepth(depth), null, null);
     }
     catch (SVNException e) {
       throw new SvnBindException(e);
@@ -79,12 +94,13 @@
   }
 
   @Override
-  public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
+  public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException {
+    final SVNProperties propertiesToSet = toSvnProperties(properties);
     try {
       createClient().doSetProperty(file, new ISVNPropertyValueProvider() {
         @Override
         public SVNProperties providePropertyValues(File path, SVNProperties properties) throws SVNException {
-          return properties;
+          return propertiesToSet;
         }
       }, true, SVNDepth.EMPTY, null, null);
     }
@@ -97,14 +113,14 @@
   public void setRevisionProperty(@NotNull SvnTarget target,
                                   @NotNull String property,
                                   @NotNull SVNRevision revision,
-                                  @Nullable SVNPropertyValue value,
+                                  @Nullable PropertyValue value,
                                   boolean force) throws VcsException {
     try {
       if (target.isFile()) {
-        createClient().doSetRevisionProperty(target.getFile(), revision, property, value, force, null);
+        createClient().doSetRevisionProperty(target.getFile(), revision, property, toPropertyValue(value), force, null);
       }
       else {
-        createClient().doSetRevisionProperty(target.getURL(), revision, property, value, force, null);
+        createClient().doSetRevisionProperty(target.getURL(), revision, property, toPropertyValue(value), force, null);
       }
     }
     catch (SVNException e) {
@@ -112,27 +128,39 @@
     }
   }
 
+  @NotNull
+  private static SVNProperties toSvnProperties(@NotNull PropertiesMap properties) {
+    SVNProperties result = new SVNProperties();
+
+    for (Map.Entry<String, PropertyValue> entry : properties.entrySet()) {
+      result.put(entry.getKey(), toPropertyValue(entry.getValue()));
+    }
+
+    return result;
+  }
+
   private void runGetProperty(@NotNull SvnTarget target,
                               @Nullable String property,
                               @Nullable SVNRevision revision,
                               @Nullable Depth depth,
-                              @Nullable ISVNPropertyHandler handler) throws VcsException {
+                              @Nullable PropertyConsumer handler) throws VcsException {
     SVNWCClient client = createClient();
 
     try {
       if (target.isURL()) {
-        client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), handler);
+        client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler));
       } else {
-        client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), handler, null);
+        client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler), null);
       }
     } catch (SVNException e) {
       throw new VcsException(e);
     }
   }
 
-  private SVNPropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision) throws SVNException{
+  private PropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision)
+    throws SVNException {
     final SVNWCClient client = createClient();
-    final SVNPropertyData[] result = new SVNPropertyData[1];
+    final PropertyData[] result = new PropertyData[1];
     ISVNPropertyHandler handler = new ISVNPropertyHandler() {
       @Override
       public void handleProperty(File path, SVNPropertyData property) throws SVNException {
@@ -151,7 +179,7 @@
 
       private void handle(@NotNull SVNPropertyData data) {
         if (property.equals(data.getName())) {
-          result[0] = data;
+          result[0] = PropertyData.create(data);
         }
       }
     };
@@ -164,4 +192,41 @@
 
     return result[0];
   }
+
+  @Nullable
+  private static ISVNPropertyHandler toHandler(@Nullable final PropertyConsumer consumer) {
+    ISVNPropertyHandler result = null;
+
+    if (consumer != null) {
+      result = new ISVNPropertyHandler() {
+        @Override
+        public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+          consumer.handleProperty(path, PropertyData.create(property));
+        }
+
+        @Override
+        public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+          consumer.handleProperty(url, PropertyData.create(property));
+        }
+
+        @Override
+        public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+          consumer.handleProperty(revision, PropertyData.create(property));
+        }
+      };
+    }
+
+    return result;
+  }
+
+  @Nullable
+  private static SVNPropertyValue toPropertyValue(@Nullable PropertyValue value) {
+    SVNPropertyValue result = null;
+
+    if (value != null) {
+      result = SVNPropertyValue.create(value.toString());
+    }
+
+    return result;
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
index 237d05b..7b09461 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -34,6 +34,9 @@
 import org.jetbrains.idea.svn.api.ProgressTracker;
 import org.jetbrains.idea.svn.commandLine.SvnBindException;
 import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.properties.PropertiesMap;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.wc.*;
 import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -100,7 +103,7 @@
     };
 
     final List<CopiedAsideInfo> fromToModified = new ArrayList<CopiedAsideInfo>();
-    final Map<File, SVNProperties> properties = ContainerUtil.newHashMap();
+    final Map<File, PropertiesMap> properties = ContainerUtil.newHashMap();
     moveRenamesToTmp(exceptions, fromToModified, properties, collector);
     // adds (deletes)
     // deletes (adds)
@@ -123,29 +126,29 @@
 
   private void moveRenamesToTmp(List<VcsException> exceptions,
                                 List<CopiedAsideInfo> fromToModified,
-                                final Map<File, SVNProperties> properties,
+                                final Map<File, PropertiesMap> properties,
                                 final UnversionedAndNotTouchedFilesGroupCollector collector) {
     final Map<File, ThroughRenameInfo> fromTo = collector.getFromTo();
     try {
       final File tmp = FileUtil.createTempDirectory("forRename", "");
-      final ISVNPropertyHandler handler = new ISVNPropertyHandler() {
+      final PropertyConsumer handler = new PropertyConsumer() {
         @Override
-        public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+        public void handleProperty(File path, PropertyData property) throws SVNException {
           final ThroughRenameInfo info = collector.findToFile(new FilePathImpl(path, path.isDirectory()), null);
           if (info != null) {
             if (!properties.containsKey(info.getTo())) {
-              properties.put(info.getTo(), new SVNProperties());
+              properties.put(info.getTo(), new PropertiesMap());
             }
             properties.get(info.getTo()).put(property.getName(), property.getValue());
           }
         }
 
         @Override
-        public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+        public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
         }
 
         @Override
-        public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+        public void handleProperty(long revision, PropertyData property) throws SVNException {
         }
       };
 
@@ -181,7 +184,7 @@
 
   private void moveGroup(final List<VcsException> exceptions,
                          List<CopiedAsideInfo> fromTo,
-                         Map<File, SVNProperties> properties) {
+                         Map<File, PropertiesMap> properties) {
     Collections.sort(fromTo, new Comparator<CopiedAsideInfo>() {
       @Override
       public int compare(CopiedAsideInfo o1, CopiedAsideInfo o2) {
@@ -240,8 +243,8 @@
     applyProperties(properties, exceptions);
   }
 
-  private void applyProperties(Map<File, SVNProperties> propertiesMap, final List<VcsException> exceptions) {
-    for (Map.Entry<File, SVNProperties> entry : propertiesMap.entrySet()) {
+  private void applyProperties(Map<File, PropertiesMap> propertiesMap, final List<VcsException> exceptions) {
+    for (Map.Entry<File, PropertiesMap> entry : propertiesMap.entrySet()) {
       File file = entry.getKey();
       try {
         mySvnVcs.getFactory(file).createPropertyClient().setProperties(file, entry.getValue());
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java
new file mode 100644
index 0000000..0d1a4c0
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn.svnkit;
+
+import com.intellij.openapi.application.ApplicationManager;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnFormatSelector;
+import org.jetbrains.idea.svn.SvnWorkingCopyFormatHolder;
+import org.jetbrains.idea.svn.WorkingCopyFormat;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNErrorMessage;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitAdminAreaFactorySelector implements ISVNAdminAreaFactorySelector {
+
+  public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      return factories;
+    }
+
+    if (!writeAccess) {
+      return factories;
+    }
+
+    Collection result = null;
+    final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat();
+    if (presetFormat != null) {
+      result = format2Factories(presetFormat, factories);
+    }
+
+    if (result == null) {
+      final WorkingCopyFormat format = SvnFormatSelector.getWorkingCopyFormat(path);
+      result = format2Factories(format, factories);
+    }
+
+    if (result == null) {
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
+    }
+    return result;
+  }
+
+  @Nullable
+  static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) {
+    if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
+      return factories;
+    }
+    else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
+      return factoriesFor16(factories);
+    }
+    else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) {
+      return factoriesFor15(factories);
+    }
+    else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) {
+      return factoriesFor14(factories);
+    }
+    else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) {
+      return factoriesFor13(factories);
+    }
+    return null;
+  }
+
+  private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) {
+    for (Object item : factories) {
+      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+      final int supportedVersion = factory.getSupportedVersion();
+      if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) {
+        return Collections.singletonList(factory);
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) {
+    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+    for (Object item : factories) {
+      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+      final int supportedVersion = factory.getSupportedVersion();
+      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) {
+        result.add(factory);
+      }
+    }
+    return result;
+  }
+
+  private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) {
+    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+    for (Object item : factories) {
+      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+      final int supportedVersion = factory.getSupportedVersion();
+      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) {
+        result.add(factory);
+      }
+    }
+    return result;
+  }
+
+  private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) {
+    final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+    for (Object item : factories) {
+      final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+      final int supportedVersion = factory.getSupportedVersion();
+      if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) ||
+          (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) {
+        result.add(factory);
+      }
+    }
+    return result;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
index a446b58..7571000 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
@@ -26,7 +26,6 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnConfiguration;
-import org.jetbrains.idea.svn.SvnFormatSelector;
 import org.jetbrains.idea.svn.SvnHttpAuthMethodsDefaultChecker;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.auth.SvnAuthenticationManager;
@@ -72,7 +71,7 @@
     SVNJNAUtil.setJNAEnabled(true);
     SvnHttpAuthMethodsDefaultChecker.check();
 
-    SVNAdminAreaFactory.setSelector(new SvnFormatSelector());
+    SVNAdminAreaFactory.setSelector(new SvnKitAdminAreaFactorySelector());
 
     DAVRepositoryFactory.setup();
     SVNRepositoryFactoryImpl.setup();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java
new file mode 100644
index 0000000..ff24c79
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.jetbrains.idea.svn;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.properties.ExternalsDefinitionParser;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class ExternalsDefinitionParserTest {
+
+  @Test
+  public void test_no_space_directory_with_revision() throws Exception {
+    assertRelativeDirectory("third-party/skins", "-r148 http://svn.example.com/skinproj third-party/skins");
+  }
+
+  @Test
+  public void test_no_space_directory_with_peg_revision() throws Exception {
+    assertRelativeDirectory("third-party/skins", "http://svn.example.com/skinproj@148 third-party/skins");
+  }
+
+  @Test
+  public void test_no_space_directory_without_revision() throws Exception {
+    assertRelativeDirectory("third-party/sounds", "      http://svn.example.com/repos/sounds third-party/sounds");
+  }
+
+  @Test
+  public void test_quoted_no_space_directory() throws Exception {
+    assertRelativeDirectory("third-party/skins", "-r148 http://svn.example.com/skinproj \"third-party/skins\"");
+  }
+
+  @Test
+  public void test_quoted_with_space_directory() throws Exception {
+    assertRelativeDirectory("My Project", "http://svn.thirdparty.com/repos/My%20Project \"My Project\"");
+  }
+
+  @Test
+  public void test_escaped_with_space_and_quotes_directory() throws Exception {
+    assertRelativeDirectory("\"Quotes Too\"", "http://svn.thirdparty.com/repos/%22Quotes%20Too%22 \\\"Quotes\\ Too\\\"");
+  }
+
+  private static void assertRelativeDirectory(@NotNull String expected, @NotNull String external) throws Exception {
+    assertEquals(expected, ExternalsDefinitionParser.parseRelativeDirectory(external));
+  }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
index 2e2da72..06f2685 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
@@ -2,7 +2,6 @@
 
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.NonDefaultProjectConfigurable;
 import com.intellij.openapi.options.SearchableConfigurable;
 import com.intellij.openapi.options.binding.BindControl;
 import com.intellij.openapi.options.binding.BindableConfigurable;
@@ -24,8 +23,7 @@
  * @author Dmitry Avdeev
  */
 @SuppressWarnings({"UnusedDeclaration"})
-public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent,
-                                                                      NonDefaultProjectConfigurable, Configurable.NoScroll {
+public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent, Configurable.NoScroll {
   
   private JPanel myPanel;
 
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
index 3da6ad3..2f93b83 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
@@ -29,16 +29,20 @@
 
   @Override
   protected TrelloRepository createRepository() throws Exception {
-    TrelloRepository repository = new TrelloRepository(new TrelloRepositoryType());
-    String token = System.getProperty("tasks.tests.trello.token");
-    if (StringUtil.isEmpty(token)) {
-      throw new AssertionError("Authorization token is not set");
+    try {
+      TrelloRepository repository = new TrelloRepository(new TrelloRepositoryType());
+      String token = System.getProperty("tasks.tests.trello.token");
+      assertTrue("Authorization token is not set", !StringUtil.isEmpty(token));
+      repository.setPassword(token);
+      TrelloUser user = repository.fetchUserByToken();
+      assertNotNull(user);
+      repository.setCurrentUser(user);
+      return repository;
     }
-    repository.setPassword(token);
-    TrelloUser user = repository.fetchUserByToken();
-    assertNotNull(user);
-    repository.setCurrentUser(user);
-    return repository;
+    catch (AssertionError ae){
+      tearDown();
+      throw ae;
+    }
   }
 
   // TODO Check closed tasks exclusion
diff --git a/plugins/terminal/lib/jediterm-pty-2.0.jar b/plugins/terminal/lib/jediterm-pty-2.0.jar
index 794d974..e8eaa9b 100644
--- a/plugins/terminal/lib/jediterm-pty-2.0.jar
+++ b/plugins/terminal/lib/jediterm-pty-2.0.jar
Binary files differ
diff --git a/plugins/terminal/resources/META-INF/terminal.xml b/plugins/terminal/resources/META-INF/terminal.xml
index 11a18e1..e85297f 100644
--- a/plugins/terminal/resources/META-INF/terminal.xml
+++ b/plugins/terminal/resources/META-INF/terminal.xml
@@ -1,12 +1,4 @@
 <idea-plugin version="2">
-  <actions>
-    <action id="org.jetbrains.plugins.terminal.OpenLocalTerminalAction"
-            class="org.jetbrains.plugins.terminal.OpenLocalTerminalAction"
-            text="Open Terminal..." description="Open terminal locally">
-      <add-to-group group-id="ToolsMenu" anchor="last"/>
-    </action>
-  </actions>
-
   <extensions defaultExtensionNs="com.intellij">
     <toolWindow id="Terminal" anchor="bottom" icon="TerminalIcons.OpenTerminal_13x13"
                 factoryClass="org.jetbrains.plugins.terminal.TerminalToolWindowFactory" secondary="false"/>
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
index caaa541..f67f844 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
@@ -16,6 +16,7 @@
 import com.jediterm.terminal.TtyConnector;
 import com.pty4j.PtyProcess;
 import com.pty4j.util.PtyUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
@@ -63,6 +64,11 @@
     return null;
   }
 
+  @NotNull
+  public static LocalTerminalDirectRunner createTerminalRunner(Project project) {
+    return new LocalTerminalDirectRunner(project);
+  }
+
   @Override
   protected PtyProcess createProcess(@Nullable String directory) throws ExecutionException {
     Map<String, String> envs = new HashMap<String, String>(System.getenv());
@@ -77,10 +83,14 @@
   }
 
   private String currentProjectFolder() {
-    for (VirtualFile vf : ProjectRootManager.getInstance(myProject).getContentRoots()) {
-      return vf.getCanonicalPath();
+    final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(myProject);
+
+    final VirtualFile[] roots = projectRootManager.getContentRoots();
+    if (roots.length == 1) {
+      roots[0].getCanonicalPath();
     }
-    return null;
+    final VirtualFile baseDir = myProject.getBaseDir();
+    return baseDir == null ? null : baseDir.getCanonicalPath();
   }
 
   @Override
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
deleted file mode 100644
index 4d93dd9..0000000
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.jetbrains.plugins.terminal;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.wm.ToolWindow;
-import com.intellij.openapi.wm.ToolWindowManager;
-import icons.TerminalIcons;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author traff
- */
-public class OpenLocalTerminalAction extends AnAction implements DumbAware {
-  public OpenLocalTerminalAction() {
-    super("Open Terminal...", null, TerminalIcons.OpenTerminal);
-  }
-
-  @Override
-  public void update(final AnActionEvent e) {
-    e.getPresentation().setVisible(true);
-    e.getPresentation().setEnabled(true);
-  }
-
-  public void actionPerformed(final AnActionEvent e) {
-    runLocalTerminal(e);
-  }
-
-  public void runLocalTerminal(AnActionEvent event) {
-    final Project project = event.getData(CommonDataKeys.PROJECT);
-    runLocalTerminal(project);
-  }
-
-  public static void runLocalTerminal(final Project project) {
-    ToolWindow terminal = ToolWindowManager.getInstance(project).getToolWindow("Terminal");
-    if (terminal.isActive()) {
-      TerminalView.getInstance(project).openLocalSession(project, terminal);
-    }
-    terminal.activate(new Runnable() {
-      @Override
-      public void run() {
-
-      }
-    }, true);
-  }
-
-  @NotNull
-  public static LocalTerminalDirectRunner createTerminalRunner(Project project) {
-    return new LocalTerminalDirectRunner(project);
-  }
-}
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
index 14b992a..32b7c9b 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
@@ -1,7 +1,6 @@
 package org.jetbrains.plugins.terminal;
 
 import com.intellij.icons.AllIcons;
-import com.intellij.notification.EventLog;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.project.DumbAwareAction;
@@ -23,7 +22,6 @@
 import com.jediterm.terminal.ui.JediTermWidget;
 import com.jediterm.terminal.ui.TabbedTerminalWidget;
 import com.jediterm.terminal.ui.TerminalWidget;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.terminal.vfs.TerminalSessionVirtualFileImpl;
@@ -54,7 +52,7 @@
 
 
   public void initTerminal(final ToolWindow toolWindow) {
-    LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(myProject);
+    LocalTerminalDirectRunner terminalRunner = LocalTerminalDirectRunner.createTerminalRunner(myProject);
 
     toolWindow.setToHideOnEmptyContent(true);
 
@@ -99,14 +97,9 @@
     }
   }
 
-  private Content createTerminalInContentPanel(@Nullable LocalTerminalDirectRunner terminalRunner,
+  private Content createTerminalInContentPanel(@NotNull AbstractTerminalRunner terminalRunner,
                                                final @NotNull ToolWindow toolWindow) {
-    SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true) {
-      @Override
-      public Object getData(@NonNls String dataId) {
-        return PlatformDataKeys.HELP_ID.is(dataId) ? EventLog.HELP_ID : super.getData(dataId);
-      }
-    };
+    SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
 
     final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, "", false);
     content.setCloseable(true);
@@ -162,14 +155,14 @@
   }
 
   public void openLocalSession(Project project, ToolWindow terminal) {
-    LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(project);
+    LocalTerminalDirectRunner terminalRunner = LocalTerminalDirectRunner.createTerminalRunner(project);
     openSession(terminal, terminalRunner);
   }
 
   private void openSession(@NotNull ToolWindow toolWindow, @NotNull AbstractTerminalRunner terminalRunner) {
     if (myTerminalWidget == null) {
       toolWindow.getContentManager().removeAllContents(true);
-      final Content content = createTerminalInContentPanel(null, toolWindow);
+      final Content content = createTerminalInContentPanel(terminalRunner, toolWindow);
       toolWindow.getContentManager().addContent(content);
     }
     else {
@@ -184,7 +177,7 @@
     }, true);
   }
 
-  private ActionToolbar createToolbar(@Nullable final LocalTerminalDirectRunner terminalRunner,
+  private ActionToolbar createToolbar(@Nullable final AbstractTerminalRunner terminalRunner,
                                       @NotNull final JBTabbedTerminalWidget terminal, @NotNull ToolWindow toolWindow) {
     DefaultActionGroup group = new DefaultActionGroup();
 
@@ -215,10 +208,10 @@
 
 
   private static class NewSession extends DumbAwareAction {
-    private final LocalTerminalDirectRunner myTerminalRunner;
+    private final AbstractTerminalRunner myTerminalRunner;
     private final TerminalWidget myTerminal;
 
-    public NewSession(@NotNull LocalTerminalDirectRunner terminalRunner, @NotNull TerminalWidget terminal) {
+    public NewSession(@NotNull AbstractTerminalRunner terminalRunner, @NotNull TerminalWidget terminal) {
       super("New Session", "Create New Terminal Session", AllIcons.General.Add);
       myTerminalRunner = terminalRunner;
       myTerminal = terminal;
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
index 6392361..413acee 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
@@ -122,7 +122,7 @@
     writeTempFile();
     finish();
 
-    if (!Registry.is("testng_sm_runner", false)) myClient.startListening(myConfig);
+    if (!Registry.is("testng_sm_runner")) myClient.startListening(myConfig);
   }
 
   @Override
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
index be95395..21afb56 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
@@ -122,7 +122,7 @@
 
   @Override
   public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
-    final boolean smRunner = Registry.is("testng_sm_runner", false);
+    final boolean smRunner = Registry.is("testng_sm_runner");
     if (smRunner) {
       return startSMRunner(executor);
     }
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
index 5b8518f..91b75c9 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
@@ -16,6 +16,7 @@
 package com.intellij.uiDesigner;
 
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.ClassUtil;
@@ -74,7 +75,8 @@
       }
 
       final PsiType type = getter.getReturnType();
-      final String propertyClassName = type.getCanonicalText();
+      String propertyClassName =
+        StringUtil.defaultIfEmpty(StringUtil.substringBefore(type.getCanonicalText(), "<"), type.getCanonicalText());
 
       LwIntrospectedProperty property = CompiledClassPropertiesProvider.propertyFromClassName(propertyClassName, name);
       if (property == null) {
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
index 7e6b94d..96ddb74 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,33 +15,19 @@
  */
 package com.intellij.uiDesigner.propertyInspector.editors;
 
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.ui.ListSpeedSearch;
-import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.components.JBList;
+import com.intellij.ui.ColorChooser;
+import com.intellij.ui.JBColor;
 import com.intellij.uiDesigner.UIDesignerBundle;
 import com.intellij.uiDesigner.lw.ColorDescriptor;
 import com.intellij.uiDesigner.propertyInspector.InplaceContext;
 import com.intellij.uiDesigner.propertyInspector.PropertyEditor;
-import com.intellij.uiDesigner.propertyInspector.renderers.ColorRenderer;
 import com.intellij.uiDesigner.radComponents.RadComponent;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.colorchooser.AbstractColorChooserPanel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.plaf.ColorChooserUI;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.*;
-import java.util.List;
 
 /**
  * @author yole
@@ -50,7 +36,6 @@
   private final String myPropertyName;
   private final TextFieldWithBrowseButton myTextField = new TextFieldWithBrowseButton();
   private ColorDescriptor myValue;
-  private Project myProject;
 
   public ColorEditor(String propertyName) {
     myPropertyName = propertyName;
@@ -58,11 +43,10 @@
     myTextField.getTextField().setEditable(false);
     myTextField.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
-        MyColorChooserDialog dialog = new MyColorChooserDialog(myProject);
-        dialog.setSelectedValue(myValue);
-        dialog.show();
-        if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
-          myValue = dialog.getSelectedValue();
+        String title = UIDesignerBundle.message("color.chooser.title", myPropertyName);
+        Color color = ColorChooser.chooseColor(myTextField, title , myValue.getColor());
+        if (color != null) {
+          myValue = new ColorDescriptor(color);
           updateTextField();
         }
       }
@@ -74,8 +58,7 @@
   }
 
   public JComponent getComponent(RadComponent component, ColorDescriptor value, InplaceContext inplaceContext) {
-    myValue = value != null ? value : new ColorDescriptor(new Color(0));
-    myProject = component.getProject();
+    myValue = value != null ? value : new ColorDescriptor(JBColor.BLACK);
     updateTextField();
     return myTextField;
   }
@@ -87,174 +70,4 @@
   public void updateUI() {
     SwingUtilities.updateComponentTreeUI(myTextField);
   }
-
-  private static class ColorDescriptorWrapper extends Color {
-    private final ColorDescriptor myDescriptor;
-
-    public ColorDescriptorWrapper(ColorDescriptor descriptor) {
-      super(descriptor.getResolvedColor() == null ? 0 : descriptor.getResolvedColor().getRGB());
-      myDescriptor = descriptor;
-    }
-
-    public ColorDescriptor getDescriptor() {
-      return myDescriptor;
-    }
-  }
-
-  private class MyColorChooserDialog extends DialogWrapper {
-    private JColorChooser myColorChooser;
-    private MyDescriptorChooserPanel mySwingChooserPanel;
-    private MyDescriptorChooserPanel mySystemChooserPanel;
-    private MyDescriptorChooserPanel myAWTChooserPanel;
-
-    public MyColorChooserDialog(Project project) {
-      super(project, false);
-      setTitle(UIDesignerBundle.message("color.chooser.title", myPropertyName));
-      init();
-    }
-
-    protected JComponent createCenterPanel() {
-      myColorChooser = new JColorChooser();
-      mySwingChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.swing.palette"), collectSwingColorDescriptors());
-      myColorChooser.addChooserPanel(mySwingChooserPanel);
-      mySystemChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.system.palette"),
-                                                          collectColorFields(SystemColor.class, true));
-      myColorChooser.addChooserPanel(mySystemChooserPanel);
-      myAWTChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.awt.palette"),
-                                                       collectColorFields(Color.class, false));
-      myColorChooser.addChooserPanel(myAWTChooserPanel);
-      return myColorChooser;
-    }
-
-    private void selectTabForColor(@Nullable final ColorDescriptor value) {
-      String tabName;
-
-      if (value == null || value.getSwingColor() != null) {
-        tabName = mySwingChooserPanel.getDisplayName();
-      }
-      else if (value.getSystemColor() != null) {
-        tabName = mySystemChooserPanel.getDisplayName();
-      }
-      else if (value.getAWTColor() != null) {
-        tabName = myAWTChooserPanel.getDisplayName();
-      }
-      else {
-        return;
-      }
-
-      final ColorChooserUI ui = myColorChooser.getUI();
-      try {
-        final Field field = ui.getClass().getDeclaredField("tabbedPane");
-        field.setAccessible(true);
-        JTabbedPane tabbedPane = (JTabbedPane) field.get(ui);
-        for(int i=0; i<tabbedPane.getTabCount(); i++) {
-          if (tabbedPane.getTitleAt(i).equals(tabName)) {
-            tabbedPane.setSelectedIndex(i);
-            break;
-          }
-        }
-      }
-      catch (NoSuchFieldException e) {
-        // ignore
-      }
-      catch (IllegalAccessException e) {
-        // ignore
-      }
-    }
-
-    private List<ColorDescriptor> collectSwingColorDescriptors() {
-      ArrayList<ColorDescriptor> result = new ArrayList<ColorDescriptor>();
-      UIDefaults defaults = UIManager.getDefaults();
-      Enumeration e = defaults.keys ();
-      while(e.hasMoreElements()) {
-        Object key = e.nextElement();
-        Object value = defaults.get(key);
-        if (key instanceof String && value instanceof Color) {
-          result.add(ColorDescriptor.fromSwingColor((String) key));
-        }
-      }
-      return result;
-    }
-
-    private List<ColorDescriptor> collectColorFields(final Class aClass, final boolean isSystem) {
-      ArrayList<ColorDescriptor> result = new ArrayList<ColorDescriptor>();
-      Field[] colorFields = aClass.getDeclaredFields();
-      for(Field field: colorFields) {
-        if ((field.getModifiers() & Modifier.STATIC) != 0 &&
-            Color.class.isAssignableFrom(field.getType()) &&
-            Character.isLowerCase(field.getName().charAt(0))) {
-          final ColorDescriptor color = isSystem
-                                        ? ColorDescriptor.fromSystemColor(field.getName())
-                                        : ColorDescriptor.fromAWTColor(field.getName());
-          result.add(color);
-        }
-      }
-      return result;
-    }
-
-    public void setSelectedValue(@NotNull final ColorDescriptor value) {
-      myColorChooser.setColor(new ColorDescriptorWrapper(value));
-      selectTabForColor(value);
-    }
-
-    public ColorDescriptor getSelectedValue() {
-      final Color color = myColorChooser.getColor();
-      if (color instanceof ColorDescriptorWrapper) {
-        return ((ColorDescriptorWrapper) color).getDescriptor();
-      }
-      return new ColorDescriptor(color);
-    }
-  }
-
-  private static class MyDescriptorChooserPanel extends AbstractColorChooserPanel {
-    private final String myDisplayName;
-    private final ColorDescriptor[] myColorDescriptors;
-    private JList myDescriptorList;
-
-    public MyDescriptorChooserPanel(final String displayName, List<ColorDescriptor> colorDescriptorList) {
-      myDisplayName = displayName;
-
-      Collections.sort(colorDescriptorList, new Comparator<ColorDescriptor>() {
-        public int compare(final ColorDescriptor o1, final ColorDescriptor o2) {
-          return o1.toString().compareTo(o2.toString());
-        }
-      });
-
-      myColorDescriptors = colorDescriptorList.toArray(new ColorDescriptor[colorDescriptorList.size()]);
-    }
-
-    public void updateChooser() {
-      myDescriptorList.setSelectedValue(getColorFromModel(), true);
-    }
-
-    protected void buildChooser() {
-      setLayout(new BorderLayout());
-      myDescriptorList = new JBList(myColorDescriptors);
-      myDescriptorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-      myDescriptorList.setVisibleRowCount(15);
-      myDescriptorList.setCellRenderer(new ColorRenderer());
-      myDescriptorList.addListSelectionListener(new ListSelectionListener() {
-        public void valueChanged(ListSelectionEvent e) {
-          ColorDescriptor descriptor = (ColorDescriptor)myDescriptorList.getSelectedValue();
-          getColorSelectionModel().setSelectedColor(new ColorDescriptorWrapper(descriptor));
-        }
-      });
-      new ListSpeedSearch(myDescriptorList);
-      add(ScrollPaneFactory.createScrollPane(myDescriptorList), BorderLayout.CENTER);
-    }
-
-    public String getDisplayName() {
-      return myDisplayName;
-    }
-
-    @Nullable
-    public Icon getSmallDisplayIcon() {
-      return null;
-    }
-
-    @Nullable
-    public Icon getLargeDisplayIcon() {
-      return null;
-    }
-  }
 }
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
index 0313fb4..dc8c737 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
@@ -20,14 +20,17 @@
 import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.components.*;
-import com.intellij.openapi.options.*;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ShowSettingsUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiFile;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 
-public class FileAssociationsConfigurable implements SearchableConfigurable, NonDefaultProjectConfigurable, Configurable.NoScroll {
+public class FileAssociationsConfigurable implements SearchableConfigurable, Configurable.NoScroll {
     private final Project myProject;
     private final UIState myState;
     private AssociationsEditor myEditor;
@@ -37,17 +40,21 @@
         myState = ServiceManager.getService(project, UIState.class);
     }
 
+    @Override
     public String getDisplayName() {
         return "XSLT File Associations";
     }
 
+  @Override
   @NotNull
     public String getHelpTopic() {
         return "xslt.associations";
     }
 
+    @Override
     public JComponent createComponent() {
         myEditor = new ReadAction<AssociationsEditor>() {
+            @Override
             protected void run(Result<AssociationsEditor> result) throws Throwable {
                 result.setResult(new AssociationsEditor(myProject, myState.state));
             }
@@ -55,19 +62,23 @@
         return myEditor.getComponent();
     }
 
+    @Override
     public synchronized boolean isModified() {
         return myEditor != null && myEditor.isModified();
     }
 
+    @Override
     public void apply() throws ConfigurationException {
         myEditor.apply();
         DaemonCodeAnalyzer.getInstance(myProject).restart();
     }
 
+    @Override
     public void reset() {
         myEditor.reset();
     }
 
+    @Override
     public synchronized void disposeUIResources() {
         if (myEditor != null) {
             myState.state = myEditor.getState();
@@ -84,6 +95,7 @@
         final FileAssociationsConfigurable instance = new FileAssociationsConfigurable(project);
 
         ShowSettingsUtil.getInstance().editConfigurable(project, instance, new Runnable() {
+            @Override
             public void run() {
                 final AssociationsEditor editor = instance.getEditor();
                 if (file != null) {
@@ -99,20 +111,24 @@
     public static class UIState implements PersistentStateComponent<TreeState> {
         private TreeState state;
 
+        @Override
         public TreeState getState() {
             return state != null ? state : new TreeState();
         }
 
+        @Override
         public void loadState(TreeState state) {
             this.state = state;
         }
     }
 
+    @Override
     @NotNull
     public String getId() {
         return getHelpTopic();
     }
 
+    @Override
     public Runnable enableSearch(final String option) {
         return null;
     }
diff --git a/python/IntelliLang-python/IntelliLang-python.iml b/python/IntelliLang-python/IntelliLang-python.iml
index a877c73..49ab883 100644
--- a/python/IntelliLang-python/IntelliLang-python.iml
+++ b/python/IntelliLang-python/IntelliLang-python.iml
@@ -4,6 +4,7 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
diff --git a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml b/python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml
similarity index 91%
rename from python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
rename to python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml
index 44bab2c..c96f0b7 100644
--- a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
+++ b/python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml
@@ -3,7 +3,7 @@
 <idea-plugin version="2">
   <extensions defaultExtensionNs="org.intellij.intelliLang">
     <languageSupport implementation="com.jetbrains.python.intelliLang.PyLanguageInjectionSupport"/>
-    <injectionConfig config="pyInjections.xml"/>
+    <injectionConfig config="resources/pyInjections.xml"/>
   </extensions>
   <extensions defaultExtensionNs="com.intellij">
     <patterns.patternClass className="com.jetbrains.python.patterns.PythonPatterns" alias="py"/>
diff --git a/python/IntelliLang-python/resources/META-INF/plugin.xml b/python/IntelliLang-python/resources/META-INF/plugin.xml
new file mode 100644
index 0000000..6b2717a
--- /dev/null
+++ b/python/IntelliLang-python/resources/META-INF/plugin.xml
@@ -0,0 +1,16 @@
+<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
+  <name>Python IntelliLang</name>
+  <id>org.jetbrains.plugins.python-intelliLang</id>
+  <version>VERSION</version>
+  <description>This plugin enables language injections</description>
+  <vendor>JetBrains</vendor>
+
+  <depends>com.intellij.modules.python</depends>
+  <depends>org.intellij.intelliLang</depends>
+
+  <xi:include href="/META-INF/intellilang-python-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+  <extensions defaultExtensionNs="com.intellij">
+    <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
+  </extensions>
+</idea-plugin>
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
index dee16d2..7076878 100644
--- a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
@@ -58,6 +58,6 @@
   @Nullable
   @Override
   public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
-    return null;
+    return super.findCommentInjection(host, commentRef);
   }
 }
diff --git a/python/IntelliLang-python/src/pyInjections.xml b/python/IntelliLang-python/src/resources/pyInjections.xml
similarity index 100%
rename from python/IntelliLang-python/src/pyInjections.xml
rename to python/IntelliLang-python/src/resources/pyInjections.xml
diff --git a/python/build/paths.nsi b/python/build/paths.nsi
index cf4f769..6baf096 100644
--- a/python/build/paths.nsi
+++ b/python/build/paths.nsi
@@ -2,5 +2,5 @@
 !define IMAGES_LOCATION ${COMMUNITY_DIR}\python\build\resources
 ;!define LICENSE_FILE ${BASE_DIR}\python\license\PyCharm_Preview_License
 !define PRODUCT_PROPERTIES_FILE ${BASE_DIR}\out\pycharmCE\layout\bin\idea.properties
-!define PRODUCT_VM_OPTIONS_NAME pycharm.exe.vmoptions
+!define PRODUCT_VM_OPTIONS_NAME pycharm*.exe.vmoptions
 !define PRODUCT_VM_OPTIONS_FILE ${BASE_DIR}\out\pycharmCE\win\bin\${PRODUCT_VM_OPTIONS_NAME}
diff --git a/python/build/pycharm64_community_launcher.properties b/python/build/pycharm64_community_launcher.properties
new file mode 100644
index 0000000..ff7b0ff
--- /dev/null
+++ b/python/build/pycharm64_community_launcher.properties
@@ -0,0 +1,3 @@
+IDS_JDK_ENV_VAR=PYCHARM_JDK_64
+IDS_JDK_ONLY=true
+IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmCore -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant
index 3b793ec..cfaaf33 100644
--- a/python/build/pycharm_community_build.gant
+++ b/python/build/pycharm_community_build.gant
@@ -162,11 +162,14 @@
   ant.echo(message: "PC-${buildNumber}", file: "${paths.distAll}/build.txt")
 
   def launcher = "${paths.distWin}/bin/pycharm.exe"
+  def launcher64 = "${paths.distWin}/bin/pycharm64.exe"
   List resourcePaths = ["$ch/community-resources/src",
     "$ch/platform/icons/src",
     "$pythonCommunityHome/resources"]
   buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
                    appInfo, "$pythonCommunityHome/build/pycharm_community_launcher.properties", system_selector, resourcePaths)
+  buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher64.exe", launcher64,
+                   appInfo, "$pythonCommunityHome/build/pycharm64_community_launcher.properties", system_selector, resourcePaths)
 
   buildWinZip("${paths.artifacts}/pycharmPC-${buildNumber}.zip", [paths.distAll, paths.distWin])
 
@@ -328,8 +331,7 @@
   }
 
   winScripts(target, ch, "pycharm.bat", args)
-  winVMOptions(target, null, "pycharm.exe")
-
+  winVMOptions(target, null, "pycharm.exe", "pycharm64.exe")
   ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
 }
 
diff --git a/python/edu/build/DMG_background.png b/python/edu/build/DMG_background.png
new file mode 100644
index 0000000..3b5a4b2
--- /dev/null
+++ b/python/edu/build/DMG_background.png
Binary files differ
diff --git a/python/edu/build/build.xml b/python/edu/build/build.xml
new file mode 100644
index 0000000..913237c
--- /dev/null
+++ b/python/edu/build/build.xml
@@ -0,0 +1,46 @@
+<project name="PyCharm Educational Edition" default="all">
+  <property name="project.home" value="${basedir}/../../.."/>
+  <property name="python.home" value="${basedir}"/>
+  <property name="out.dir" value="${project.home}/out"/>
+  <property name="tmp.dir" value="${project.home}/out/tmp"/>
+
+  <target name="cleanup">
+    <delete dir="${out.dir}" failonerror="false"/>
+  </target>
+
+  <target name="init">
+    <mkdir dir="${out.dir}"/>
+    <mkdir dir="${tmp.dir}"/>
+  </target>
+
+  <macrodef name="call_gant">
+    <attribute name="script" />
+    <sequential>
+      <java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
+        <jvmarg line="-Xmx612m -XX:MaxPermSize=152m -Didea.build.number=${idea.build.number} &quot;-DideaPath=${idea.path}&quot;"/>
+        <sysproperty key="java.awt.headless" value="true"/>
+        <arg line="&quot;-Dgant.script=@{script}&quot;"/>
+        <arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
+        <arg line="&quot;-Didea.build.number=${idea.build.number}&quot;"/>
+        <arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
+        <arg value="-f"/>
+        <arg value="${project.home}/build/gant.xml"/>
+      </java>
+    </sequential>
+  </macrodef>
+
+  <target name="build" depends="init">
+    <call_gant script="${python.home}/pycharm_edu_build.gant"/>
+  </target>
+
+  <!--<target name="plugin" depends="init">-->
+    <!--<call_gant script="${python.home}/build/python_plugin_build.gant"/>-->
+  <!--</target>-->
+  <!--
+  <target name="test" depends="init">
+    <call_gant script="${project.home}/build/scripts/tests.gant"/>
+  </target>
+  -->
+
+  <target name="all" depends="cleanup,build"/>
+</project>
diff --git a/python/edu/build/paths.nsi b/python/edu/build/paths.nsi
new file mode 100644
index 0000000..910f2b3
--- /dev/null
+++ b/python/edu/build/paths.nsi
@@ -0,0 +1,6 @@
+; Installer images
+!define IMAGES_LOCATION ${COMMUNITY_DIR}\python\build\resources
+;!define LICENSE_FILE ${BASE_DIR}\python\license\PyCharm_Preview_License
+!define PRODUCT_PROPERTIES_FILE ${BASE_DIR}\out\pycharmEDU\layout\bin\idea.properties
+!define PRODUCT_VM_OPTIONS_NAME pycharm.exe.vmoptions
+!define PRODUCT_VM_OPTIONS_FILE ${BASE_DIR}\out\pycharmEDU\win\bin\${PRODUCT_VM_OPTIONS_NAME}
diff --git a/python/edu/build/plugin-list.txt b/python/edu/build/plugin-list.txt
new file mode 100644
index 0000000..ceaa608
--- /dev/null
+++ b/python/edu/build/plugin-list.txt
@@ -0,0 +1,11 @@
+svn4idea
+git4idea
+remote-servers-git
+github
+terminal
+IntelliLang
+IntelliLang-xml
+IntelliLang-js
+IntelliLang-python
+rest
+python-rest
diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant
new file mode 100644
index 0000000..8c857c1
--- /dev/null
+++ b/python/edu/build/pycharm_edu_build.gant
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ */
+import org.jetbrains.jps.LayoutInfo
+
+import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
+
+setProperty("home", guessHome(this as Script))
+
+includeTargets << new File("${guessHome(this as Script)}/build/scripts/utils.gant")
+// signMacZip locates in ultimate_utils.gant
+ includeTargets << new File("${guessHome(this)}/ultimate/build/scripts/ultimate_utils.gant")
+includeTargets << new File("${guessHome(this)}/build/scripts/libLicenses.gant")
+
+requireProperty("buildNumber", requireProperty("build.number", snapshot))
+
+setProperty("ch", "$home")
+setProperty("pythonCommunityHome", "$ch/python")
+setProperty("pythonEduHome", "$ch/python/edu")
+
+// load ApplicationInfo.xml properties
+ant.xmlproperty(file: "$pythonEduHome/resources/idea/PyCharmEduApplicationInfo.xml", collapseAttributes: "true")
+
+setProperty("system_selector", "PyCharm${p("component.version.major")}0")
+setProperty("dryRun", false)
+setProperty("jdk16", guessJdk())
+
+//modules to compile
+setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
+
+private List<String> pycharmPlatformApiModules() {
+  return [platformApiModules, "dom-openapi"].flatten()
+}
+
+
+private List pycharmImplementationModules() {   //modules to put into pycharm.jar
+  return [platformImplementationModules, "dom-impl", "python-community", "python-ide-community", "python-educational", "python-openapi", "python-psi-api",
+    "platform-main"].flatten()
+}
+
+private List modules() {
+  return [
+    "python-pydev", "colorSchemes", pycharmPlatformApiModules(), pycharmImplementationModules(), pluginFilter
+  ].flatten()
+}
+
+private List approvedJars() {
+  def normalizedHome = ch.replace('\\', '/')
+  def normalizedPythonHome = pythonCommunityHome.replace('\\', '/')
+  return ["$normalizedHome/lib/", "$normalizedPythonHome/lib/", "$normalizedHome/xml/relaxng/lib/"]
+}
+
+class Paths {
+  final sandbox
+  final distAll
+  final distWin
+  final distMac
+  final distUnix
+  final artifacts
+  final ideaSystem
+  final ideaConfig
+
+  def Paths(String home) {
+    sandbox = "$home/out/pycharmEDU"
+
+    distAll = "$sandbox/layout"
+    distWin = "$sandbox/win"
+    distMac = "$sandbox/mac"
+    distUnix = "$sandbox/unix"
+    artifacts = "$sandbox/artifacts"
+
+    ideaSystem = "$sandbox/system"
+    ideaConfig = "$sandbox/config"
+  }
+}
+
+setProperty("paths", new Paths(home))
+setProperty("buildName", "PE-$buildNumber")
+
+target('default': "Build artifacts") {
+
+  loadProject()
+
+  projectBuilder.stage("Cleaning up sandbox folder")
+
+  projectBuilder.targetFolder = "${paths.sandbox}/classes"
+  projectBuilder.dryRun = dryRun
+
+  if (!dryRun) {
+    forceDelete(paths.sandbox)
+    ant.mkdir(dir: paths.sandbox)
+  }
+
+  ant.tstamp() {
+    format(property: "todayYear", pattern: "yyyy")
+  }
+
+  ant.patternset(id: "resources.included") {
+    include(name: "**/*.properties")
+    include(name: "fileTemplates/**/*")
+    include(name: "inspectionDescriptions/**/*")
+    include(name: "intentionDescriptions/**/*")
+    include(name: "tips/**/*")
+    include(name: "search/**/*")
+  }
+
+  ant.patternset(id: "resources.excluded") {
+    exclude(name: "**/*.properties")
+    exclude(name: "fileTemplates/**/*")
+    exclude(name: "fileTemplates")
+    exclude(name: "inspectionDescriptions/**/*")
+    exclude(name: "inspectionDescriptions")
+    exclude(name: "intentionDescriptions/**/*")
+    exclude(name: "intentionDescriptions")
+    exclude(name: "tips/**/*")
+    exclude(name: "tips")
+  }
+
+  zipSources(home, paths.artifacts)
+
+  def usedJars = buildModulesAndCollectUsedJars(modules(), approvedJars(), ["/ant/"])
+
+  layoutEducational("${paths.sandbox}/classes/production", usedJars)
+
+
+  //buildNSIS([paths.distAll, paths.distWin],
+  //          "${pythonEduHome}/build/strings.nsi", "${pythonEduHome}/build/paths.nsi",
+  //          "pycharm", false, true, ".py", system_selector)
+
+  def extraArgs = ["build.code": "pycharmEDU-${buildNumber}", "build.number": "PE-$buildNumber", "artifacts.path": "${paths.artifacts}"]
+  signMacZip("pycharm", extraArgs)
+  buildDmg("pycharm", "${pythonEduHome}/build/DMG_background.png", extraArgs)
+
+}
+
+public layoutEducational(String classesPath, Set usedJars) {
+  setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
+
+  if (usedJars == null) {
+    usedJars = collectUsedJars(modules(), approvedJars(), ["/ant/"], null)
+  }
+
+  def appInfo = appInfoFile(classesPath)
+  def paths = new Paths(home)
+  buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], {
+    projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_edu"), false).each {
+      ant.pathelement(location: it)
+    }
+  }, "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true")
+
+  if (!dryRun) {
+    wireBuildDate("PE-${buildNumber}", appInfo)
+  }
+
+  Map args = [
+    buildNumber: "PE-${buildNumber}",
+    system_selector: system_selector,
+    ide_jvm_args: "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true"]
+
+  LayoutInfo layoutInfo = layoutFull(args, paths.distAll, usedJars)
+  generateLicensesTable("$paths.artifacts/third-party-libraries.txt", layoutInfo.usedModules);
+
+  layoutWin(args, paths.distWin)
+  layoutUnix(args, paths.distUnix)
+  layoutMac(args, paths.distMac)
+
+  ant.echo(message: "PE-${buildNumber}", file: "${paths.distAll}/build.txt")
+
+  def launcher = "${paths.distWin}/bin/pycharm.exe"
+  List resourcePaths = ["$ch/community-resources/src",
+    "$ch/platform/icons/src",
+    "$pythonEduHome/resources"]
+  buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
+                   appInfo, "$pythonEduHome/build/pycharm_edu_launcher.properties", system_selector, resourcePaths)
+
+  buildWinZip("${paths.artifacts}/pycharmPE-${buildNumber}.zip", [paths.distAll, paths.distWin])
+
+  String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}"
+  buildTarGz(tarRoot, "$paths.artifacts/pycharmPE-${buildNumber}.tar", [paths.distAll, paths.distUnix])
+
+  String macAppRoot = isEap() ? "PyCharm EDU ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm EDU.app/Contents"
+  buildMacZip(macAppRoot, "${paths.artifacts}/pycharmEDU-${buildNumber}.sit", [paths.distAll], paths.distMac)
+}
+
+private layoutPlugins(layouts) {
+  dir("plugins") {
+    layouts.layoutPlugin("rest")
+    layouts.layoutPlugin("python-rest")
+  }
+
+  layouts.layoutCommunityPlugins(ch)
+}
+
+private String appInfoFile(String classesPath) {
+  return "$classesPath/python-educational/idea/PyCharmEduApplicationInfo.xml"
+}
+
+private layoutFull(Map args, String target, Set usedJars) {
+  def openapiModules = pycharmPlatformApiModules()
+  def superLayouts = includeFile("$ch/build/scripts/layouts.gant")
+
+  reassignAltClickToMultipleCarets("$ch")
+  
+  def result = layout(target) {
+    dir("lib") {
+      jar("util.jar") {
+        module("util")
+        module("util-rt")
+      }
+
+      jar("openapi.jar") {
+        openapiModules.each { module it }
+      }
+
+      jar("annotations.jar") { module("annotations") }
+      jar("extensions.jar") { module("extensions") }
+
+      jar("pycharm.jar") {
+        pycharmImplementationModules().each {
+          module(it) {
+            exclude(name: "**/tips/**")
+          }
+        }
+      }
+
+      jar("pycharm-pydev.jar") {
+        module("python-pydev")
+      }
+
+      jar("bootstrap.jar") { module("bootstrap") }
+      jar("resources.jar") {
+        module("platform-resources")
+        module("colorSchemes")
+      }
+
+      jar("forms_rt.jar") {
+        module("forms_rt")
+      }
+
+      //noinspection GroovyAssignabilityCheck
+      jar([name: "resources_en.jar", duplicate: "preserve"]) {
+        // custom resources should go first
+        fileset(dir: "$pythonCommunityHome/resources") {
+          include(name: "**/tips/**")
+        }
+        module("platform-resources-en") {
+          ant.patternset {
+            exclude(name: "tips/images/switcher.png")
+            exclude(name: "tips/images/navigateToFilePath.gif")
+          }
+        }
+      }
+
+      jar("icons.jar") { module("icons") }
+      jar("boot.jar") { module("boot") }
+
+      usedJars.each {
+        fileset(file: it)
+      }
+
+      dir("libpty") {
+        fileset(dir: "$ch/lib/libpty") {
+          exclude(name: "*.txt")
+        }
+      }
+
+      dir("ext") {
+        fileset(dir: "$ch/lib") {
+          include(name: "cglib*.jar")
+        }
+      }
+
+      dir("src") {
+        fileset(dir: "$ch/lib/src") {
+          include(name: "trove4j_changes.txt")
+          include(name: "trove4j_src.jar")
+        }
+
+        jar("pycharm-pydev-src.zip") {
+          fileset(dir: "$pythonCommunityHome/pydevSrc")
+        }
+        jar("pycharm-openapi-src.zip") {
+          fileset(dir: "$pythonCommunityHome/openapi/src")
+          fileset(dir: "$pythonCommunityHome/psi-api/src")
+        }
+      }
+    }
+
+    dir("help") {
+      fileset(dir: "$home/python/help") {
+        include(name: "*.pdf")
+      }
+    }
+
+    dir("helpers") {
+      fileset(dir: "$pythonCommunityHome/helpers")
+    }
+
+    dir("license") {
+      fileset(dir: "$ch/license")
+      fileset(dir: "$ch") {
+        include(name: "LICENSE.txt")
+        include(name: "NOTICE.txt")
+      }
+    }
+
+    layoutPlugins(superLayouts)
+
+    dir("bin") {
+      fileset(dir: "$ch/bin") {
+        exclude(name: "appletviewer.policy")
+        include(name: "*.*")
+      }
+    }
+  }
+  patchPropertiesFile(target, args + [appendices: ["$home/build/conf/ideaJNC.properties"]])
+  return result
+}
+
+private layoutWin(Map args, String target) {
+  layout(target) {
+    dir("bin") {
+      fileset(dir: "$ch/bin/win") {
+        exclude(name: "breakgen*")
+      }
+    }
+
+    dir("skeletons") {
+      fileset(dir: "$pythonCommunityHome/skeletons") {
+        include(name: "skeletons-win*.zip")
+      }
+    }
+  }
+
+  winScripts(target, ch, "pycharm.bat", args)
+  winVMOptions(target, null, "pycharm.exe")
+
+  ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
+}
+
+private layoutUnix(Map args, String target) {
+  layout(target) {
+    dir("bin") {
+      fileset(dir: "$ch/bin/linux") {
+        exclude(name: "libbreakgen*")
+      }
+    }
+  }
+
+  ant.copy(file: "$pythonCommunityHome/resources/PyCharmCore128.png", tofile: "$target/bin/pycharm.png")
+
+  unixScripts(target, ch, "pycharm.sh", args)
+  unixVMOptions(target, "pycharm")
+
+  ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
+}
+
+private layoutMac(Map _args, String target) {
+  layout(target) {
+    dir("bin") {
+      fileset(dir: "$home/bin") {
+        include(name: "*.jnilib")
+      }
+    }
+
+    dir("skeletons") {
+      fileset(dir: "$pythonCommunityHome/skeletons") {
+        include(name: "skeletons-mac*.zip")
+      }
+    }
+  }
+
+  Map args = new HashMap(_args)
+  args.icns = "$pythonCommunityHome/resources/PyCharmCore.icns"
+  args.bundleIdentifier = "com.jetbrains.pycharm"
+  args.platform_prefix = "PyCharmEdu"
+  args.help_id = "PY"
+  args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
+  args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"];
+  layoutMacApp(target, ch, args)
+}
diff --git a/python/edu/build/pycharm_edu_launcher.properties b/python/edu/build/pycharm_edu_launcher.properties
new file mode 100644
index 0000000..d355468
--- /dev/null
+++ b/python/edu/build/pycharm_edu_launcher.properties
@@ -0,0 +1,3 @@
+IDS_JDK_ENV_VAR=PYCHARM_JDK
+IDS_JDK_ONLY=false
+IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
diff --git a/python/edu/build/python-edu-build.iml b/python/edu/build/python-edu-build.iml
new file mode 100644
index 0000000..bda1778
--- /dev/null
+++ b/python/edu/build/python-edu-build.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Groovy" level="project" />
+    <orderEntry type="module" module-name="jps-standalone-builder" />
+  </component>
+</module>
+
diff --git a/python/edu/build/resources/PC_instCom.ico b/python/edu/build/resources/PC_instCom.ico
new file mode 100644
index 0000000..44ecec9
--- /dev/null
+++ b/python/edu/build/resources/PC_instCom.ico
Binary files differ
diff --git a/python/edu/build/resources/PC_uninstCom.ico b/python/edu/build/resources/PC_uninstCom.ico
new file mode 100644
index 0000000..13e9f96
--- /dev/null
+++ b/python/edu/build/resources/PC_uninstCom.ico
Binary files differ
diff --git a/python/edu/build/resources/headerlogo.bmp b/python/edu/build/resources/headerlogo.bmp
new file mode 100644
index 0000000..c060992
--- /dev/null
+++ b/python/edu/build/resources/headerlogo.bmp
Binary files differ
diff --git a/python/edu/build/resources/logo.bmp b/python/edu/build/resources/logo.bmp
new file mode 100644
index 0000000..0f0f82d
--- /dev/null
+++ b/python/edu/build/resources/logo.bmp
Binary files differ
diff --git a/python/edu/build/resources/pycharm_inst.ico b/python/edu/build/resources/pycharm_inst.ico
new file mode 100644
index 0000000..6c75bcd
--- /dev/null
+++ b/python/edu/build/resources/pycharm_inst.ico
Binary files differ
diff --git a/python/edu/build/resources/pycharm_uninst.ico b/python/edu/build/resources/pycharm_uninst.ico
new file mode 100644
index 0000000..a5b9ad8
--- /dev/null
+++ b/python/edu/build/resources/pycharm_uninst.ico
Binary files differ
diff --git a/python/edu/build/strings.nsi b/python/edu/build/strings.nsi
new file mode 100644
index 0000000..fa10d42
--- /dev/null
+++ b/python/edu/build/strings.nsi
@@ -0,0 +1,13 @@
+!define MANUFACTURER "JetBrains"
+!define MUI_PRODUCT  "PyCharm Educational Edition"
+!define PRODUCT_FULL_NAME "JetBrains PyCharm Educational Edition"
+!define PRODUCT_EXE_FILE "pycharm.exe"
+!define PRODUCT_ICON_FILE "PC_instCom.ico"
+!define PRODUCT_UNINST_ICON_FILE "PC_uninstCom.ico"
+!define PRODUCT_LOGO_FILE "logo.bmp"
+!define PRODUCT_HEADER_FILE "headerlogo.bmp"
+
+; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered PyCharm build has been installed
+; set to 1 for release build
+!define SHOULD_SET_DEFAULT_INSTDIR "0"
+
diff --git a/python/edu/main_pycharm_edu.iml b/python/edu/main_pycharm_edu.iml
new file mode 100644
index 0000000..2acdd87
--- /dev/null
+++ b/python/edu/main_pycharm_edu.iml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="bootstrap" />
+    <orderEntry type="module" module-name="colorSchemes" />
+    <orderEntry type="module" module-name="svn4idea" />
+    <orderEntry type="module" module-name="git4idea" />
+    <orderEntry type="module" module-name="relaxng" />
+    <orderEntry type="module" module-name="rest" />
+    <orderEntry type="module" module-name="python-helpers" />
+    <orderEntry type="module" module-name="terminal" />
+    <orderEntry type="module" module-name="python-ide-community" />
+    <orderEntry type="module" module-name="platform-main" />
+    <orderEntry type="module" module-name="ShortcutPromoter" />
+    <orderEntry type="module" module-name="python-educational" />
+  </component>
+</module>
+
diff --git a/python/edu/python-educational.iml b/python/edu/python-educational.iml
new file mode 100644
index 0000000..92439c4
--- /dev/null
+++ b/python/edu/python-educational.iml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="python-openapi" exported="" />
+    <orderEntry type="module" module-name="platform-impl" />
+    <orderEntry type="module" module-name="lang-impl" />
+    <orderEntry type="library" name="Guava" level="project" />
+    <orderEntry type="module" module-name="python-pydev" />
+    <orderEntry type="library" exported="" name="XmlRPC" level="project" />
+    <orderEntry type="module" module-name="xdebugger-api" />
+    <orderEntry type="library" name="http-client-3.1" level="project" />
+    <orderEntry type="module" module-name="RegExpSupport" exported="" />
+    <orderEntry type="module" module-name="testRunner" />
+    <orderEntry type="module" module-name="smRunner" />
+    <orderEntry type="module" module-name="spellchecker" />
+    <orderEntry type="module" module-name="xdebugger-impl" />
+    <orderEntry type="module" module-name="xml-psi-impl" />
+    <orderEntry type="module" module-name="python-community" />
+  </component>
+</module>
+
diff --git a/python/edu/resources/idea/PyCharmEduApplicationInfo.xml b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
new file mode 100644
index 0000000..46695ef
--- /dev/null
+++ b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
@@ -0,0 +1,23 @@
+<component>
+  <company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
+  <version major="3" minor="0" eap="true"/>
+  <build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
+  <logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
+  <about url="/pycharm_core_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="ffffff" linkColor="fca11a"/>
+  <icon size32="/PyCharmCore32.png" size16="/PyCharmCore16.png" size32opaque="/PyCharmCore32.png" size12="/PyCharmCore13.png" ico="PyCharmCore.ico"/>
+  <package code="__PACKAGE_CODE__"/>
+  <names product="PyCharm" fullname="PyCharm Educational Edition" script="charm"/>
+  <install-over minbuild="0" maxbuild="0" version="1.x"/>
+
+  <welcome-screen logo-url="/PyCharmCoreWelcomeScreen.png" caption-url="PyCharmCoreWelcomeCaption.png" slogan-url="/developSlogan.png"/>
+
+  <third-party url="http://confluence.jetbrains.com/display/PYH/Third-Party+Software+Used+by+PyCharm"/>
+
+  <update-urls logo-url="/Logo_welcomeScreen.png"
+               check="http://www.jetbrains.com/updates/updates.xml"
+               patches="http://download.jetbrains.com/python/"/>
+
+  <feedback eap-url="http://www.jetbrains.com/feedback/feedback.jsp?product=PyCharm&amp;build=$BUILD&amp;timezone=$TIMEZONE&amp;eval=$EVAL"
+            release-url="http://www.jetbrains.com/feedback/feedback.jsp?product=PyCharm&amp;build=$BUILD&amp;timezone=$TIMEZONE&amp;eval=$EVAL"/>
+  <help file="pycharmhelp.jar" root="pycharm"/>
+</component>
diff --git a/python/edu/src/META-INF/PyCharmEduPlugin.xml b/python/edu/src/META-INF/PyCharmEduPlugin.xml
new file mode 100644
index 0000000..9adf03d
--- /dev/null
+++ b/python/edu/src/META-INF/PyCharmEduPlugin.xml
@@ -0,0 +1,36 @@
+<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
+  <!-- Components and extensions declared in this file work ONLY in Pycharm Educational Edition -->
+
+  <application-components>
+    <component>
+      <implementation-class>com.jetbrains.python.edu.PyCharmEduInitialConfigurator$First</implementation-class>
+      <headless-implementation-class/>
+    </component>
+  </application-components>
+
+  <xi:include href="/META-INF/pycharm-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+  <xi:include href="/META-INF/python-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+
+  <actions>
+    <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="ToolsMenu"/>
+
+    <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="PrintExportGroup"/>
+    <group overrides="true" id="FileMainSettingsGroup">
+      <reference id="ShowSettings"/>
+      <separator/>
+      <reference id="ExportImportGroup"/>
+    </group>
+
+    <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="EditBookmarksGroup"/>
+    <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="AddToFavorites"/>
+    <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="AddAllToFavorites"/>
+    <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="AddToFavoritesPopup"/>
+    <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="RemoveFromFavorites"/>
+
+    <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="NewHtmlFile"/>
+
+
+  </actions>
+</idea-plugin>
diff --git a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
new file mode 100644
index 0000000..451c519
--- /dev/null
+++ b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2000-2013 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.jetbrains.python.edu;
+
+import com.intellij.application.options.InitialConfigurationDialog;
+import com.intellij.codeInsight.CodeInsightSettings;
+import com.intellij.codeInsight.intention.IntentionActionBean;
+import com.intellij.codeInsight.intention.IntentionManager;
+import com.intellij.ide.AppLifecycleListener;
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.RecentProjectsManagerBase;
+import com.intellij.ide.SelectInTarget;
+import com.intellij.ide.ui.UISettings;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.ide.util.TipDialog;
+import com.intellij.notification.EventLog;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.extensions.ExtensionsArea;
+import com.intellij.openapi.fileChooser.impl.FileChooserUtil;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.keymap.Keymap;
+import com.intellij.openapi.keymap.ex.KeymapManagerEx;
+import com.intellij.openapi.keymap.impl.KeymapImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.project.ProjectManagerAdapter;
+import com.intellij.openapi.project.ex.ProjectManagerEx;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.wm.ToolWindowEP;
+import com.intellij.openapi.wm.ToolWindowId;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.platform.DirectoryProjectConfigurator;
+import com.intellij.platform.PlatformProjectViewOpener;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.util.Alarm;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.messages.MessageBus;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UtilityClassWithPublicConstructor"})
+public class PyCharmEduInitialConfigurator {
+  @NonNls private static final String DISPLAYED_PROPERTY = "PyCharm.initialConfigurationShown";
+
+  @NonNls private static final String CONFIGURED = "PyCharm.InitialConfiguration";
+
+
+  public static class First {
+
+    public First() {
+      patchRootAreaExtensions();
+    }
+  }
+
+  /**
+   * @noinspection UnusedParameters
+   */
+  public PyCharmEduInitialConfigurator(MessageBus bus,
+                                       UISettings uiSettings,
+                                       CodeInsightSettings codeInsightSettings,
+                                       final PropertiesComponent propertiesComponent,
+                                       FileTypeManager fileTypeManager,
+                                       final ProjectManagerEx projectManager,
+                                       RecentProjectsManagerBase recentProjectsManager) {
+    if (!propertiesComponent.getBoolean(CONFIGURED, false)) {
+      propertiesComponent.setValue(CONFIGURED, "true");
+      recentProjectsManager.loadState(new RecentProjectsManagerBase.State());
+      propertiesComponent.setValue("toolwindow.stripes.buttons.info.shown", "true");
+      UISettings.getInstance().HIDE_TOOL_STRIPES = false;
+      uiSettings.SHOW_MEMORY_INDICATOR = false;
+      uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true;
+      codeInsightSettings.REFORMAT_ON_PASTE = CodeInsightSettings.NO_REFORMAT;
+
+      EditorSettingsExternalizable.getInstance().setVirtualSpace(false);
+      final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance().getCurrentSettings();
+      settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+      settings.getCommonSettings(PythonLanguage.getInstance()).ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+      UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true;
+      UISettings.getInstance().SHOW_MEMORY_INDICATOR = false;
+      final String ignoredFilesList = fileTypeManager.getIgnoredFilesList();
+      ApplicationManager.getApplication().invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          ApplicationManager.getApplication().runWriteAction(new Runnable() {
+            @Override
+            public void run() {
+              FileTypeManager.getInstance().setIgnoredFilesList(ignoredFilesList + ";*$py.class");
+            }
+          });
+        }
+      });
+      PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = false;
+    }
+    bus.connect().subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
+      @Override
+      public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
+        if (!propertiesComponent.isValueSet(DISPLAYED_PROPERTY)) {
+          GeneralSettings.getInstance().setShowTipsOnStartup(false);
+          showInitialConfigurationDialog();
+          propertiesComponent.setValue(DISPLAYED_PROPERTY, "true");
+        }
+      }
+
+      @Override
+      public void appStarting(Project projectFromCommandLine) {
+        patchKeymap();
+      }
+    });
+    bus.connect().subscribe(ProjectManager.TOPIC, new ProjectManagerAdapter() {
+      @Override
+      public void projectOpened(final Project project) {
+        if (project.isDefault()) return;
+        if (FileChooserUtil.getLastOpenedFile(project) == null) {
+          FileChooserUtil.setLastOpenedFile(project, VfsUtil.getUserHomeDir());
+        }
+
+        patchProjectAreaExtensions(project);
+
+        //StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
+        //  @Override
+        //  public void run() {
+        //    if (project.isDisposed()) return;
+        //
+        //    ToolWindowManager.getInstance(project).invokeLater(new Runnable() {
+        //      int count = 0;
+        //      public void run() {
+        //        if (project.isDisposed()) return;
+        //        if (count ++ < 3) {
+        //          ToolWindowManager.getInstance(project).invokeLater(this);
+        //          return;
+        //        }
+        //        if (!propertiesComponent.isValueSet(INIT_DB_DIALOG_DISPLAYED)) {
+        //          ToolWindow toolWindow = DatabaseView.getDatabaseToolWindow(project);
+        //          if (toolWindow.getType() != ToolWindowType.SLIDING) {
+        //            toolWindow.activate(null);
+        //          }
+        //          propertiesComponent.setValue(INIT_DB_DIALOG_DISPLAYED, "true");
+        //          onFirstProjectOpened(project);
+        //        }
+        //      }
+        //    });
+        //  }
+        //});
+      }
+    });
+  }
+
+  private static void onFirstProjectOpened(@NotNull final Project project) {
+    // show python console
+
+
+    GeneralSettings.getInstance().setShowTipsOnStartup(true);
+
+    // show tips once
+    final Alarm alarm = new Alarm(project);
+    alarm.addRequest(new Runnable() {
+      @Override
+      public void run() {
+        Disposer.dispose(alarm);
+        TipDialog.createForProject(project).show();
+      }
+    }, 2000, ModalityState.NON_MODAL);
+  }
+
+  private static void patchRootAreaExtensions() {
+    ExtensionsArea rootArea = Extensions.getArea(null);
+
+    for (ToolWindowEP ep : Extensions.getExtensions(ToolWindowEP.EP_NAME)) {
+      if (ToolWindowId.FAVORITES_VIEW.equals(ep.id) || ToolWindowId.TODO_VIEW.equals(ep.id) || EventLog.LOG_TOOL_WINDOW_ID.equals(ep.id)) {
+        rootArea.getExtensionPoint(ToolWindowEP.EP_NAME).unregisterExtension(ep);
+      }
+    }
+
+    for (DirectoryProjectConfigurator ep : Extensions.getExtensions(DirectoryProjectConfigurator.EP_NAME)) {
+      if (ep instanceof PlatformProjectViewOpener) {
+        rootArea.getExtensionPoint(DirectoryProjectConfigurator.EP_NAME).unregisterExtension(ep);
+      }
+    }
+
+    for (IntentionActionBean ep : Extensions.getExtensions(IntentionManager.EP_INTENTION_ACTIONS)) {
+      if ("org.intellij.lang.regexp.intention.CheckRegExpIntentionAction".equals(ep.className)) {
+        rootArea.getExtensionPoint(IntentionManager.EP_INTENTION_ACTIONS).unregisterExtension(ep);
+      }
+    }
+  }
+
+  private static void patchProjectAreaExtensions(@NotNull final Project project) {
+    for (SelectInTarget target : Extensions.getExtensions(SelectInTarget.EP_NAME, project)) {
+      if (ToolWindowId.FAVORITES_VIEW.equals(target.getToolWindowId())) {
+        Extensions.getArea(project).getExtensionPoint(SelectInTarget.EP_NAME).unregisterExtension(target);
+      }
+    }
+  }
+
+  private static void patchKeymap() {
+    Set<String> droppedActions = ContainerUtil.newHashSet(
+      "AddToFavoritesPopup", "RemoveFromFavorites",
+      "DatabaseView.ImportDataSources",
+      "CompileDirty", "Compile",
+      // hidden
+      "AddNewFavoritesList", "EditFavorites", "RemoveFromFavorites", "RenameFavoritesList", "RemoveFavoritesList");
+    KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx();
+
+
+    for (Keymap keymap : keymapManager.getAllKeymaps()) {
+      if (keymap.canModify()) continue;
+
+      KeymapImpl keymapImpl = (KeymapImpl)keymap;
+
+      for (String id : keymapImpl.getOwnActionIds()) {
+        if (droppedActions.contains(id)) keymapImpl.clearOwnActionsId(id);
+      }
+    }
+  }
+
+  private static void showInitialConfigurationDialog() {
+    final JFrame frame = WindowManager.getInstance().findVisibleFrame();
+    new InitialConfigurationDialog(frame, "Python").show();
+  }
+}
diff --git a/python/helpers/pycharm/_bdd_utils.py b/python/helpers/pycharm/_bdd_utils.py
new file mode 100644
index 0000000..0c92532
--- /dev/null
+++ b/python/helpers/pycharm/_bdd_utils.py
@@ -0,0 +1,201 @@
+# coding=utf-8
+"""
+Tools for running BDD frameworks in python.
+You probably need to extend BddRunner (see its doc).
+
+You may also need "get_path_by_args" that gets folder (current or passed as first argument)
+"""
+import os
+import time
+import abc
+
+import tcmessages
+
+
+__author__ = 'Ilya.Kazakevich'
+
+
+def get_path_by_args(arguments):
+    """
+    :type arguments list
+    :param arguments: arguments (sys.argv)
+    :return: tuple (base_dir, what_to_run) where dir is current or first argument from argv, checking it exists
+    :rtype tuple of str
+    """
+    what_to_run = arguments[1] if len(arguments) > 1 else "."
+    base_dir = what_to_run
+    assert os.path.exists(what_to_run), "{} does not exist".format(what_to_run)
+
+    if os.path.isfile(what_to_run):
+        base_dir = os.path.dirname(what_to_run) # User may point to the file directly
+    return base_dir, what_to_run
+
+
+class BddRunner(object):
+    """
+    Extends this class, implement abstract methods and use its API to implement new BDD frameworks.
+    Call "run()" to launch it.
+    This class does the following:
+    * Gets features to run (using "_get_features_to_run()") and calculates steps in it
+    * Reports steps to Intellij or TC
+    * Calls "_run_tests()" where *you* should install all hooks you need into your BDD and use "self._" functions
+    to report tests and features. It actually wraps tcmessages but adds some stuff like duration count etc
+    :param base_dir:
+    """
+    __metaclass__ = abc.ABCMeta
+
+    def __init__(self, base_dir):
+        """
+        :type base_dir str
+        :param base_dir base directory of your project
+        """
+        super(BddRunner, self).__init__()
+        self.tc_messages = tcmessages.TeamcityServiceMessages()
+        """
+        tcmessages TeamCity/Intellij test API. See TeamcityServiceMessages
+        """
+        self.__base_dir = base_dir
+        self.__last_test_start_time = None  # TODO: Doc when use
+        self.__last_test_name = None
+
+    def run(self):
+        """"
+        Runs runner. To be called right after constructor.
+        """
+        self.tc_messages.testCount(self._get_number_of_tests())
+        self.tc_messages.testMatrixEntered()
+        self._run_tests()
+
+    def __gen_location(self, location):
+        """
+        Generates location in format, supported by tcmessages
+        :param location object with "file" (relative to base_dir) and "line" fields.
+        :return: location in format file:line (as supported in tcmessages)
+        """
+        my_file = str(location.file).lstrip("/\\")
+        return "file:///{}:{}".format(os.path.normpath(os.path.join(self.__base_dir, my_file)), location.line)
+
+    def _test_undefined(self, test_name, location):
+        """
+        Mark test as undefined
+        :param test_name: name of test
+        :type test_name str
+        :param location its location
+
+        """
+        if test_name != self.__last_test_name:
+            self._test_started(test_name, location)
+        self._test_failed(test_name, message="Test undefined", details="Please define test")
+
+    def _test_skipped(self, test_name, reason, location):
+        """
+        Mark test as skipped
+        :param test_name: name of test
+        :param reason: why test was skipped
+        :type reason str
+        :type test_name str
+        :param location its location
+
+        """
+        if test_name != self.__last_test_name:
+            self._test_started(test_name, location)
+        self.tc_messages.testIgnored(test_name, "Skipped: {}".format(reason))
+        self.__last_test_name = None
+        pass
+
+    def _test_failed(self, name, message, details):
+        """
+        Report test failure
+        :param name: test name
+        :type name str
+        :param message: failure message
+        :type message str
+        :param details: failure details (probably stacktrace)
+        :type details str
+        """
+        self.tc_messages.testFailed(name, message=message, details=details)
+        self.__last_test_name = None
+
+    def _test_passed(self, name, duration=None):
+        """
+        Reports test passed
+        :param name: test name
+        :type name str
+        :param duration: time (in seconds) test took. Pass None if you do not know (we'll try to calculate it)
+        :type duration int
+        :return:
+        """
+        duration_to_report = duration
+        if self.__last_test_start_time and not duration:  # And not provided
+            duration_to_report = int(time.time() - self.__last_test_start_time)
+        self.tc_messages.testFinished(name, duration=int(duration_to_report))
+        self.__last_test_start_time = None
+        self.__last_test_name = None
+
+    def _test_started(self, name, location):
+        """
+        Reports test launched
+        :param name: test name
+        :param location object with "file" (relative to base_dir) and "line" fields.
+        :type name str
+        """
+        self.__last_test_start_time = time.time()
+        self.__last_test_name = name
+        self.tc_messages.testStarted(name, self.__gen_location(location))
+
+    def _feature_or_scenario(self, is_started, name, location):
+        """
+        Reports feature or scenario launched or stopped
+        :param is_started: started or finished?
+        :type is_started bool
+        :param name: scenario or feature name
+        :param location object with "file" (relative to base_dir) and "line" fields.
+        """
+        if is_started:
+            self.tc_messages.testSuiteStarted(name, self.__gen_location(location))
+        else:
+            self.tc_messages.testSuiteFinished(name)
+
+    def _background(self, is_started, location):
+        """
+        Reports background or stopped
+        :param is_started: started or finished?
+        :type is_started bool
+        :param location object with "file" (relative to base_dir) and "line" fields.
+        """
+        self._feature_or_scenario(is_started, "Background", location)
+
+    def _get_number_of_tests(self):
+        """"
+        Gets number of tests using "_get_features_to_run()" to obtain number of features to calculate.
+        Supports backgrounds as well.
+         :return number of steps
+         :rtype int
+        """
+        num_of_steps = 0
+        for feature in self._get_features_to_run():
+            if feature.background:
+                num_of_steps += len(feature.background.steps) * len(feature.scenarios)
+            for scenario in feature.scenarios:
+                num_of_steps += len(scenario.steps)
+        return num_of_steps
+
+    @abc.abstractmethod
+    def _get_features_to_run(self):
+        """
+        Implement it! Return list of features to run. Each "feature" should have "scenarios".
+         Each "scenario" should have "steps". Each "feature" may have "background" and each "background" should have
+          "steps". Duck typing.
+        :rtype list
+        :returns list of features
+        """
+        return []
+
+    @abc.abstractmethod
+    def _run_tests(self):
+        """
+        Implement it! It should launch tests using your BDD. Use "self._" functions to report results.
+        """
+        pass
+
+
diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py
new file mode 100644
index 0000000..4a1b2f6
--- /dev/null
+++ b/python/helpers/pycharm/behave_runner.py
@@ -0,0 +1,242 @@
+# coding=utf-8
+"""
+Behave BDD runner.
+*FIRST* param now: folder to search "features" for.
+Each "features" folder should have features and "steps" subdir.
+
+Other args are tag expressionsin format (--tags=.. --tags=..).
+See https://pythonhosted.org/behave/behave.html#tag-expression
+"""
+import functools
+import sys
+import os
+import traceback
+
+from behave.formatter.base import Formatter
+from behave.model import Step, ScenarioOutline, Feature, Scenario
+from behave.tag_expression import TagExpression
+
+import _bdd_utils
+
+
+_MAX_STEPS_SEARCH_FEATURES = 5000  # Do not look for features in folder that has more that this number of children
+_FEATURES_FOLDER = 'features'  # "features" folder name.
+
+__author__ = 'Ilya.Kazakevich'
+
+from behave import configuration, runner
+from behave.formatter import formatters
+
+
+def _get_dirs_to_run(base_dir_to_search):
+    """
+    Searches for "features" dirs in some base_dir
+    :return: list of feature dirs to run
+    :rtype: list
+    :param base_dir_to_search root directory to search (should not have too many children!)
+    :type base_dir_to_search str
+
+    """
+    result = set()
+    for (step, (folder, sub_folders, files)) in enumerate(os.walk(base_dir_to_search)):
+        if os.path.basename(folder) == _FEATURES_FOLDER and os.path.isdir(folder):
+            result.add(os.path.abspath(folder))
+        if step == _MAX_STEPS_SEARCH_FEATURES:  # Guard
+            err = "Folder {} is too deep to find any features folder. Please provider concrete folder".format(
+                base_dir_to_search)
+            raise Exception(err)
+    return list(result)
+
+
+def _merge_hooks_wrapper(*hooks):
+    """
+    Creates wrapper that runs provided behave hooks sequentally
+    :param hooks: hooks to run
+    :return: wrapper
+    """
+    # TODO: Wheel reinvented!!!!
+    def wrapper(*args, **kwargs):
+        for hook in hooks:
+            hook(*args, **kwargs)
+
+    return wrapper
+
+
+class _RunnerWrapper(runner.Runner):
+    """
+    Wrapper around behave native wrapper. Has nothing todo with BddRunner!
+    We need it to support dry runs (to fetch data from scenarios) and hooks api
+    """
+
+    def __init__(self, config, hooks):
+        """
+        :type config configuration.Configuration
+        :param config behave configuration
+        :type hooks dict
+        :param hooks hooks in format "before_scenario" => f(context, scenario) to load after/before hooks, provided by user
+        """
+        super(_RunnerWrapper, self).__init__(config)
+        self.dry_run = False
+        """
+        Does not run tests (only fetches "self.features") if true. Runs tests otherwise.
+        """
+        self.__hooks = hooks
+
+    def load_hooks(self, filename='environment.py'):
+        """
+        Overrides parent "load_hooks" to add "self.__hooks"
+        :param filename: env. file name
+        """
+        super(_RunnerWrapper, self).load_hooks(filename)
+        for (hook_name, hook) in self.__hooks.items():
+            hook_to_add = hook
+            if hook_name in self.hooks:
+                user_hook = self.hooks[hook_name]
+                if hook_name.startswith("before"):
+                    user_and_custom_hook = [user_hook, hook]
+                else:
+                    user_and_custom_hook = [hook, user_hook]
+                hook_to_add = _merge_hooks_wrapper(*user_and_custom_hook)
+            self.hooks[hook_name] = hook_to_add
+
+    def run_model(self, features=None):
+        """
+        Overrides parent method to stop (do nothing) in case of "dry_run"
+        :param features: features to run
+        :return:
+        """
+        if self.dry_run:  # To stop further execution
+            return
+        return super(_RunnerWrapper, self).run_model(features)
+
+    def clean(self):
+        """
+        Cleans runner after dry run (clears hooks, features etc). To be called before real run!
+        """
+        self.dry_run = False
+        self.hooks.clear()
+        self.features = []
+
+
+class _BehaveRunner(_bdd_utils.BddRunner):
+    """
+    BddRunner for behave
+    """
+
+
+    def __process_hook(self, is_started, context, element):
+        """
+        Hook to be installed. Reports steps, features etc.
+        :param is_started true if test/feature/scenario is started
+        :type is_started bool
+        :param context behave context
+        :type context behave.runner.Context
+        :param element feature/suite/step
+        """
+        element.location.file = element.location.filename  # To preserve _bdd_utils contract
+        if isinstance(element, Step):
+            # Process step
+            if is_started:
+                self._test_started(element.name, element.location)
+            elif element.status == 'passed':
+                self._test_passed(element.name, element.duration)
+            elif element.status == 'failed':
+                try:
+                    trace = traceback.format_exc()
+                except Exception:
+                    trace = "".join(traceback.format_tb(element.exc_traceback))
+                self._test_failed(element.name, element.error_message, trace)
+            elif element.status == 'undefined':
+                self._test_undefined(element.name, element.location)
+            else:
+                self._test_skipped(element.name, element.status, element.location)
+        elif not is_started and isinstance(element, Scenario) and element.status == 'failed':
+            # To process scenarios with undefined/skipped tests
+            for step in element.steps:
+                assert isinstance(step, Step), step
+                if step.status not in ['passed', 'failed']:  # Something strange, probably skipped or undefined
+                    self.__process_hook(False, context, step)
+            self._feature_or_scenario(is_started, element.name, element.location)
+        elif isinstance(element, ScenarioOutline):
+            self._feature_or_scenario(is_started, str(element.examples), element.location)
+        else:
+            self._feature_or_scenario(is_started, element.name, element.location)
+
+    def __init__(self, config, base_dir):
+        """
+        :type config configuration.Configuration
+        """
+        super(_BehaveRunner, self).__init__(base_dir)
+        self.__config = config
+        # Install hooks
+        self.__real_runner = _RunnerWrapper(config, {
+            "before_feature": functools.partial(self.__process_hook, True),
+            "after_feature": functools.partial(self.__process_hook, False),
+            "before_scenario": functools.partial(self.__process_hook, True),
+            "after_scenario": functools.partial(self.__process_hook, False),
+            "before_step": functools.partial(self.__process_hook, True),
+            "after_step": functools.partial(self.__process_hook, False)
+        })
+
+    def _run_tests(self):
+        self.__real_runner.run()
+
+
+    def __filter_scenarios_by_tag(self, scenario):
+        """
+        Filters out scenarios that should be skipped by tags
+        :param scenario scenario to check
+        :return true if should pass
+        """
+        assert isinstance(scenario, Scenario), scenario
+        expected_tags = self.__config.tags
+        if not expected_tags:
+            return True  # No tags are required
+        return isinstance(expected_tags, TagExpression) and expected_tags.check(scenario.tags)
+
+
+    def _get_features_to_run(self):
+        self.__real_runner.dry_run = True
+        self.__real_runner.run()
+        features_to_run = self.__real_runner.features
+        self.__real_runner.clean()  # To make sure nothing left after dry run
+
+        # Change outline scenario skeletons with real scenarios
+        for feature in features_to_run:
+            assert isinstance(feature, Feature), feature
+            scenarios = []
+            for scenario in feature.scenarios:
+                if isinstance(scenario, ScenarioOutline):
+                    scenarios.extend(scenario.scenarios)
+                else:
+                    scenarios.append(scenario)
+            feature.scenarios = filter(self.__filter_scenarios_by_tag, scenarios)
+
+        return features_to_run
+
+
+if __name__ == "__main__":
+    # TODO: support all other params instead
+
+    class _Null(Formatter):
+        """
+        Null formater to prevent stdout output
+        """
+        pass
+
+    command_args = list(filter(None, sys.argv[1:]))
+    my_config = configuration.Configuration(command_args=command_args)
+    formatters.register_as(_Null, "com.intellij.python.null")
+    my_config.format = ["com.intellij.python.null"]  # To prevent output to stdout
+    my_config.reporters = []  # To prevent summary to stdout
+    my_config.stdout_capture = False  # For test output
+    my_config.stderr_capture = False  # For test output
+    (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
+    if not my_config.paths:  # No path provided, trying to load dit manually
+        if os.path.isfile(what_to_run):  # File is provided, load it
+            my_config.paths = [what_to_run]
+        else:  # Dir is provided, find subdirs ro run
+            my_config.paths = _get_dirs_to_run(base_dir)
+    _BehaveRunner(my_config, base_dir).run()
+
+
diff --git a/python/helpers/pycharm/lettuce_runner.py b/python/helpers/pycharm/lettuce_runner.py
index 6aaa566..3cd1125 100644
--- a/python/helpers/pycharm/lettuce_runner.py
+++ b/python/helpers/pycharm/lettuce_runner.py
@@ -1,132 +1,112 @@
 # coding=utf-8
 """
 BDD lettuce framework runner
+TODO: Support other params (like tags) as well.
+Supports only 1 param now: folder to search "features" for.
 """
+import _bdd_utils
+
 __author__ = 'Ilya.Kazakevich'
-import os
 from lettuce.exceptions import ReasonToFail
-import time
 import sys
-import tcmessages
 import lettuce
 from lettuce import core
 
 
-# Error message about unsupported outlines
-_NO_OUTLINE_ERROR = "Outline scenarios are not supported due to https://github.com/gabrielfalcao/lettuce/issues/451"
-
-
-class LettuceRunner(object):
+class _LettuceRunner(_bdd_utils.BddRunner):
     """
-    TODO: Runs lettuce
+    Lettuce runner (BddRunner for lettuce)
     """
 
-    def __init__(self, base_dir):
+    def __init__(self, base_dir, what_to_run):
         """
+
         :param base_dir base directory to run tests in
         :type base_dir: str
+        :param what_to_run folder or file to run
+        :type what_to_run str
+        """
+        super(_LettuceRunner, self).__init__(base_dir)
+        self.__runner = lettuce.Runner(what_to_run)
 
-        """
-        self.base_dir = base_dir
-        self.runner = lettuce.Runner(base_dir)
-        self.messages = tcmessages.TeamcityServiceMessages()
-        self.test_start_time = None
+    def _get_features_to_run(self):
+        super(_LettuceRunner, self)._get_features_to_run()
+        if self.__runner.single_feature:  # We need to run one and only one feature
+            return [core.Feature.from_file(self.__runner.single_feature)]
 
-    def report_tests(self):
-        """
-        :returns : number of tests
-        :rtype : int
-        """
-        result = 0
-        for feature_file in self.runner.loader.find_feature_files():
+        # Find all features in dir
+        features = []
+        for feature_file in self.__runner.loader.find_feature_files():
             feature = core.Feature.from_file(feature_file)
-            for scenario in feature.scenarios:
-                assert isinstance(scenario, core.Scenario), scenario
-                if not scenario.outlines:
-                    result += len(scenario.steps)
-        self.messages.testCount(result)
+            assert isinstance(feature, core.Feature), feature
+            # TODO: cut out due to https://github.com/gabrielfalcao/lettuce/issues/451  Fix when this issue fixed
+            feature.scenarios = filter(lambda s: not s.outlines, feature.scenarios)
+            if feature.scenarios:
+                features.append(feature)
+        return features
 
-    def report_scenario_started(self, scenario):
+    def _run_tests(self):
+        super(_LettuceRunner, self)._run_tests()
+        self.__install_hooks()
+        self.__runner.run()
+
+    def __step(self, is_started, step):
+        """
+        Reports step start / stop
+        :type step core.Step
+        :param step: step
+        """
+        test_name = step.sentence
+        if is_started:
+            self._test_started(test_name, step.described_at)
+        elif step.passed:
+            self._test_passed(test_name)
+        elif step.failed:
+            reason = step.why
+            assert isinstance(reason, ReasonToFail), reason
+            self._test_failed(test_name, message=reason.exception, details=reason.traceback)
+        elif step.has_definition:
+            self._test_skipped(test_name, "In lettuce, we do know the reason", step.described_at)
+        else:
+            self._test_undefined(test_name, step.described_at)
+
+    def __install_hooks(self):
+        """
+        Installs required hooks
+        """
+
+        # Install hooks
+        lettuce.before.each_feature(
+            lambda f: self._feature_or_scenario(True, f.name, f.described_at))
+        lettuce.after.each_feature(
+            lambda f: self._feature_or_scenario(False, f.name, f.described_at))
+
+        lettuce.before.each_scenario(
+            lambda s: self.__scenario(True, s))
+        lettuce.after.each_scenario(
+            lambda s: self.__scenario(False, s))
+
+        lettuce.before.each_background(
+            lambda b, *args: self._background(True, b.feature.described_at))
+        lettuce.after.each_background(
+            lambda b, *args: self._background(False, b.feature.described_at))
+
+        lettuce.before.each_step(lambda s: self.__step(True, s))
+        lettuce.after.each_step(lambda s: self.__step(False, s))
+
+    def __scenario(self, is_started, scenario):
         """
         Reports scenario launched
         :type scenario core.Scenario
         :param scenario: scenario
         """
         if scenario.outlines:
-            self.messages.testIgnored(scenario.name,
-                                      _NO_OUTLINE_ERROR)
             scenario.steps = []  # Clear to prevent running. TODO: Fix when this issue fixed
             scenario.background = None  # TODO: undocumented
             return
-        self.report_suite(True, scenario.name, scenario.described_at)
-
-    def report_suite(self, is_start, name, described_at):
-        """
-        Reports some suite (scenario, feature, background etc) is started or stopped
-        :param is_start: started or not
-        :param name: suite name
-        :param described_at: where it is described (file, line)
-        :return:
-        """
-        if is_start:
-            self.messages.testSuiteStarted(name, self._gen_location(described_at))
-        else:
-            self.messages.testSuiteFinished(name)
-
-    def report_step(self, is_start, step):
-        """
-        Reports step start / stop
-        :param is_start: true if step started
-        :type step core.Step
-        :param step: step
-        """
-        test_name = step.sentence
-        if is_start:
-            self.test_start_time = time.time()
-            self.messages.testStarted(test_name, self._gen_location(step.described_at))
-        elif step.passed:
-            duration = 0
-            if self.test_start_time:
-                duration = long(time.time() - self.test_start_time)
-            self.messages.testFinished(test_name, duration=duration)
-            self.test_start_time = None
-        elif step.failed:
-            reason = step.why
-            assert isinstance(reason, ReasonToFail), reason
-            self.messages.testFailed(test_name, message=reason.exception, details=reason.traceback)
-
-    def _gen_location(self, description):
-        """
-        :param description: "described_at" (file, line)
-        :return: location in format file:line by "described_at"
-        """
-        return "file:///{}/{}:{}".format(self.base_dir, description.file, description.line)
-
-    def run(self):
-        """
-        Launches runner
-        """
-        self.report_tests()
-        self.messages.testMatrixEntered()
-
-        lettuce.before.each_feature(lambda f: self.report_suite(True, f.name, f.described_at))
-        lettuce.after.each_feature(lambda f: self.report_suite(False, f.name, f.described_at))
-
-        lettuce.before.each_scenario(lambda s: self.report_scenario_started(s))
-        lettuce.after.each_scenario(lambda s: self.report_suite(False, s.name, s.described_at))
-
-        lettuce.before.each_background(
-            lambda b, *args: self.report_suite(True, "Scenario background", b.feature.described_at))
-        lettuce.after.each_background(
-            lambda b, *args: self.report_suite(False, "Scenario background", b.feature.described_at))
-
-        lettuce.before.each_step(lambda s: self.report_step(True, s))
-        lettuce.after.each_step(lambda s: self.report_step(False, s))
-
-        self.runner.run()
+        self._feature_or_scenario(is_started, scenario.name, scenario.described_at)
 
 
 if __name__ == "__main__":
-    path = sys.argv[1] if len(sys.argv) > 1 else "."
-    assert os.path.exists(path), "{} does not exist".format(path)
-    LettuceRunner(path).run()
\ No newline at end of file
+    (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
+    _LettuceRunner(base_dir, what_to_run).run()
\ No newline at end of file
diff --git a/python/helpers/pycharm/tcunittest.py b/python/helpers/pycharm/tcunittest.py
index b6950c9..99b3059 100644
--- a/python/helpers/pycharm/tcunittest.py
+++ b/python/helpers/pycharm/tcunittest.py
@@ -6,14 +6,16 @@
 
 PYTHON_VERSION_MAJOR = sys.version_info[0]
 
+
 def strclass(cls):
   if not cls.__name__:
     return cls.__module__
   return "%s.%s" % (cls.__module__, cls.__name__)
 
+
 def smart_str(s):
-  encoding='utf-8'
-  errors='strict'
+  encoding = 'utf-8'
+  errors = 'strict'
   if PYTHON_VERSION_MAJOR < 3:
     is_string = isinstance(s, basestring)
   else:
@@ -33,6 +35,7 @@
   else:
     return s
 
+
 class TeamcityTestResult(TestResult):
   def __init__(self, stream=sys.stdout, *args, **kwargs):
     TestResult.__init__(self)
@@ -41,42 +44,47 @@
     self.output = stream
     self.messages = TeamcityServiceMessages(self.output, prepend_linebreak=True)
     self.messages.testMatrixEntered()
+    self.current_failed = False
     self.current_suite = None
+    self.subtest_suite = None
 
   def find_first(self, val):
     quot = val[0]
     count = 1
     quote_ind = val[count:].find(quot)
-    while quote_ind != -1 and val[count+quote_ind-1] == "\\":
+    while quote_ind != -1 and val[count + quote_ind - 1] == "\\":
       count = count + quote_ind + 1
       quote_ind = val[count:].find(quot)
 
-    return val[0:quote_ind+count+1]
+    return val[0:quote_ind + count + 1]
 
   def find_second(self, val):
     val_index = val.find("!=")
     if val_index != -1:
       count = 1
-      val = val[val_index+2:].strip()
+      val = val[val_index + 2:].strip()
       quot = val[0]
       quote_ind = val[count:].find(quot)
-      while quote_ind != -1 and val[count+quote_ind-1] == "\\":
+      while quote_ind != -1 and val[count + quote_ind - 1] == "\\":
         count = count + quote_ind + 1
         quote_ind = val[count:].find(quot)
-      return val[0:quote_ind+count+1]
+      return val[0:quote_ind + count + 1]
 
     else:
       quot = val[-1]
-      quote_ind = val[:len(val)-1].rfind(quot)
-      while quote_ind != -1 and val[quote_ind-1] == "\\":
-        quote_ind = val[:quote_ind-1].rfind(quot)
+      quote_ind = val[:len(val) - 1].rfind(quot)
+      while quote_ind != -1 and val[quote_ind - 1] == "\\":
+        quote_ind = val[:quote_ind - 1].rfind(quot)
       return val[quote_ind:]
 
   def formatErr(self, err):
     exctype, value, tb = err
     return ''.join(traceback.format_exception(exctype, value, tb))
 
-  def getTestName(self, test):
+  def getTestName(self, test, is_subtest=False):
+    if is_subtest:
+      test_name = self.getTestName(test.test_case)
+      return "{} {}".format(test_name, test._subDescription())
     if hasattr(test, '_testMethodName'):
       if test._testMethodName == "runTest":
         return str(test)
@@ -95,10 +103,13 @@
     TestResult.addSuccess(self, test)
 
   def addError(self, test, err):
+    self.init_suite(test)
+    self.current_failed = True
     TestResult.addError(self, test, err)
 
     err = self._exc_info_to_string(err, test)
 
+    self.messages.testStarted(self.getTestName(test))
     self.messages.testError(self.getTestName(test),
                             message='Error', details=err)
 
@@ -108,6 +119,8 @@
     return error_value.split('assert')[-1].strip()
 
   def addFailure(self, test, err):
+    self.init_suite(test)
+    self.current_failed = True
     TestResult.addFailure(self, test, err)
 
     error_value = smart_str(err[1])
@@ -119,7 +132,7 @@
     self_find_second = self.find_second(error_value)
     quotes = ["'", '"']
     if (self_find_first[0] == self_find_first[-1] and self_find_first[0] in quotes and
-        self_find_second[0] == self_find_second[-1] and self_find_second[0] in quotes):
+            self_find_second[0] == self_find_second[-1] and self_find_second[0] in quotes):
       # let's unescape strings to show sexy multiline diff in PyCharm.
       # By default all caret return chars are escaped by testing framework
       first = self._unescape(self_find_first)
@@ -128,10 +141,13 @@
       first = second = ""
     err = self._exc_info_to_string(err, test)
 
+    self.messages.testStarted(self.getTestName(test))
     self.messages.testFailed(self.getTestName(test),
                              message='Failure', details=err, expected=first, actual=second)
 
   def addSkip(self, test, reason):
+    self.init_suite(test)
+    self.current_failed = True
     self.messages.testIgnored(self.getTestName(test), message=reason)
 
   def __getSuite(self, test):
@@ -149,10 +165,10 @@
       try:
         source_file = inspect.getsourcefile(test.__class__)
         if source_file:
-            source_dir_splitted = source_file.split("/")[:-1]
-            source_dir = "/".join(source_dir_splitted) + "/"
+          source_dir_splitted = source_file.split("/")[:-1]
+          source_dir = "/".join(source_dir_splitted) + "/"
         else:
-            source_dir = ""
+          source_dir = ""
       except TypeError:
         source_dir = ""
 
@@ -163,20 +179,52 @@
     return (suite, location, suite_location)
 
   def startTest(self, test):
+    self.current_failed = False
+    setattr(test, "startTime", datetime.datetime.now())
+
+  def init_suite(self, test):
     suite, location, suite_location = self.__getSuite(test)
     if suite != self.current_suite:
       if self.current_suite:
         self.messages.testSuiteFinished(self.current_suite)
       self.current_suite = suite
       self.messages.testSuiteStarted(self.current_suite, location=suite_location)
-    setattr(test, "startTime", datetime.datetime.now())
-    self.messages.testStarted(self.getTestName(test), location=location)
+    return location
 
   def stopTest(self, test):
     start = getattr(test, "startTime", datetime.datetime.now())
     d = datetime.datetime.now() - start
-    duration=d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000
-    self.messages.testFinished(self.getTestName(test), duration=int(duration))
+    duration = d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000
+    if not self.subtest_suite:
+      if not self.current_failed:
+        location = self.init_suite(test)
+        self.messages.testStarted(self.getTestName(test), location=location)
+        self.messages.testFinished(self.getTestName(test), duration=int(duration))
+    else:
+      self.messages.testSuiteFinished(self.subtest_suite)
+      self.subtest_suite = None
+
+
+  def addSubTest(self, test, subtest, err):
+    suite_name = self.getTestName(test)  # + " (subTests)"
+    if not self.subtest_suite:
+      self.subtest_suite = suite_name
+      self.messages.testSuiteStarted(self.subtest_suite)
+    else:
+      if suite_name != self.subtest_suite:
+        self.messages.testSuiteFinished(self.subtest_suite)
+        self.subtest_suite = suite_name
+        self.messages.testSuiteStarted(self.subtest_suite)
+
+    name = self.getTestName(subtest, True)
+    if err is not None:
+      error = self._exc_info_to_string(err, test)
+      self.messages.testStarted(name)
+      self.messages.testFailed(name, message='Failure', details=error)
+    else:
+      self.messages.testStarted(name)
+      self.messages.testFinished(name)
+
 
   def endLastSuite(self):
     if self.current_suite:
@@ -187,6 +235,7 @@
     # do not use text.decode('string_escape'), it leads to problems with different string encodings given
     return text.replace("\\n", "\n")
 
+
 class TeamcityTestRunner(object):
   def __init__(self, stream=sys.stdout):
     self.stream = stream
diff --git a/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java b/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
index d186f33..7570e3f 100644
--- a/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
+++ b/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
@@ -16,9 +16,11 @@
 package com.jetbrains.python.newProject;
 
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.wm.impl.welcomeScreen.CardActionsPanel;
+import com.intellij.platform.DirectoryProjectGenerator;
 import com.jetbrains.python.newProject.actions.PyCharmNewProjectStep;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -42,7 +44,8 @@
         PyCharmNewProjectDialog.this.close(OK_EXIT_CODE);
       }
     };
-    final DefaultActionGroup root = new PyCharmNewProjectStep(runnable);
+    final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+    final DefaultActionGroup root = new PyCharmNewProjectStep(generators.length == 0 ? "Create Project" : "Select Project Type", runnable);
 
     return new CardActionsPanel(root) {
 
@@ -53,6 +56,7 @@
 
       @Override
       public Dimension getMinimumSize() {
+        if (generators.length == 0) return new Dimension(550, 200);
         return new Dimension(650, 450);
       }
     };
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
index d9f3cf2..6ba283c 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
@@ -8,6 +8,7 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.actionSystem.impl.ActionButtonWithText;
+import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
 import com.intellij.openapi.project.DumbAware;
@@ -45,10 +46,12 @@
 
 import javax.swing.*;
 import javax.swing.border.Border;
+import javax.swing.border.LineBorder;
 import javax.swing.event.DocumentEvent;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
 import java.awt.event.MouseEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -62,9 +65,10 @@
   private boolean myInstallFramework;
   private TextFieldWithBrowseButton myLocationField;
   protected final File myProjectDirectory;
-  private ActionButtonWithText myCreateButton;
+  private Button myCreateButton;
   private JLabel myErrorLabel;
   private AnAction myCreateAction;
+  private Sdk mySdk;
 
   public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, NullableConsumer<AbstractProjectSettingsStep> callback) {
     super();
@@ -104,16 +108,24 @@
 
   @Override
   public JPanel createPanel() {
-    final JPanel mainPanel = new JPanel(new BorderLayout());
+    final JPanel basePanel = createBasePanel();
+    final JPanel mainPanel = new JPanel(new BorderLayout()) {
+      @Override
+      protected void paintComponent(Graphics g) {
+        myLocationField.requestFocus();
+      }
+    };
+
     final JPanel scrollPanel = new JPanel(new BorderLayout());
 
-    mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, 400));
+    final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+    final int height = generators.length == 0 ? 150 : 400;
+    mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, height));
     myErrorLabel = new JLabel("");
     myErrorLabel.setForeground(JBColor.RED);
     myCreateButton = new Button(myCreateAction, myCreateAction.getTemplatePresentation());
 
-    final JPanel panel = createBasePanel();
-    scrollPanel.add(panel, BorderLayout.NORTH);
+    scrollPanel.add(basePanel, BorderLayout.NORTH);
     final JPanel advancedSettings = createAdvancedSettings();
     if (advancedSettings != null) {
       scrollPanel.add(advancedSettings, BorderLayout.CENTER);
@@ -125,8 +137,6 @@
 
     final JPanel bottomPanel = new JPanel(new BorderLayout());
 
-
-    myCreateButton.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, 40));
     bottomPanel.add(myErrorLabel, BorderLayout.NORTH);
     bottomPanel.add(myCreateButton, BorderLayout.EAST);
     mainPanel.add(bottomPanel, BorderLayout.SOUTH);
@@ -150,7 +160,22 @@
     final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
     myLocationField.addBrowseFolderListener("Select base directory", "Select base directory for the Project",
                                             null, descriptor);
-
+    myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+      @Override
+      protected void textChanged(DocumentEvent e) {
+        if (myProjectGenerator instanceof PythonProjectGenerator) {
+          String path = myLocationField.getText().trim();
+          if (path.endsWith(File.separator)) {
+            path = path.substring(0, path.length() - File.separator.length());
+          }
+          int ind = path.lastIndexOf(File.separator);
+          if (ind != -1) {
+            String projectName = path.substring(ind + 1, path.length());
+            ((PythonProjectGenerator)myProjectGenerator).locationChanged(projectName);
+          }
+        }
+      }
+    });
     final JLabel locationLabel = new JLabel("Location:");
     c.gridx = 0;
     c.gridy = 0;
@@ -193,13 +218,23 @@
     c.gridy = 1;
     c.weightx = 1.;
     panel.add(mySdkCombo, c);
-
+    final JPanel basePanelExtension = extendBasePanel();
+    if (basePanelExtension != null) {
+      c.gridwidth = 2;
+      c.gridy = 2;
+      c.gridx = 0;
+      panel.add(basePanelExtension, c);
+    }
     registerValidators();
     return panel;
   }
 
-  protected void registerValidators() {
+  @Nullable
+  protected JPanel extendBasePanel() {
+    return null;
+  }
 
+  protected void registerValidators() {
     myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
       @Override
       protected void textChanged(DocumentEvent e) {
@@ -358,7 +393,8 @@
 
     public Button(AnAction action, Presentation presentation) {
       super(action, presentation, "NewProject", new Dimension(70, 50));
-      myBorder = UIUtil.isUnderDarcula() ? UIUtil.getButtonBorder() : BorderFactory.createLineBorder(UIUtil.getBorderColor());
+      final Border border = new LineBorder(JBColor.border(), 1, true);
+      myBorder = UIUtil.isUnderDarcula() ? UIUtil.getButtonBorder() : border;
       setBorder(myBorder);
     }
 
@@ -368,6 +404,23 @@
     }
 
     @Override
+    public boolean isFocusable() {
+      return true;
+    }
+
+    @Override
+    protected void processFocusEvent(FocusEvent e) {
+      super.processFocusEvent(e);
+      if (e.getID() == FocusEvent.FOCUS_GAINED) {
+        processMouseEvent(new MouseEvent(this, MouseEvent.MOUSE_ENTERED, System.currentTimeMillis(), 0, 0, 0, 0, false));
+
+      }
+      else if (e.getID() == FocusEvent.FOCUS_LOST) {
+        processMouseEvent(new MouseEvent(this, MouseEvent.MOUSE_EXITED, System.currentTimeMillis(), 0, 0, 0, 0, false));
+      }
+    }
+
+    @Override
     public Insets getInsets() {
       return new Insets(5,10,5,5);
     }
@@ -377,11 +430,6 @@
       return SwingConstants.LEFT;
     }
 
-    @Override
-    public String getToolTipText() {
-      return null;
-    }
-
     protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_ENTERED) {
@@ -394,9 +442,14 @@
   }
 
   public Sdk getSdk() {
+    if (mySdk != null) return mySdk;
     return (Sdk)mySdkCombo.getComboBox().getSelectedItem();
   }
 
+  public void setSdk(final Sdk sdk) {
+    mySdk = sdk;
+  }
+
   public String getProjectLocation() {
     return myLocationField.getText();
   }
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
index ebd0658..5e60601 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
@@ -15,6 +15,7 @@
  */
 package com.jetbrains.python.newProject.actions;
 
+import com.intellij.facet.ui.ValidationResult;
 import com.intellij.ide.util.projectWizard.WebProjectTemplate;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.ui.VerticalFlowLayout;
@@ -46,6 +47,12 @@
     if (advancedSettings != null) {
       final JPanel jPanel = new JPanel(new VerticalFlowLayout());
       final HideableDecorator deco = new HideableDecorator(jPanel, "Mor&e Settings", false);
+      boolean isValid = checkValid();
+      deco.setOn(!isValid);
+      if (myProjectGenerator instanceof PythonProjectGenerator && !deco.isExpanded()) {
+        final ValidationResult result = ((PythonProjectGenerator)myProjectGenerator).warningValidation(getSdk());
+        deco.setOn(!result.isOk());
+      }
       deco.setContentComponent(advancedSettings);
       return jPanel;
     }
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
index b6134ed..4f9f107 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
@@ -62,8 +62,8 @@
 public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAware {
   private static final Logger LOG = Logger.getInstance(PyCharmNewProjectStep.class);
 
-  public PyCharmNewProjectStep(@Nullable final Runnable runnable) {
-    super("Select Project Type", true);
+  public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable) {
+    super(name, true);
 
     final NullableConsumer<AbstractProjectSettingsStep> callback = new NullableConsumer<AbstractProjectSettingsStep>() {
       @Override
@@ -87,6 +87,7 @@
           sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null,
                                               null);
           model.addSdk(sdk);
+          settingsStep.setSdk(sdk);
           try {
             model.apply();
           }
@@ -165,6 +166,9 @@
     add(action);
 
     final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+    if (generators.length == 0) {
+      action.setPopup(false);
+    }
     Arrays.sort(generators, new Comparator<DirectoryProjectGenerator>() {
       @Override
       public int compare(DirectoryProjectGenerator o1, DirectoryProjectGenerator o2) {
@@ -188,7 +192,7 @@
   }
 
   public PyCharmNewProjectStep() {
-    this(null);
+    this("Select Project Type", null);
 
   }
 
diff --git a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
index 5577959..1432e46 100644
--- a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
+++ b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
@@ -31,6 +31,8 @@
     myListeners.add(listener);
   }
 
+  public void locationChanged(@NotNull final String newLocation) {}
+
   public interface SettingsListener {
     void stateChanged();
   }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
index 9f6e7c9..daa8b30 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
@@ -37,15 +37,17 @@
   public abstract PyStringLiteralExpression createStringLiteralAlreadyEscaped(String str);
 
 
-
-
   /**
    * Creates a string literal, adding appropriate quotes, properly escaping characters inside.
+   *
    * @param destination where the literal is destined to; used to determine the encoding.
    * @param unescaped   the string
-   * @return            a newly created literal
+   * @param preferUTF8 try to use UTF8 (would use ascii if false)
+   * @return a newly created literal
    */
-  public abstract PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, String unescaped);
+  public abstract PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, String unescaped,
+                                                                          boolean preferUTF8);
+
   public abstract PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped);
 
   public abstract PyStringLiteralExpression createStringLiteral(@NotNull PyStringLiteralExpression oldElement, @NotNull String unescaped);
@@ -59,11 +61,11 @@
   public abstract PyBinaryExpression createBinaryExpression(String s, PyExpression expr, PyExpression listLiteral);
 
   /**
-   * @deprecated  use the overload with language level specified
    * @param text the text to create an expression from
    * @return the expression
+   * @deprecated use the overload with language level specified
    */
-  public abstract  PyExpression createExpressionFromText(String text);
+  public abstract PyExpression createExpressionFromText(String text);
 
   public abstract PyExpression createExpressionFromText(final LanguageLevel languageLevel, String text);
 
@@ -71,9 +73,9 @@
    * Adds elements to list inserting required commas.
    * Method is like {@link #insertItemIntoList(PyElement, PyExpression, PyExpression)} but does not add unneeded commas.
    *
-   * @param list where to add
+   * @param list      where to add
    * @param afterThis after which element it should be added (null for add to the head)
-   * @param toInsert what to insert
+   * @param toInsert  what to insert
    * @return newly inserted element
    */
   @NotNull
@@ -92,7 +94,10 @@
 
   public abstract PyImportElement createImportElement(final LanguageLevel languageLevel, String name);
 
-  public abstract PyFunction createProperty(final LanguageLevel languageLevel, String propertyName, String fieldName, AccessDirection accessDirection);
+  public abstract PyFunction createProperty(final LanguageLevel languageLevel,
+                                            String propertyName,
+                                            String fieldName,
+                                            AccessDirection accessDirection);
 
   @NotNull
   public abstract <T> T createFromText(LanguageLevel langLevel, Class<T> aClass, final String text);
@@ -103,6 +108,7 @@
   /**
    * Creates an arbitrary PSI element from text, by creating a bigger construction and then cutting the proper subelement.
    * Will produce all kinds of exceptions if the path or class would not match the PSI tree.
+   *
    * @param langLevel the language level to use for parsing the text
    * @param aClass    class of the PSI element; may be an interface not descending from PsiElement, as long as target node can be cast to it
    * @param text      text to parse
@@ -122,8 +128,15 @@
   public abstract PsiFile createDummyFile(LanguageLevel langLevel, String contents);
 
   public abstract PyExpressionStatement createDocstring(String content);
+
   public abstract PyPassStatement createPassStatement();
 
   @NotNull
   public abstract PyDecoratorList createDecoratorList(@NotNull final String... decoratorTexts);
+
+  /**
+   * Creates new line whitespace
+   */
+  @NotNull
+  public abstract PsiElement createNewLine();
 }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java b/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
index c329162..41b715f 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
@@ -15,17 +15,10 @@
  */
 package com.jetbrains.python.psi;
 
-import org.jetbrains.annotations.Nullable;
-
 /**
  * The 'else:' part of various compound statements.
  * User: dcheryasov
  * Date: Mar 15, 2009 9:34:51 PM
  */
 public interface PyElsePart extends PyStatementPart {
-  /**
-   * @return the body of the 'else' part.
-   */
-  @Nullable
-  PyStatementList getStatementList();
 }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
index f491a6a..a14a91e 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
@@ -15,19 +15,19 @@
  */
 package com.jetbrains.python.psi;
 
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Abstract part of a multipart statement.
  * User: dcheryasov
  * Date: Mar 16, 2009 4:34:59 AM
  */
-public interface PyStatementPart extends PyElement {
+public interface PyStatementPart extends PyElement, PyStatementListContainer {
   PyStatementPart[] EMPTY_ARRAY = new PyStatementPart[0];
 
   /**
    * @return the body of the part.
    */
-  @Nullable
+  @NotNull
   PyStatementList getStatementList();
 }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java b/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
index 201ae30..b23ca63 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
@@ -18,6 +18,6 @@
 /**
  * @author yole
  */
-public interface PyWithStatement extends PyStatement, NameDefiner {
+public interface PyWithStatement extends PyStatement, NameDefiner, PyStatementListContainer {
   PyWithItem[] getWithItems();
 }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
index fa88810..808ec47 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
@@ -25,6 +25,15 @@
  * @author vlan
  */
 public interface StructuredDocString {
+  /**
+   * Creates parameter type documentation specific for certain doct type
+   * @param name param name
+   * @param type param type
+   * @return text to add to docsting
+   */
+  @NotNull
+  String createParameterType(@NotNull String name, @NotNull String type);
+
   String getDescription();
 
   String getSummary();
diff --git a/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java b/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
index e421df8..e5b52b5 100644
--- a/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
+++ b/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
@@ -19,7 +19,6 @@
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.configurations.ParametersList;
 import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
 import com.intellij.execution.process.ProcessAdapter;
 import com.intellij.execution.process.ProcessEvent;
 import com.intellij.execution.process.ProcessHandler;
@@ -33,7 +32,6 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.Collections;
 
 /**
  * User : catherine
@@ -43,7 +41,7 @@
 
   public RestCommandLineState(RestRunConfiguration configuration,
                               ExecutionEnvironment env) {
-    super(configuration, env, Collections.<Filter>emptyList());
+    super(configuration, env);
     myConfiguration = configuration;
   }
 
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index 88280cc..a27eb44 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -528,6 +528,12 @@
     <!-- Packaging -->
     <moduleService serviceInterface="com.jetbrains.python.packaging.PyPackageRequirementsSettings"
                    serviceImplementation="com.jetbrains.python.packaging.PyPackageRequirementsSettings"/>
+
+    <!-- Console -->
+    <toolWindow id="Python Console" anchor="bottom" icon=""
+                factoryClass="com.jetbrains.python.console.PythonConsoleToolWindowFactory" secondary="false"/>
+
+
   </extensions>
 
   <extensionPoints>    
@@ -615,6 +621,12 @@
     </component>
   </project-components>
 
+  <project-components>
+    <component>
+      <implementation-class>com.jetbrains.python.console.PythonConsoleToolWindow</implementation-class>
+    </component>
+  </project-components>
+
   <actions>
     <group id="PyTypeHierarchyPopupMenu">
       <reference ref="TypeHierarchyBase.BaseOnThisType"/>
diff --git a/python/src/com/jetbrains/python/PyAddImportFix.java b/python/src/com/jetbrains/python/PyAddImportFix.java
new file mode 100644
index 0000000..c13fed1
--- /dev/null
+++ b/python/src/com/jetbrains/python/PyAddImportFix.java
@@ -0,0 +1,55 @@
+package com.jetbrains.python;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.psi.PyImportStatementBase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Quick fix that adds import to file
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyAddImportFix implements LocalQuickFix {
+  @NotNull
+  private final String myImportToAdd;
+  @NotNull
+  private final PyFile myFile;
+
+  /**
+   * @param importToAdd string representing what to add (i.e. "from foo import bar")
+   * @param file where to add
+   */
+  public PyAddImportFix(@NotNull final String importToAdd, @NotNull final PyFile file) {
+    myImportToAdd = importToAdd;
+    myFile = file;
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return PyBundle.message("QFIX.add.import", myImportToAdd);
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
+  @Override
+  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+    final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+    final PyImportStatementBase statement =
+      generator.createFromText(LanguageLevel.forElement(myFile), PyImportStatementBase.class, myImportToAdd);
+    final PsiElement recommendedPosition = AddImportHelper.getFileInsertPosition(myFile);
+    myFile.addAfter(statement, recommendedPosition);
+  }
+}
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 5d29d3f..482daa8 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -32,6 +32,8 @@
 
 QFIX.add.encoding=Add encoding declaration
 
+QFIX.add.import=Add "''{0}''"
+
 QFIX.NAME.parameters=Parameters of functions and methods
 QFIX.rename.parameter.to.$0=Rename to ''{0}''
 
diff --git a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
index 58b35fe..cb90d49 100644
--- a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
+++ b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
@@ -17,7 +17,6 @@
 
 import com.intellij.execution.ExecutionHelper;
 import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.execution.console.LanguageConsoleViewImpl;
 import com.intellij.execution.process.ProcessHandler;
 import com.intellij.execution.ui.RunContentDescriptor;
 import com.intellij.openapi.actionSystem.*;
@@ -215,7 +214,7 @@
   private static void startConsole(final Project project,
                                    final Consumer<PyCodeExecutor> consumer,
                                    Module context) {
-    PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context);
+    PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context, null);
     runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
       @Override
       public void handleConsoleInitialized(LanguageConsoleView consoleView) {
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
index e27f2a6..2785b23 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
@@ -79,7 +79,7 @@
     }
 
     final PsiElement[] children = element.getChildren();
-    for (PsiElement child : children) {
+    for (final PsiElement child : children) {
       if (element instanceof PyStatement && child instanceof PyStatement) {
         continue;
       }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
index ac2e312..ccdcf1b 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
@@ -20,7 +20,9 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil;
-import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementListContainer;
+import com.jetbrains.python.psi.PyStatementPart;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -32,17 +34,8 @@
 public class PyPlainEnterProcessor implements EnterProcessor {
   @Nullable
   private static PyStatementList getStatementList(PsiElement psiElement, Editor editor) {
-    if (psiElement instanceof PyStatementPart) {
-      return ((PyStatementPart)psiElement).getStatementList();
-    }
-    else if (psiElement instanceof PyFunction) {
-      return ((PyFunction)psiElement).getStatementList();
-    }
-    else if (psiElement instanceof PyClass) {
-      return ((PyClass)psiElement).getStatementList();
-    }
-    else if (psiElement instanceof PyWithStatement) {
-      return PsiTreeUtil.getChildOfType(psiElement, PyStatementList.class);
+    if (psiElement instanceof PyStatementListContainer) {
+      return ((PyStatementListContainer)psiElement).getStatementList();
     }
     else {
       final CaretModel caretModel = editor.getCaretModel();
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
index f7d877e..de90fa1 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
@@ -25,26 +25,30 @@
 import com.jetbrains.python.psi.PyClass;
 import com.jetbrains.python.psi.PyDecorator;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author Alexey.Ivanov
  */
-public class PyArgumentListFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyArgumentList) {
-      final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
-      if (psiElement.getParent() instanceof PyClass || psiElement.getParent() instanceof PyDecorator) {
-        final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
-        if (lBrace != null && rBrace == null) {
-          final Document document = editor.getDocument();
-          document.insertString(psiElement.getTextRange().getEndOffset(), ")");
-        }
+public class PyArgumentListFixer extends PyFixer<PyArgumentList> {
+  public PyArgumentListFixer() {
+    super(PyArgumentList.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyArgumentList arguments) throws IncorrectOperationException {
+    final PsiElement rBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0);
+    if (arguments.getParent() instanceof PyClass || arguments.getParent() instanceof PyDecorator) {
+      final PsiElement lBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0);
+      if (lBrace != null && rBrace == null) {
+        final Document document = editor.getDocument();
+        document.insertString(arguments.getTextRange().getEndOffset(), ")");
       }
-      else {
-        if (rBrace == null) {
-          final Document document = editor.getDocument();
-          document.insertString(psiElement.getTextRange().getEndOffset(), ")");
-        }
+    }
+    else {
+      if (rBrace == null) {
+        final Document document = editor.getDocument();
+        document.insertString(arguments.getTextRange().getEndOffset(), ")");
       }
     }
   }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
index b9846e1..ce51d6d 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
@@ -17,7 +17,6 @@
 
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
@@ -25,6 +24,9 @@
 import com.jetbrains.python.psi.PyArgumentList;
 import com.jetbrains.python.psi.PyClass;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * Created by IntelliJ IDEA.
@@ -32,21 +34,22 @@
  * Date:   16.04.2010
  * Time:   18:41:08
  */
-public class PyClassFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyClass) {
-      final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
-      if (colon == null) {
-        final PyClass aClass = (PyClass)psiElement;
-        final PyArgumentList argList = PsiTreeUtil.getChildOfType(aClass, PyArgumentList.class);
-        int offset = argList.getTextRange().getEndOffset();
-        String textToInsert = ":";
-        if (aClass.getNameNode() == null) {
-          processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
-          textToInsert = " :";
-        }
-        editor.getDocument().insertString(offset, textToInsert);
+public class PyClassFixer extends PyFixer<PyClass> {
+  public PyClassFixer() {
+    super(PyClass.class);
+  }
+
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyClass pyClass) throws IncorrectOperationException {
+    final PsiElement colon = PyUtil.getFirstChildOfType(pyClass, PyTokenTypes.COLON);
+    if (colon == null) {
+      final PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class);
+      final int offset = sure(argList).getTextRange().getEndOffset();
+      String textToInsert = ":";
+      if (pyClass.getNameNode() == null) {
+        processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
+        textToInsert = " :";
       }
+      editor.getDocument().insertString(offset, textToInsert);
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
index 2885c63..f71c612 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
@@ -25,6 +25,9 @@
 import com.jetbrains.python.psi.PyConditionalStatementPart;
 import com.jetbrains.python.psi.PyExpression;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * Created by IntelliJ IDEA.
@@ -32,31 +35,35 @@
  * Date:   15.04.2010
  * Time:   19:33:14
  */
-public class PyConditionalStatementPartFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyConditionalStatementPart) {
-      final PyConditionalStatementPart conditionalStatementPart = (PyConditionalStatementPart)psiElement;
-      final PyExpression condition = conditionalStatementPart.getCondition();
-      final Document document = editor.getDocument();
-      final PsiElement colon = PyUtil.getChildByFilter(conditionalStatementPart, TokenSet.create(PyTokenTypes.COLON), 0);
-      if (colon == null) {
-        if (condition != null) {
-          final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
-          if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
-            document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
-          }
+public class PyConditionalStatementPartFixer extends PyFixer<PyConditionalStatementPart> {
+  public PyConditionalStatementPartFixer() {
+    super(PyConditionalStatementPart.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyConditionalStatementPart statementPart)
+    throws IncorrectOperationException {
+    final PyExpression condition = statementPart.getCondition();
+    final Document document = editor.getDocument();
+    final PsiElement colon = PyUtil.getFirstChildOfType(statementPart, PyTokenTypes.COLON);
+    if (colon == null) {
+      if (condition != null) {
+        final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
+        if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
+          document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
         }
-        else {
-          final PsiElement keywordToken = PyUtil.getChildByFilter(conditionalStatementPart,
-                                                                  TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD,
-                                                                                  PyTokenTypes.WHILE_KEYWORD), 0);
-          final int offset = keywordToken.getTextRange().getEndOffset();
-          document.insertString(offset, " :");
-          processor.registerUnresolvedError(offset + 1);
-        }
-      } else if (condition == null) {
-          processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
       }
+      else {
+        final TokenSet keywords = TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD, PyTokenTypes.WHILE_KEYWORD);
+        final PsiElement keywordToken = PyUtil.getChildByFilter(statementPart,
+                                                                keywords, 0);
+        final int offset = sure(keywordToken).getTextRange().getEndOffset();
+        document.insertString(offset, " :");
+        processor.registerUnresolvedError(offset + 1);
+      }
+    }
+    else if (condition == null) {
+      processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
index 8e3532c..67d5ff5 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
@@ -17,13 +17,15 @@
 
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyExceptPart;
 import com.jetbrains.python.psi.PyExpression;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * Created by IntelliJ IDEA.
@@ -31,24 +33,26 @@
  * Date:   22.04.2010
  * Time:   18:13:34
  */
-public class PyExceptFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyExceptPart) {
-      PyExceptPart exceptPart = (PyExceptPart)psiElement;
-      final PsiElement colon = PyUtil.getChildByFilter(exceptPart, TokenSet.create(PyTokenTypes.COLON), 0);
-      if (colon == null) {
-        int offset = PyUtil.getChildByFilter(exceptPart,
-                                             TokenSet.create(PyTokenTypes.EXCEPT_KEYWORD), 0).getTextRange().getEndOffset();
-        final PyExpression exceptClass = exceptPart.getExceptClass();
-        if (exceptClass != null) {
-          offset = exceptClass.getTextRange().getEndOffset();
-        }
-        final PyExpression target = exceptPart.getTarget();
-        if (target != null) {
-          offset = target.getTextRange().getEndOffset();
-        }
-        editor.getDocument().insertString(offset, ":");
+public class PyExceptFixer extends PyFixer<PyExceptPart> {
+  public PyExceptFixer() {
+    super(PyExceptPart.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyExceptPart exceptPart) throws IncorrectOperationException {
+    final PsiElement colon = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.COLON);
+    if (colon == null) {
+      final PsiElement exceptToken = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD);
+      int offset = sure(exceptToken).getTextRange().getEndOffset();
+      final PyExpression exceptClass = exceptPart.getExceptClass();
+      if (exceptClass != null) {
+        offset = exceptClass.getTextRange().getEndOffset();
       }
+      final PyExpression target = exceptPart.getTarget();
+      if (target != null) {
+        offset = target.getTextRange().getEndOffset();
+      }
+      editor.getDocument().insertString(offset, ":");
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
index f02831d..0ebdceb 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
@@ -19,6 +19,8 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -26,6 +28,20 @@
  * Date:   15.04.2010
  * Time:   17:10:33
  */
-public interface PyFixer {
-    void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException;
+public abstract class PyFixer<T extends PyElement> {
+  private final Class<T> myClass;
+
+  public PyFixer(@NotNull Class<T> aClass) {
+    myClass = aClass;
+  }
+
+  public final void apply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PsiElement element)
+    throws IncorrectOperationException {
+    if (myClass.isInstance(element)) {
+      //noinspection unchecked
+      doApply(editor, processor, (T)element);
+    }
+  }
+
+  public abstract void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull T element);
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
index 1b8b438..eefe5cd 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
@@ -18,12 +18,13 @@
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyForPart;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * Created by IntelliJ IDEA.
@@ -31,41 +32,42 @@
  * Date:   16.04.2010
  * Time:   16:03:43
  */
-public class PyForPartFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyForPart) {
-      final PyForPart forPart = (PyForPart)psiElement;
-      final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
-      final Document document = editor.getDocument();
-      final PsiElement forToken = PyUtil.getChildByFilter(forPart,
-                                                          TokenSet.create(PyTokenTypes.FOR_KEYWORD), 0);
-      if (colon == null) {
-        String textToInsert = ":";
-        PsiElement sourceOrTarget = forPart.getSource();
-        PsiElement positionToInsert = sourceOrTarget;
-        if (sourceOrTarget == null) {
-          sourceOrTarget = forPart.getTarget();
-          final PsiElement inToken = PyUtil.getChildByFilter(forPart, TokenSet.create(PyTokenTypes.IN_KEYWORD), 0);
-          if (inToken == null) {
-            if (sourceOrTarget == null) {
-              positionToInsert = forToken;
-              textToInsert = "  in :";
-              processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
-            }
-            else {
-              positionToInsert = sourceOrTarget;
-              textToInsert = " in :";
-              processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
-            }
-          }
-          else {
-            positionToInsert = inToken;
-            textToInsert = " :";
+public class PyForPartFixer extends PyFixer<PyForPart> {
+  public PyForPartFixer() {
+    super(PyForPart.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyForPart forPart) {
+    final PsiElement colon = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.COLON);
+    final Document document = editor.getDocument();
+    final PsiElement forToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD);
+    if (colon == null) {
+      String textToInsert = ":";
+      PsiElement sourceOrTarget = forPart.getSource();
+      PsiElement positionToInsert = sourceOrTarget;
+      if (sourceOrTarget == null) {
+        sourceOrTarget = forPart.getTarget();
+        final PsiElement inToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD);
+        if (inToken == null) {
+          if (sourceOrTarget == null) {
+            positionToInsert = sure(forToken);
+            textToInsert = "  in :";
             processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
           }
+          else {
+            positionToInsert = sourceOrTarget;
+            textToInsert = " in :";
+            processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
+          }
         }
-        document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
+        else {
+          positionToInsert = inToken;
+          textToInsert = " :";
+          processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
+        }
       }
+      document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
index f1988e1..ad959f8 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
@@ -18,13 +18,13 @@
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyFunction;
 import com.jetbrains.python.psi.PyParameterList;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -32,16 +32,19 @@
  * Date:   16.04.2010
  * Time:   16:59:07
  */
-public class PyFunctionFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyFunction) {
-      final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
-      if (colon == null) {
-        final PyFunction function = (PyFunction)psiElement;
-        final PyParameterList parameterList = function.getParameterList();
-        final Document document = editor.getDocument();
-        document.insertString(parameterList.getTextRange().getEndOffset(), ":");
-      }
+public class PyFunctionFixer extends PyFixer<PyFunction> {
+  public PyFunctionFixer() {
+    super(PyFunction.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyFunction function)
+    throws IncorrectOperationException {
+    final PsiElement colon = PyUtil.getFirstChildOfType(function, PyTokenTypes.COLON);
+    if (colon == null) {
+      final PyParameterList parameterList = function.getParameterList();
+      final Document document = editor.getDocument();
+      document.insertString(parameterList.getTextRange().getEndOffset(), ":");
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
index 0d8565d..eb97d2b 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
@@ -20,6 +20,7 @@
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -27,10 +28,16 @@
  * Date:   15.04.2010
  * Time:   17:55:46
  */
-public class PyMissingBracesFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyMissingBracesFixer extends PyFixer<PyElement> {
+  public PyMissingBracesFixer() {
+    super(PyElement.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+    throws IncorrectOperationException {
     if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) {
-      PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+      final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
       if (lastChild != null && !"}".equals(lastChild.getText())) {
         editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}");
       }
@@ -38,7 +45,7 @@
     else if (psiElement instanceof PyListLiteralExpression ||
              psiElement instanceof PySliceExpression ||
              psiElement instanceof PySubscriptionExpression) {
-      PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+      final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
       if (lastChild != null && !"]".equals(lastChild.getText())) {
         editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]");
       }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
index 7b5970d..69a06b8 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
@@ -23,6 +23,7 @@
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyParameterList;
 import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -30,19 +31,22 @@
  * Date:   16.04.2010
  * Time:   17:25:46
  */
-public class PyParameterListFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyParameterList) {
-      final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
-      final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
-      if (lBrace == null || rBrace == null) {
-        final Document document = editor.getDocument();
-        if (lBrace == null) {
-          document.insertString(psiElement.getTextRange().getStartOffset(), "(");
-        }
-        else {
-          document.insertString(psiElement.getTextRange().getEndOffset(), ")");
-        }
+public class PyParameterListFixer extends PyFixer<PyParameterList> {
+  public PyParameterListFixer() {
+    super(PyParameterList.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParameterList psiElement) throws IncorrectOperationException {
+    final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
+    final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
+    if (lBrace == null || rBrace == null) {
+      final Document document = editor.getDocument();
+      if (lBrace == null) {
+        document.insertString(psiElement.getTextRange().getStartOffset(), "(");
+      }
+      else {
+        document.insertString(psiElement.getTextRange().getEndOffset(), ")");
       }
     }
   }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
index a055375..582e034 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
@@ -20,6 +20,7 @@
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyParenthesizedExpression;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -27,13 +28,17 @@
  * Date:   15.04.2010
  * Time:   17:42:08
  */
-public class PyParenthesizedFixer implements PyFixer {
-  public void apply(final Editor editor, final PySmartEnterProcessor processor, final PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyParenthesizedExpression) {
-      final PsiElement lastChild = psiElement.getLastChild();
-      if (lastChild != null && !")".equals(lastChild.getText())) {
-        editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), ")");
-      }
+public class PyParenthesizedFixer extends PyFixer<PyParenthesizedExpression> {
+  public PyParenthesizedFixer() {
+    super(PyParenthesizedExpression.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParenthesizedExpression expression)
+    throws IncorrectOperationException {
+    final PsiElement lastChild = expression.getLastChild();
+    if (lastChild != null && !")".equals(lastChild.getText())) {
+      editor.getDocument().insertString(expression.getTextRange().getEndOffset(), ")");
     }
   }
 }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
index 906aecd..3e9925a 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
@@ -17,10 +17,10 @@
 
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
 import com.jetbrains.python.psi.PyStringLiteralExpression;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Created by IntelliJ IDEA.
@@ -28,31 +28,35 @@
  * Date:   15.04.2010
  * Time:   17:17:14
  */
-public class PyStringLiteralFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyStringLiteralExpression) {
-      final String text = psiElement.getText();
-      if (StringUtil.startsWith(text, "\"\"\"")) {
-        final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
-        if (suffixLength != 3) {
-          editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
-        }
+public class PyStringLiteralFixer extends PyFixer<PyStringLiteralExpression> {
+  public PyStringLiteralFixer() {
+    super(PyStringLiteralExpression.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyStringLiteralExpression psiElement)
+    throws IncorrectOperationException {
+    final String text = psiElement.getText();
+    if (StringUtil.startsWith(text, "\"\"\"")) {
+      final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
+      if (suffixLength != 3) {
+        editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
       }
-      else if (StringUtil.startsWith(text, "\'\'\'")) {
-        final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
-        if (suffixLength != 3) {
-          editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
-        }
+    }
+    else if (StringUtil.startsWith(text, "\'\'\'")) {
+      final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
+      if (suffixLength != 3) {
+        editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
       }
-      else if (StringUtil.startsWith(text, "\"")) {
-        if (!StringUtil.endsWith(text, "\"")) {
-          editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
-        }
+    }
+    else if (StringUtil.startsWith(text, "\"")) {
+      if (!StringUtil.endsWith(text, "\"")) {
+        editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
       }
-      else if (StringUtil.startsWith(text, "\'")) {
-        if (!StringUtil.endsWith(text, "\'")) {
-          editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
-        }
+    }
+    else if (StringUtil.startsWith(text, "\'")) {
+      if (!StringUtil.endsWith(text, "\'")) {
+        editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
       }
     }
   }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
index 57bfd39..6aace39 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
@@ -21,10 +21,10 @@
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyFinallyPart;
-import com.jetbrains.python.psi.PyTryPart;
-import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * Created by IntelliJ IDEA.
@@ -32,16 +32,20 @@
  * Date:   16.04.2010
  * Time:   14:25:20
  */
-public class PyUnconditionalStatementPartFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyUnconditionalStatementPartFixer extends PyFixer<PyElement> {
+  public PyUnconditionalStatementPartFixer() {
+    super(PyElement.class);
+  }
+
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+    throws IncorrectOperationException {
     if (PyUtil.instanceOf(psiElement, PyElsePart.class, PyTryPart.class, PyFinallyPart.class)) {
-      final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
+      final PsiElement colon = PyUtil.getFirstChildOfType(psiElement, PyTokenTypes.COLON);
       if (colon == null) {
-        final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement,
-                                                                TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD,
-                                                                                PyTokenTypes.FINALLY_KEYWORD),
-                                                                0);
-        editor.getDocument().insertString(keywordToken.getTextRange().getEndOffset(), ":");
+        final TokenSet keywords = TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD, PyTokenTypes.FINALLY_KEYWORD);
+        final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement, keywords, 0);
+        editor.getDocument().insertString(sure(keywordToken).getTextRange().getEndOffset(), ":");
       }
     }
   }
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
index b6d099e..ec236d9 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
@@ -15,65 +15,59 @@
  */
 package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
 
-import com.intellij.lang.ASTNode;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiElement;
 import com.intellij.util.IncorrectOperationException;
 import com.jetbrains.python.PyTokenTypes;
 import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElementType;
 import com.jetbrains.python.psi.PyExpression;
+import com.jetbrains.python.psi.PyUtil;
 import com.jetbrains.python.psi.PyWithItem;
 import com.jetbrains.python.psi.PyWithStatement;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import static com.jetbrains.python.psi.PyUtil.sure;
 
 /**
  * @author Mikhail Golubev
  */
-public class PyWithFixer implements PyFixer {
-  public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
-    if (psiElement instanceof PyWithStatement) {
-      final PyWithStatement withStatement = (PyWithStatement)psiElement;
-      final PsiElement colonToken = getFirstChildOfType(psiElement, PyTokenTypes.COLON);
-      final PsiElement withToken = getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
-      final Document document = editor.getDocument();
-      if (colonToken == null) {
-        int insertAt = sure(withToken).getTextRange().getEndOffset();
-        String textToInsert = ":";
-        final PyWithItem[] withItems = withStatement.getWithItems();
-        final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
-        if (lastItem == null || lastItem.getExpression() == null) {
-          textToInsert = " :";
-          processor.registerUnresolvedError(insertAt + 1);
-        }
-        else {
-          final PyExpression expression = lastItem.getExpression();
-          insertAt = expression.getTextRange().getEndOffset();
-          final PsiElement asToken = getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
-          if (asToken != null) {
-            insertAt = asToken.getTextRange().getEndOffset();
-            final PyExpression target = lastItem.getTarget();
-            if (target != null) {
-              insertAt = target.getTextRange().getEndOffset();
-            }
-            else {
-              textToInsert = " :";
-              processor.registerUnresolvedError(insertAt + 1);
-            }
-          }
-        }
-        document.insertString(insertAt, textToInsert);
-      }
-    }
+public class PyWithFixer extends PyFixer<PyWithStatement> {
+  public PyWithFixer() {
+    super(PyWithStatement.class);
   }
 
-  @Nullable
-  private static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
-    final ASTNode child = element.getNode().findChildByType(type);
-    return child != null ? child.getPsi() : null;
+  @Override
+  public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException {
+    final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
+    final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
+    final Document document = editor.getDocument();
+    if (colonToken == null) {
+      int insertAt = sure(withToken).getTextRange().getEndOffset();
+      String textToInsert = ":";
+      final PyWithItem[] withItems = withStatement.getWithItems();
+      final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
+      if (lastItem == null || lastItem.getExpression() == null) {
+        textToInsert = " :";
+        processor.registerUnresolvedError(insertAt + 1);
+      }
+      else {
+        final PyExpression expression = lastItem.getExpression();
+        insertAt = expression.getTextRange().getEndOffset();
+        final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
+        if (asToken != null) {
+          insertAt = asToken.getTextRange().getEndOffset();
+          final PyExpression target = lastItem.getTarget();
+          if (target != null) {
+            insertAt = target.getTextRange().getEndOffset();
+          }
+          else {
+            textToInsert = " :";
+            processor.registerUnresolvedError(insertAt + 1);
+          }
+        }
+      }
+      document.insertString(insertAt, textToInsert);
+    }
   }
 }
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 3d77ac4..848818b 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -16,6 +16,10 @@
 package com.jetbrains.python.console;
 
 import com.google.common.base.CharMatcher;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.ExecutionHelper;
@@ -59,11 +63,14 @@
 import com.intellij.openapi.vfs.CharsetToolkit;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.encoding.EncodingManager;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.impl.source.tree.FileElement;
 import com.intellij.remote.RemoteSshProcess;
 import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.ui.content.Content;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IJSwingUtilities;
 import com.intellij.util.PathMappingSettings;
@@ -132,6 +139,9 @@
 
   private static final long APPROPRIATE_TO_WAIT = 60000;
   private PyRemoteSdkCredentials myRemoteCredentials;
+  private ToolWindow myToolWindow;
+
+  private String myConsoleTitle = null;
 
   protected PydevConsoleRunner(@NotNull final Project project,
                                @NotNull Sdk sdk, @NotNull final PyConsoleType consoleType,
@@ -192,8 +202,10 @@
                                                 @NotNull final PyConsoleType consoleType,
                                                 @Nullable final String workingDirectory,
                                                 @NotNull final Map<String, String> environmentVariables,
+                                                @Nullable final ToolWindow toolWindow,
                                                 final String... statements2execute) {
     final PydevConsoleRunner consoleRunner = create(project, sdk, consoleType, workingDirectory, environmentVariables);
+    consoleRunner.setToolWindow(toolWindow);
     consoleRunner.setStatementsToExecute(statements2execute);
     consoleRunner.run();
     return consoleRunner;
@@ -481,6 +493,20 @@
     }
   }
 
+  @Override
+  protected String constructConsoleTitle(@NotNull String consoleTitle) {
+    if (myConsoleTitle == null) {
+      myConsoleTitle = super.constructConsoleTitle(consoleTitle);
+    }
+    return myConsoleTitle;
+  }
+
+  @Override
+  protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
+    PythonConsoleToolWindow terminalView = PythonConsoleToolWindow.getInstance(getProject());
+    terminalView.init(getToolWindow(), contentDescriptor);
+  }
+
   protected AnAction createRerunAction() {
     return new RestartAction(this);
   }
@@ -583,9 +609,32 @@
   }
 
   @Override
-  protected AnAction createCloseAction(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
-    final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, myDescriptor);
-    return createConsoleStoppingAction(generalCloseAction);
+  protected AnAction createCloseAction(Executor defaultExecutor, final RunContentDescriptor descriptor) {
+    final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, descriptor);
+
+    final AnAction stopAction = new DumbAwareAction() {
+      @Override
+      public void update(AnActionEvent e) {
+        generalCloseAction.update(e);
+      }
+
+      @Override
+      public void actionPerformed(AnActionEvent e) {
+        e = stopConsole(e);
+
+        clearContent(descriptor);
+
+        generalCloseAction.actionPerformed(e);
+      }
+    };
+    stopAction.copyFrom(generalCloseAction);
+    return stopAction;
+  }
+
+  private void clearContent(RunContentDescriptor descriptor) {
+    Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName());
+    assert content != null;
+    getToolWindow().getContentManager().removeContent(content, true);
   }
 
   private AnAction createConsoleStoppingAction(final AnAction generalStopAction) {
@@ -597,26 +646,31 @@
 
       @Override
       public void actionPerformed(AnActionEvent e) {
-        if (myPydevConsoleCommunication != null) {
-          final AnActionEvent furtherActionEvent =
-            new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
-                              e.getPresentation(), e.getActionManager(), e.getModifiers());
-          try {
-            closeCommunication();
-            // waiting for REPL communication before destroying process handler
-            Thread.sleep(300);
-          }
-          catch (Exception ignored) {
-            // Ignore
-          }
-          generalStopAction.actionPerformed(furtherActionEvent);
-        }
+        e = stopConsole(e);
+
+        generalStopAction.actionPerformed(e);
       }
     };
     stopAction.copyFrom(generalStopAction);
     return stopAction;
   }
 
+  private AnActionEvent stopConsole(AnActionEvent e) {
+    if (myPydevConsoleCommunication != null) {
+      e = new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
+                            e.getPresentation(), e.getActionManager(), e.getModifiers());
+      try {
+        closeCommunication();
+        // waiting for REPL communication before destroying process handler
+        Thread.sleep(300);
+      }
+      catch (Exception ignored) {
+        // Ignore
+      }
+    }
+    return e;
+  }
+
   protected AnAction createSplitLineAction() {
 
     class ConsoleSplitLineAction extends EditorAction {
@@ -738,6 +792,17 @@
     }
   }
 
+  public ToolWindow getToolWindow() {
+    if (myToolWindow == null) {
+      myToolWindow = ToolWindowManager.getInstance(getProject()).getToolWindow(PythonConsoleToolWindowFactory.ID);
+    }
+    return myToolWindow;
+  }
+
+  public void setToolWindow(ToolWindow toolWindow) {
+    myToolWindow = toolWindow;
+  }
+
   public interface ConsoleListener {
     void handleConsoleInitialized(LanguageConsoleView consoleView);
   }
@@ -889,4 +954,21 @@
 
     return session;
   }
+
+  @Override
+  protected List<String> getActiveConsoleNames(final String consoleTitle) {
+    return FluentIterable.from(
+      Lists.newArrayList(PythonConsoleToolWindow.getInstance(getProject()).getToolWindow().getContentManager().getContents())).transform(
+      new Function<Content, String>() {
+        @Override
+        public String apply(Content input) {
+          return input.getDisplayName();
+        }
+      }).filter(new Predicate<String>() {
+      @Override
+      public boolean apply(String input) {
+        return input.contains(consoleTitle);
+      }
+    }).toList();
+  }
 }
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
new file mode 100644
index 0000000..e8c50e4
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
@@ -0,0 +1,127 @@
+package com.jetbrains.python.console;
+
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.SimpleToolWindowPanel;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
+import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
+import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindow {
+
+  private final Project myProject;
+
+  private boolean myInitialized = false;
+
+  public PythonConsoleToolWindow(Project project) {
+    myProject = project;
+  }
+
+  public static PythonConsoleToolWindow getInstance(@NotNull Project project) {
+    return project.getComponent(PythonConsoleToolWindow.class);
+  }
+
+
+  public void init(final @NotNull ToolWindow toolWindow, final @NotNull RunContentDescriptor contentDescriptor) {
+    addContent(toolWindow, contentDescriptor);
+
+    if (!myInitialized) {
+      doInit(toolWindow);
+    }
+  }
+
+  private void doInit(final ToolWindow toolWindow) {
+    myInitialized = true;
+
+    toolWindow.setToHideOnEmptyContent(true);
+
+    ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerListener() {
+      @Override
+      public void toolWindowRegistered(@NotNull String id) {
+      }
+
+      @Override
+      public void stateChanged() {
+        ToolWindow window = getToolWindow();
+        if (window != null) {
+          boolean visible = window.isVisible();
+          if (visible && toolWindow.getContentManager().getContentCount() == 0) {
+            RunPythonConsoleAction.runPythonConsole(myProject, null, toolWindow);
+          }
+        }
+      }
+    });
+  }
+
+  private static void addContent(ToolWindow toolWindow, RunContentDescriptor contentDescriptor) {
+    toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
+
+    Content content = toolWindow.getContentManager().findContent(contentDescriptor.getDisplayName());
+    if (content == null) {
+      content = createContent(contentDescriptor);
+      toolWindow.getContentManager().addContent(content);
+    }
+    else {
+      SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+      resetContent(contentDescriptor, panel, content);
+    }
+
+    toolWindow.getContentManager().setSelectedContent(content);
+  }
+
+  public ToolWindow getToolWindow() {
+    return ToolWindowManager.getInstance(myProject).getToolWindow(PythonConsoleToolWindowFactory.ID);
+  }
+
+  private static Content createContent(final @NotNull RunContentDescriptor contentDescriptor) {
+    SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+
+    final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, contentDescriptor.getDisplayName(), false);
+    content.setCloseable(true);
+
+    resetContent(contentDescriptor, panel, content);
+
+    return content;
+  }
+
+  private static void resetContent(RunContentDescriptor contentDescriptor, SimpleToolWindowPanel panel, Content content) {
+    panel.setContent(contentDescriptor.getComponent());
+    //panel.addFocusListener(createFocusListener(toolWindow));
+
+    content.setComponent(panel);
+    content.setPreferredFocusableComponent(contentDescriptor.getComponent());
+  }
+
+  private static FocusListener createFocusListener(final ToolWindow toolWindow) {
+    return new FocusListener() {
+      @Override
+      public void focusGained(FocusEvent e) {
+        JComponent component = getComponentToFocus(toolWindow);
+        if (component != null) {
+          component.requestFocusInWindow();
+        }
+      }
+
+      @Override
+      public void focusLost(FocusEvent e) {
+
+      }
+    };
+  }
+
+  private static JComponent getComponentToFocus(ToolWindow window) {
+    return window.getContentManager().getComponent();
+  }
+}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
new file mode 100644
index 0000000..f042a53
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package com.jetbrains.python.console;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowFactory;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindowFactory implements ToolWindowFactory, DumbAware {
+  public static final String ID = "Python Console";
+
+  @Override
+  public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+    RunPythonConsoleAction.runPythonConsole(project, null, toolWindow);
+  }
+}
diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
index 02a153f..566adea 100644
--- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
+++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
@@ -32,6 +32,7 @@
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
 import com.intellij.util.PathMappingSettings;
 import com.jetbrains.python.buildout.BuildoutFacet;
 import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
@@ -42,6 +43,7 @@
 import com.jetbrains.python.sdk.PythonSdkType;
 import icons.PythonIcons;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.List;
@@ -77,11 +79,11 @@
 
   public void actionPerformed(final AnActionEvent e) {
     final Project project = e.getData(CommonDataKeys.PROJECT);
-    runPythonConsole(project, e.getData(LangDataKeys.MODULE));
+    runPythonConsole(project, e.getData(LangDataKeys.MODULE), null);
   }
 
   @NotNull
-  public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule) {
+  public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule, @Nullable ToolWindow toolWindow) {
     assert project != null : "Project is null";
 
     Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule);
@@ -152,7 +154,7 @@
     envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
 
     return PydevConsoleRunner
-      .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, setupFragment);
+      .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, toolWindow, setupFragment);
   }
 
   public static PathMappingSettings getMappings(Project project, Sdk sdk) {
diff --git a/python/src/com/jetbrains/python/documentation/EpydocString.java b/python/src/com/jetbrains/python/documentation/EpydocString.java
index 132ef49..3d0fc3e 100644
--- a/python/src/com/jetbrains/python/documentation/EpydocString.java
+++ b/python/src/com/jetbrains/python/documentation/EpydocString.java
@@ -44,6 +44,13 @@
     "precondition", "postcondition", "invariant", "author", "organization", "copyright", "license", "contact", "summary", "see"
   };
 
+  /**
+   * Empty doc (for {@link #createParameterType(String, String)} probably)
+   */
+  public EpydocString() {
+    this("");
+  }
+
   public EpydocString(@NotNull String docstringText) {
     super(docstringText, "@");
   }
diff --git a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
index d09af58..c050690 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
@@ -87,8 +87,6 @@
     for (PyParameter functionParam : function.getParameterList().getParameters()) {
       String paramName = functionParam.getName();
       if (!functionParam.isSelf() && !StringUtil.isEmpty(paramName)) {
-        assert paramName != null;
-
         String type = signature != null ? signature.getArgTypeQualifiedName(paramName) : null;
 
         if (type != null) {
@@ -140,12 +138,9 @@
 
       final VirtualFile virtualFile = myFile.getVirtualFile();
       if (virtualFile == null) return;
-      OpenFileDescriptor descriptor = new OpenFileDescriptor(
-        myProject, virtualFile, myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
-      );
+      OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, virtualFile, myDocStringExpression.getTextOffset());
       Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
       if (targetEditor != null) {
-        targetEditor.getCaretModel().moveToOffset(myDocStringExpression.getTextOffset());
         TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
       }
     }
@@ -298,7 +293,7 @@
     if (myDocStringOwner instanceof PyFunction) {
       final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
       final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
-      if (document != null && statementList != null && myFunction != null && statementList.getStatements().length != 0
+      if (document != null && myFunction != null && statementList.getStatements().length != 0
           && document.getLineNumber(statementList.getTextOffset()) != document.getLineNumber(myFunction.getTextOffset())) {
         whitespace = PsiTreeUtil.getPrevSiblingOfType(statementList, PsiWhiteSpace.class);
       }
@@ -411,7 +406,7 @@
       final PyStatementList list = myFunction.getStatementList();
       final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
 
-      if (document != null && list != null) {
+      if (document != null) {
         if (document.getLineNumber(list.getTextOffset()) == document.getLineNumber(myFunction.getTextOffset()) ||
             list.getStatements().length == 0) {
           PyFunction func = elementGenerator.createFromText(LanguageLevel.forElement(myFunction),
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
index 6ea6540..49a17ef 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
@@ -15,7 +15,9 @@
  */
 package com.jetbrains.python.documentation;
 
-import com.intellij.openapi.components.*;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleServiceManager;
 import com.intellij.openapi.util.text.StringUtil;
@@ -27,6 +29,7 @@
 import com.jetbrains.python.psi.PyTargetExpression;
 import com.jetbrains.python.psi.impl.PyPsiUtils;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
@@ -54,7 +57,7 @@
 
   private boolean isFormat(PsiFile file, final String format) {
     if (file instanceof PyFile) {
-      PyTargetExpression expr = ((PyFile) file).findTopLevelAttribute(PyNames.DOCFORMAT);
+      PyTargetExpression expr = ((PyFile)file).findTopLevelAttribute(PyNames.DOCFORMAT);
       if (expr != null) {
         String docformat = PyPsiUtils.strValue(expr.findAssignedValue());
         if (docformat != null) {
@@ -88,4 +91,21 @@
   public void loadState(PyDocumentationSettings state) {
     XmlSerializerUtil.copyBean(state, this);
   }
+
+  /**
+   * TODO: Use this factory for the whole document infrastructure to simplify new documentation engine support
+   * Factory that returns appropriate instance of {@link StructuredDocStringBase} if specificed
+   *
+   * @return instance or null if no doctype os set
+   */
+  @Nullable
+  public StructuredDocStringBase getDocString() {
+    if (myDocStringFormat.equals(DocStringFormat.EPYTEXT)) {
+      return new EpydocString();
+    }
+    if (myDocStringFormat.equals(DocStringFormat.REST)) {
+      return new SphinxDocString();
+    }
+    return null;
+  }
 }
diff --git a/python/src/com/jetbrains/python/documentation/SphinxDocString.java b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
index ae5c705..c04e1c9 100644
--- a/python/src/com/jetbrains/python/documentation/SphinxDocString.java
+++ b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
@@ -31,7 +31,14 @@
                                                    ":type", ":raise", ":raises", ":var", ":cvar", ":ivar",
                                                    ":return", ":returns", ":rtype", ":except", ":exception" };
 
-  public SphinxDocString(@NotNull String docstringText) {
+  /**
+   * Empty doc (for {@link #createParameterType(String, String)} probably)
+   */
+  public SphinxDocString() {
+    this("");
+  }
+
+  public SphinxDocString(@NotNull final String docstringText) {
     super(docstringText, ":");
   }
 
diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
index 9f6cecb..36b70ec 100644
--- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
+++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
@@ -43,18 +43,21 @@
   private static final Pattern RE_LOOSE_TAG_LINE = Pattern.compile("([a-z]+) ([a-zA-Z_0-9]*):?([^:]*)");
   private static final Pattern RE_ARG_TYPE = Pattern.compile("(.*) ([a-zA-Z_0-9]+)");
 
-  public static String[] PARAM_TAGS = new String[] { "param", "parameter", "arg", "argument" };
-  public static String[] PARAM_TYPE_TAGS = new String[] { "type" };
-  public static String[] VARIABLE_TAGS = new String[] { "ivar", "cvar", "var" };
+  public static String[] PARAM_TAGS = new String[]{"param", "parameter", "arg", "argument"};
+  public static String[] PARAM_TYPE_TAGS = new String[]{"type"};
+  public static String[] VARIABLE_TAGS = new String[]{"ivar", "cvar", "var"};
 
-  public static String[] RAISES_TAGS = new String[] { "raises", "raise", "except", "exception" };
-  public static String[] RETURN_TAGS = new String[] { "return", "returns" };
+  public static String[] RAISES_TAGS = new String[]{"raises", "raise", "except", "exception"};
+  public static String[] RETURN_TAGS = new String[]{"return", "returns"};
+  @NotNull
+  private final String myTagPrefix;
 
   public enum ReferenceType {PARAMETER, PARAMETER_TYPE, KEYWORD, VARIABLE, CLASS_VARIABLE, INSTANCE_VARIABLE}
 
   public static String TYPE = "type";
 
   protected StructuredDocStringBase(@NotNull String docStringText, String tagPrefix) {
+    myTagPrefix = tagPrefix;
     final Substring docString = new Substring(docStringText);
     final List<Substring> lines = docString.splitLines();
     final int nlines = lines.size();
@@ -74,6 +77,12 @@
   }
 
   @Override
+  @NotNull
+  public String createParameterType(@NotNull final String name, @NotNull final String type) {
+    return myTagPrefix + TYPE + String.format(" %s %s", name, type);
+  }
+
+  @Override
   public String getDescription() {
     return myDescription;
   }
@@ -82,8 +91,9 @@
   public String getSummary() {
     final List<String> strings = StringUtil.split(StringUtil.trimLeading(myDescription), "\n", true, false);
     if (strings.size() > 1) {
-      if (strings.get(1).isEmpty())
+      if (strings.get(1).isEmpty()) {
         return strings.get(0);
+      }
     }
     return "";
   }
@@ -216,8 +226,8 @@
 
   @Override
   @Nullable
-  public Substring getParamByNameAndKind(@NotNull String name, String kind)  {
-    for (Substring s: getTagArguments(kind)) {
+  public Substring getParamByNameAndKind(@NotNull String name, String kind) {
+    for (Substring s : getTagArguments(kind)) {
       if (name.equals(s.getValue())) {
         return s;
       }
diff --git a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
index 4584f06..6c86e72 100644
--- a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
+++ b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
@@ -78,12 +78,12 @@
 
   protected final void registerProblem(@Nullable final PsiElement element,
                                        @NotNull final String message,
-                                       @NotNull final LocalQuickFix quickFix) {
+                                       @NotNull final LocalQuickFix... quickFixes) {
     if (element == null || element.getTextLength() == 0) {
       return;
     }
     if (myHolder != null) {
-      myHolder.registerProblem(element, message, quickFix);
+      myHolder.registerProblem(element, message, quickFixes);
     }
   }
 
diff --git a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
index 8b6143f..b2ad485 100644
--- a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
@@ -99,7 +99,7 @@
           final ScopeOwner nextOwner = ScopeUtil.getScopeOwner(owner);
           if (nextOwner != null) {
             final ResolveProcessor processor = new ResolveProcessor(name);
-            PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null);
+            PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null, null);
             final PsiElement resolved = processor.getResult();
             if (resolved != null) {
               final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(resolved, PyComprehensionElement.class);
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
index 0ae7ac1..708e917 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
@@ -27,6 +27,7 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+//TODO: Remove pydoc aswell
 public class PyRemoveArgumentQuickFix implements LocalQuickFix {
 
   @NotNull
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 877da8d..cd4e582 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -901,6 +901,20 @@
   }
 
   /**
+   * Returns first child psi element with specified element type or {@code null} if no such element exists.
+   * Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
+   *
+   * @param element tree parent node
+   * @param type    element type expected
+   * @return child element described
+   */
+  @Nullable
+  public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
+    final ASTNode child = element.getNode().findChildByType(type);
+    return child != null ? child.getPsi() : null;
+  }
+
+  /**
    * If argument is a PsiDirectory, turn it into a PsiFile that points to __init__.py in that directory.
    * If there's no __init__.py there, null is returned, there's no point to resolve to a dir which is not a package.
    * Alas, resolve() and multiResolve() can't return anything but a PyFile or PsiFileImpl.isPsiUpToDate() would fail.
@@ -1645,6 +1659,11 @@
     return Collections2.filter(pyMemberInfos, new ObjectPredicate(false));
   }
 
+  public static boolean isStarImportableFrom(@NotNull String name, @NotNull PyFile file) {
+    final List<String> dunderAll = file.getDunderAll();
+    return dunderAll != null ? dunderAll.contains(name) : !name.startsWith("_");
+  }
+
   /**
    * Filters only pyclass object (new class)
    */
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
index 744dc97..bb0e29f 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
@@ -24,6 +24,7 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.PsiWhiteSpace;
 import com.intellij.psi.impl.PsiFileFactoryImpl;
 import com.intellij.psi.impl.source.tree.LeafPsiElement;
 import com.intellij.psi.tree.TokenSet;
@@ -86,8 +87,9 @@
   }
 
 
+  @Override
   public PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped) {
-    return createStringLiteralFromString(null, unescaped);
+    return createStringLiteralFromString(null, unescaped, true);
   }
 
   public PyStringLiteralExpression createStringLiteral(@NotNull PyStringLiteralExpression oldElement, @NotNull String unescaped) {
@@ -100,7 +102,11 @@
     }
   }
 
-  public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, @NotNull String unescaped) {
+
+  @Override
+  public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination,
+                                                                 @NotNull String unescaped,
+                                                                 final boolean preferUTF8) {
     boolean useDouble = !unescaped.contains("\"");
     boolean useMulti = unescaped.matches(".*(\r|\n).*");
     String quotes;
@@ -115,7 +121,7 @@
     VirtualFile vfile = destination == null ? null : destination.getVirtualFile();
     Charset charset;
     if (vfile == null) {
-      charset = Charset.forName("US-ASCII");
+      charset = (preferUTF8 ? Charset.forName("UTF-8") : Charset.forName("US-ASCII"));
     }
     else {
       charset = vfile.getCharset();
@@ -191,7 +197,7 @@
     final LeafPsiElement[] leafs = PsiTreeUtil.getChildrenOfType(list, LeafPsiElement.class);
     if (leafs != null) {
       final Deque<LeafPsiElement> commas = Queues.newArrayDeque(Collections2.filter(Arrays.asList(leafs), COMMAS_ONLY));
-      if (! commas.isEmpty()) {
+      if (!commas.isEmpty()) {
         final LeafPsiElement lastComma = commas.getLast();
         if (PsiTreeUtil.getNextSiblingOfType(lastComma, PyExpression.class) == null) { //Comma has no expression after it
           lastComma.delete();
@@ -297,7 +303,7 @@
                                    AccessDirection accessDirection) {
     String propertyText;
     if (accessDirection == AccessDirection.DELETE) {
-      propertyText = "@" + propertyName +".deleter\ndef " + propertyName + "(self):\n  del self." + fieldName;
+      propertyText = "@" + propertyName + ".deleter\ndef " + propertyName + "(self):\n  del self." + fieldName;
     }
     else if (accessDirection == AccessDirection.WRITE) {
       propertyText = "@" + propertyName + ".setter\ndef " + propertyName + "(self, value):\n  self." + fieldName + " = value";
@@ -415,6 +421,12 @@
                           PyExpressionStatement.class, content + "\n");
   }
 
+  @NotNull
+  @Override
+  public PsiElement createNewLine() {
+    return createFromText(LanguageLevel.getDefault(), PsiWhiteSpace.class, " \n\n ");
+  }
+
   private static class CommasOnly extends NotNullPredicate<LeafPsiElement> {
     @Override
     protected boolean applyNotNull(@NotNull final LeafPsiElement input) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
index ddd02d5..8c69893 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
@@ -15,26 +15,16 @@
  */
 package com.jetbrains.python.psi.impl;
 
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
 import com.intellij.lang.ASTNode;
+import com.jetbrains.python.psi.PyElsePart;
 
 /**
  * User: dcheryasov
  * Date: Mar 15, 2009 9:40:35 PM
  */
-public class PyElsePartImpl extends PyElementImpl implements PyElsePart {
+public class PyElsePartImpl extends PyStatementPartImpl implements PyElsePart {
   
   public PyElsePartImpl(ASTNode astNode) {
     super(astNode);
   }
-
-  public PyStatementList getStatementList() {
-    ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
-    if (n != null) {
-      return (PyStatementList)n.getPsi();
-    }
-    return null;
-  }
 }
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
index 030fcfe..02b7906 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
@@ -477,8 +477,9 @@
     if (starImportSource != null) {
       starImportSource = PyUtil.turnDirIntoInit(starImportSource);
       if (starImportSource instanceof PyFile) {
-        final PsiElement result = ((PyFile)starImportSource).getElementNamed(name);
-        if (result != null) {
+        final PyFile file = (PyFile)starImportSource;
+        final PsiElement result = file.getElementNamed(name);
+        if (result != null && PyUtil.isStarImportableFrom(name, file)) {
           return result;
         }
       }
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
index e0cdf87..9d2be0f 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
@@ -23,6 +23,7 @@
 import com.intellij.util.ArrayUtil;
 import com.jetbrains.python.PyNames;
 import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.documentation.StructuredDocStringBase;
 import com.jetbrains.python.psi.*;
 import org.jetbrains.annotations.NotNull;
 
@@ -82,14 +83,21 @@
   /**
    * Adds docstring to function. Provide doc with out of comment blocks.
    *
+   *
    * @param docString doc
    */
   public void docString(@NotNull final String docString) {
-    myDocStringLines = StringUtil.splitByLines(removeIndent(docString));
+    final String[] stringsToAdd = StringUtil.splitByLines(removeIndent(docString));
+    if (myDocStringLines == null) {
+      myDocStringLines = stringsToAdd;
+    }
+    else {
+      myDocStringLines = ArrayUtil.mergeArrays(myDocStringLines, stringsToAdd);
+    }
   }
 
   @NotNull
-  private String removeIndent(@NotNull final String string) {
+  private static String removeIndent(@NotNull final String string) {
     return INDENT_REMOVE_PATTERN.matcher(string).replaceAll("");
   }
 
@@ -97,6 +105,21 @@
     myName = name;
   }
 
+  /**
+   * Adds param and its type to doc
+   * @param name param name
+   * @param type param type
+   * @param docStyle what docstyle to use to doc param type
+   */
+  @NotNull
+  public PyFunctionBuilder parameterWithType(@NotNull final String name,
+                                             @NotNull final String type,
+                                             @NotNull final StructuredDocStringBase docStyle) {
+    parameter(name);
+    docString(docStyle.createParameterType(name, type));
+    return this;
+  }
+
   public PyFunctionBuilder parameter(String baseName) {
     String name = baseName;
     int uniqueIndex = 0;
@@ -173,8 +196,9 @@
 
   /**
    * Adds decorator with argument
+   *
    * @param decoratorName decorator name
-   * @param value its argument
+   * @param value         its argument
    */
   public void decorate(@NotNull final String decoratorName, @NotNull final String value) {
     decorate(decoratorName);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
index 4011c23..88c3134 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
@@ -52,11 +52,8 @@
       for (PsiElement importedFile : new HashSet<PsiElement>(importedFiles)) { // resolver gives lots of duplicates
         final PsiElement source = PyUtil.turnDirIntoInit(importedFile);
         if (source instanceof PyFile) {
-          Iterable<PyElement> declaredNames = ((PyFile)source).iterateNames();
-          if (((PyFile)source).getDunderAll() == null) {
-            declaredNames = excludeUnderscoredNames(declaredNames);
-          }
-          chain.add(declaredNames);
+          final PyFile sourceFile = (PyFile)source;
+          chain.add(filterStarImportableNames(sourceFile.iterateNames(), sourceFile));
         }
       }
       return chain;
@@ -64,15 +61,13 @@
     return Collections.emptyList();
   }
 
-  private static Iterable<PyElement> excludeUnderscoredNames(Iterable<PyElement> declaredNames) {
+  @NotNull
+  private static Iterable<PyElement> filterStarImportableNames(@NotNull Iterable<PyElement> declaredNames, @NotNull final PyFile file) {
     return Iterables.filter(declaredNames, new Predicate<PyElement>() {
       @Override
       public boolean apply(@Nullable PyElement input) {
         final String name = input != null ? input.getName() : null;
-        if (name != null && name.startsWith("_")) {
-          return false;
-        }
-        return true;
+        return name != null && PyUtil.isStarImportableFrom(name, file);
       }
     });
   }
@@ -93,11 +88,7 @@
           final List<? extends RatedResolveResult> results = moduleType.resolveMember(name, null, AccessDirection.READ,
                                                                                       PyResolveContext.defaultContext());
           final PsiElement result = results != null && !results.isEmpty() ? results.get(0).getElement() : null;
-          if (result != null) {
-            final List<String> all = sourceFile.getDunderAll();
-            if (all != null ? !all.contains(name) : name.startsWith("_")) {
-              continue;
-            }
+          if (result != null && PyUtil.isStarImportableFrom(name, sourceFile) ) {
             return result;
           }
         }
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
index 46e9a78..7454d67 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
@@ -15,10 +15,11 @@
  */
 package com.jetbrains.python.psi.impl;
 
-import com.jetbrains.python.psi.PyStatementPart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
 import com.intellij.lang.ASTNode;
+import com.jetbrains.python.PyElementTypes;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementPart;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Abstract statement part implementation; extracts the statements list.
@@ -30,11 +31,8 @@
     super(astNode);
   }
 
+  @NotNull
   public PyStatementList getStatementList() {
-    ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
-    if (n != null) {
-      return (PyStatementList)n.getPsi();
-    }
-    return null;
+    return childToPsiNotNull(PyElementTypes.STATEMENT_LIST);
   }
 }
diff --git a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
index 98cd8e5..3af3771 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
@@ -63,6 +63,14 @@
   }
 
   public PyWithItem[] getWithItems() {
-    return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY); 
+    return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY);
+  }
+
+  @Override
+  @NotNull
+  public PyStatementList getStatementList() {
+    final PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST);
+    assert statementList != null : "Statement list missing for with statement " + getText();
+    return statementList;
   }
 }
diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
index da8c0d6..838a4db 100644
--- a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
+++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
@@ -38,6 +38,11 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 /**
  * Ref resolution routines.
  * User: dcheryasov
@@ -106,16 +111,17 @@
         owner = outerScopeOwner;
       }
     }
-    scopeCrawlUp(processor, owner, originalOwner, name, roof);
+    scopeCrawlUp(processor, owner, originalOwner, name, roof, realContext);
   }
 
   public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @NotNull ScopeOwner scopeOwner, @Nullable String name,
                                   @Nullable PsiElement roof) {
-    scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof);
+    scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof, null);
   }
 
   public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @Nullable ScopeOwner scopeOwner,
-                                  @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof) {
+                                  @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof,
+                                  @Nullable final PsiElement anchor) {
     while (scopeOwner != null) {
       if (!(scopeOwner instanceof PyClass) || scopeOwner == originalScopeOwner) {
         final Scope scope = ControlFlowCache.getScope(scopeOwner);
@@ -136,7 +142,31 @@
             }
           }
         }
-        for (NameDefiner definer : scope.getImportedNameDefiners()) {
+        List<NameDefiner> definers = new ArrayList<NameDefiner>(scope.getImportedNameDefiners());
+        if (anchor != null && ScopeUtil.getScopeOwner(anchor) == scopeOwner) {
+          final Comparator<NameDefiner> nearestDefinerComparator = new Comparator<NameDefiner>() {
+            @Override
+            public int compare(NameDefiner a, NameDefiner b) {
+              final boolean aIsBefore = PyPsiUtils.isBefore(a, anchor);
+              final boolean bIsBefore = PyPsiUtils.isBefore(b, anchor);
+              final int diff = a.getTextOffset() - b.getTextOffset();
+              if (aIsBefore && bIsBefore) {
+                return -diff;
+              }
+              else if (aIsBefore) {
+                return -1;
+              }
+              else if (bIsBefore) {
+                return 1;
+              }
+              else {
+                return diff;
+              }
+            }
+          };
+          Collections.sort(definers, nearestDefinerComparator);
+        }
+        for (NameDefiner definer : definers) {
           if (!processor.execute(definer, ResolveState.initial())) {
             found = true;
             break;
diff --git a/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
new file mode 100644
index 0000000..2af1a64
--- /dev/null
+++ b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package com.jetbrains.python.run;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
+import com.intellij.util.PathMappingSettings;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public class PyRemoteTracebackFilter extends PythonTracebackFilter {
+  private final RemoteProcessHandlerBase myHandler;
+
+  public PyRemoteTracebackFilter(Project project, String workingDirectory, RemoteProcessHandlerBase remoteProcessHandler) {
+    super(project, workingDirectory);
+
+    myHandler = remoteProcessHandler;
+  }
+
+  @Override
+  @Nullable
+  protected VirtualFile findFileByName(String fileName) {
+    VirtualFile vFile = super.findFileByName(fileName);
+    if (vFile != null) {
+      return vFile;
+    }
+    for (PathMappingSettings.PathMapping m : myHandler.getMappingSettings().getPathMappings()) {
+      if (m.canReplaceRemote(fileName)) {
+        VirtualFile file = LocalFileSystem.getInstance().findFileByPath(m.mapToLocal(fileName));
+        if (file != null && file.exists()) {
+          return file;
+        }
+      }
+    }
+
+
+
+    return null;
+  }
+}
diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
index 216e68c..a4d1718 100644
--- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
@@ -47,6 +47,7 @@
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.vfs.JarFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
 import com.intellij.util.PlatformUtils;
 import com.intellij.util.containers.HashMap;
 import com.jetbrains.python.PythonHelpersLocator;
@@ -80,7 +81,9 @@
   public static final String GROUP_DEBUGGER = "Debugger";
   public static final String GROUP_SCRIPT = "Script";
   private final AbstractPythonRunConfiguration myConfig;
-  private final List<Filter> myFilters;
+
+  private final List<Filter> myFilters = Lists.<Filter>newArrayList(new UrlFilter());
+
   private Boolean myMultiprocessDebug = null;
 
   public boolean isDebug() {
@@ -99,15 +102,9 @@
     return serverSocket;
   }
 
-  public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
+  public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
     super(env);
     myConfig = runConfiguration;
-    myFilters = Lists.newArrayList(filters);
-    addDefaultFilters();
-  }
-
-  protected void addDefaultFilters() {
-    myFilters.add(new UrlFilter());
   }
 
   @Nullable
@@ -134,10 +131,23 @@
   protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
     throws ExecutionException {
     final ConsoleView consoleView = createConsoleBuilder(project).filters(myFilters).getConsole();
+
+    addTracebackFilter(project, consoleView, processHandler);
+
     consoleView.attachToProcess(processHandler);
     return consoleView;
   }
 
+  protected void addTracebackFilter(Project project, ConsoleView consoleView, ProcessHandler processHandler) {
+    if (PySdkUtil.isRemote(myConfig.getSdk())) {
+      assert processHandler instanceof RemoteProcessHandlerBase;
+      consoleView.addMessageFilter(new PyRemoteTracebackFilter(project, myConfig.getWorkingDirectory(), (RemoteProcessHandlerBase) processHandler));
+    }
+    else {
+      consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfig.getWorkingDirectory()));
+    }
+  }
+
   private TextConsoleBuilder createConsoleBuilder(Project project) {
     if (isDebug()) {
       return new PyDebugConsoleBuilder(project, PythonSdkType.findSdkByPath(myConfig.getInterpreterPath()));
diff --git a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
index bbba444..118c27b 100644
--- a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
+++ b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
@@ -15,11 +15,9 @@
  */
 package com.jetbrains.python.run;
 
-import com.google.common.collect.Lists;
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.Executor;
 import com.intellij.execution.configurations.*;
-import com.intellij.execution.filters.Filter;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.openapi.components.PathMacroManager;
 import com.intellij.openapi.options.SettingsEditor;
@@ -40,7 +38,6 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
-import java.util.List;
 
 /**
  * @author yole
@@ -64,10 +61,7 @@
   }
 
   public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
-    List<Filter> filters = Lists.newArrayList();
-    filters.add(new PythonTracebackFilter(getProject(), getWorkingDirectory()));
-
-    return new PythonScriptCommandLineState(this, env, filters);
+    return new PythonScriptCommandLineState(this, env);
   }
 
   public void checkConfiguration() throws RuntimeConfigurationException {
diff --git a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
index 53ef554..81d2daa 100644
--- a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
@@ -18,20 +18,17 @@
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.configurations.ParametersList;
 import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.openapi.util.text.StringUtil;
 
-import java.util.List;
-
 /**
  * @author yole
  */
 public class PythonScriptCommandLineState extends PythonCommandLineState {
   private final PythonRunConfiguration myConfig;
 
-  public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
-    super(runConfiguration, env, filters);
+  public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
+    super(runConfiguration, env);
     myConfig = runConfiguration;
   }
 
diff --git a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
index e3bd879..73a3abd 100644
--- a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
+++ b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
@@ -51,10 +51,7 @@
     if (matcher.find()) {
       String fileName = matcher.group(1).replace('\\', '/');
       int lineNumber = Integer.parseInt(matcher.group(2));
-      VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
-      if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
-        vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName)); 
-      }
+      VirtualFile vFile = findFileByName(fileName);
       
       if (vFile != null) {
         OpenFileHyperlinkInfo hyperlink = new OpenFileHyperlinkInfo(myProject, vFile, lineNumber - 1);
@@ -66,4 +63,13 @@
     }
     return null;
   }
+
+  @Nullable
+  protected VirtualFile findFileByName(String fileName) {
+    VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
+    if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
+      vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName));
+    }
+    return vFile;
+  }
 }
diff --git a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
index 098462e..f288bd9 100644
--- a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
+++ b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
@@ -8,4 +8,8 @@
     setHomePath(name);
   }
 
+  @Override
+  public String getVersionString() {
+    return "";
+  }
 }
diff --git a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
index 39e4e96..1a5aafe 100644
--- a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
+++ b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
@@ -22,7 +22,6 @@
 import com.intellij.execution.Executor;
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
 import com.intellij.execution.process.ProcessHandler;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.execution.testframework.TestFrameworkRunningModel;
@@ -42,12 +41,10 @@
 import com.jetbrains.python.run.AbstractPythonRunConfiguration;
 import com.jetbrains.python.run.CommandLinePatcher;
 import com.jetbrains.python.run.PythonCommandLineState;
-import com.jetbrains.python.run.PythonTracebackFilter;
 import com.jetbrains.python.sdk.PythonSdkType;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -62,7 +59,7 @@
   }
 
   public PythonTestCommandLineStateBase(AbstractPythonRunConfiguration configuration, ExecutionEnvironment env) {
-    super(configuration, env, Collections.<Filter>emptyList());
+    super(configuration, env);
     myConfiguration = configuration;
   }
 
@@ -77,7 +74,6 @@
                                                                                       consoleProperties,
                                                                                       getEnvironment());
       final ConsoleView consoleView = new PythonDebugLanguageConsoleView(project, PythonSdkType.findSdkByPath(myConfiguration.getInterpreterPath()), testsOutputConsoleView);
-      consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
       consoleView.attachToProcess(processHandler);
       return consoleView;
     }
@@ -85,7 +81,7 @@
                                                                                       processHandler,
                                                                                       consoleProperties,
                                                                                       getEnvironment());
-    consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+    addTracebackFilter(project, consoleView, processHandler);
     return consoleView;
   }
 
diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
index 3637f37..581e688 100644
--- a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
+++ b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
@@ -81,7 +81,7 @@
   protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
     throws ExecutionException {
     final ConsoleView consoleView = super.createAndAttachConsole(project, processHandler, executor);
-    consoleView.addMessageFilter(new PyTestTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+    addTracebackFilter(project, consoleView, processHandler);
     return consoleView;
   }
 }
diff --git a/python/testData/codeInsight/smartEnter/withExpressionMissing.py b/python/testData/codeInsight/smartEnter/withExpressionMissing.py
new file mode 100644
index 0000000..25526ea
--- /dev/null
+++ b/python/testData/codeInsight/smartEnter/withExpressionMissing.py
@@ -0,0 +1 @@
+with <caret>
\ No newline at end of file
diff --git a/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py b/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py
new file mode 100644
index 0000000..722e64a
--- /dev/null
+++ b/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py
@@ -0,0 +1 @@
+with <caret>:
\ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py
new file mode 100644
index 0000000..6d44496
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py
@@ -0,0 +1,3 @@
+import b
+<warning descr="Unused import statement">from p1 import *</warning>
+print(b)
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py
new file mode 100644
index 0000000..31f7e1a
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py
@@ -0,0 +1 @@
+from p1.m1 import *
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py
new file mode 100644
index 0000000..3f8018d
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py
@@ -0,0 +1,2 @@
+import b
+__all__ = []
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py
new file mode 100644
index 0000000..7495833
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py
@@ -0,0 +1,5 @@
+import m1
+
+print(m1.foo)
+
+<warning descr="Unused import statement">from m2 import *</warning>
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py
new file mode 100644
index 0000000..1cfbade
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py
@@ -0,0 +1 @@
+foo = 0
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py
new file mode 100644
index 0000000..5215a01
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py
@@ -0,0 +1 @@
+import m1
diff --git a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
index b8421c9..09e0317 100644
--- a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
+++ b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
@@ -179,4 +179,9 @@
   public void testWithTargetIncomplete() {
     doTest();
   }
+
+  // PY-12877
+  public void testWithExpressionMissing() {
+    doTest();
+  }
 }
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
index 6850c3b..45d582a 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
@@ -15,6 +15,9 @@
  */
 package com.jetbrains.python.fixtures;
 
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ex.QuickFixWrapper;
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.module.Module;
@@ -28,6 +31,7 @@
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
 import com.intellij.testFramework.LightProjectDescriptor;
 import com.intellij.testFramework.PlatformTestCase;
@@ -131,8 +135,32 @@
     }
   }
 
-  protected static void assertNotParsed(PyFile file) {
-    assertNull(PARSED_ERROR_MSG, ((PyFileImpl)file).getTreeElement());
+  /**
+   * Searches for quickfix itetion by its class
+   * @param clazz quick fix class
+   * @param <T> quick fix class
+   * @return quick fix or null if nothing found
+   */
+  @Nullable
+  public <T extends LocalQuickFix> T findQuickFixByClassInIntentions(@NotNull final Class<T> clazz) {
+
+    for (final IntentionAction action : myFixture.getAvailableIntentions()) {
+      if ((action instanceof QuickFixWrapper)) {
+        final QuickFixWrapper quickFixWrapper = (QuickFixWrapper)action;
+        final LocalQuickFix fix = quickFixWrapper.getFix();
+        if (clazz.isInstance(fix)) {
+          @SuppressWarnings("unchecked")
+          final T result = (T)fix;
+          return result;
+        }
+      }
+    }
+    return null;
+  }
+
+
+    protected static void assertNotParsed(PyFile file) {
+      assertNull(PARSED_ERROR_MSG, ((PyFileImpl)file).getTreeElement());
   }
 
   /**
@@ -144,6 +172,18 @@
     return myFixture.findElementByText("class " + name, PyClass.class);
   }
 
+  /**
+   * Finds some text and moves cursor to it (if found)
+   *
+   * @param testToFind text to find
+   * @throws AssertionError if element not found
+   */
+  protected void moveByText(@NotNull final String testToFind) {
+    final PsiElement element = myFixture.findElementByText(testToFind, PsiElement.class);
+    assert element != null : "No element found by text: " + testToFind;
+    myFixture.getEditor().getCaretModel().moveToOffset(element.getTextOffset());
+  }
+
   protected static class PyLightProjectDescriptor implements LightProjectDescriptor {
     private final String myPythonVersion;
 
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
index 0c5e87a..a0a2a12 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -371,6 +371,16 @@
     doMultiFileTest();
   }
 
+  // PY-11472
+  public void testUnusedImportBeforeStarImport() {
+    doMultiFileTest();
+  }
+
+  // PY-13585
+  public void testUnusedImportBeforeStarDunderAll() {
+    doMultiFileTest();
+  }
+
   @NotNull
   @Override
   protected Class<? extends PyInspection> getInspectionClass() {
diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties
index fa51256..f245bb5 100644
--- a/resources-en/src/messages/DebuggerBundle.properties
+++ b/resources-en/src/messages/DebuggerBundle.properties
@@ -204,9 +204,6 @@
 button.move.down=Move &Down
 label.compound.renderer.configurable.table.header.name=Name
 label.compound.renderer.configurable.table.header.expression=Expression
-debugger.launching.configurable.display.name=Launching
-debugger.hotswap.configurable.display.name=HotSwap
-label.debugger.launching.configurable.hide.window=Hide debug &window on process termination
 label.debugger.hotswap.configurable.hotswap.background=Reload classes in &background
 label.debugger.hotswap.configurable.compile.before.hotswap=Make project before reloading classes
 label.debugger.hotswap.configurable.enable.vm.hang.warning=Enable 'JVM will hang' warning
@@ -214,7 +211,6 @@
 label.debugger.hotswap.configurable.always=&Always
 label.debugger.hotswap.configurable.never=&Never
 label.debugger.hotswap.configurable.ask=As&k
-label.debugger.general.configurable.group.launching=Launching
 label.debugger.launching.configurable.force.classic.vm=Force Class&ic VM for JDK 1.3.x and earlier
 label.debugger.launching.configurable.disable.jit=Disable JIT
 label.debugger.launching.configurable.debugger.transport=Transport:
@@ -232,7 +228,7 @@
 label.threads.view.configurable.show.stack.frames.for.synthetic.methods=Show stack &frames for synthetic methods
 label.threads.view.configurable.show.thread.groups=Show thread &groups
 threads.view.configurable.display.name=Customize Threads View
-user.renderers.configurable.display.name=Data Type Renderers
+user.renderers.configurable.display.name=Java Data Type Renderers
 label.user.renderers.configurable.renderer.name=Renderer name:
 text.user.renderers.configurable.no.renderers=No renderers
 button.copy=Copy
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 9764417..7260497 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -27,7 +27,8 @@
       <implementation-class>com.intellij.util.xml.impl.JavaDomApplicationComponent</implementation-class>
     </component>
     <component>
-      <implementation-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter</implementation-class>
+      <interface-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter</interface-class>
+      <implementation-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverterImpl</implementation-class>
     </component>
   </application-components>
 
@@ -238,6 +239,8 @@
     <extensionPoint name="hierarchy.referenceProcessor" interface="com.intellij.ide.hierarchy.call.CallReferenceProcessor"/>
 
     <extensionPoint name="lang.psiAugmentProvider" interface="com.intellij.psi.augment.PsiAugmentProvider"/>
+
+    <extensionPoint name="custom.exception.handler" interface="com.intellij.codeInsight.CustomExceptionHandler"/>
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij">
diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml
index 12a8d34..562f7c4 100644
--- a/resources/src/idea/RichPlatformActions.xml
+++ b/resources/src/idea/RichPlatformActions.xml
@@ -389,12 +389,6 @@
       <add-to-group group-id="NavbarPopupMenu" anchor="after" relative-to-action="WeighingNewGroup"/>
     </action>
 
-
-    <group id="DiffPanel.Toolbar.IDEA">
-      <reference ref="Find"/>
-      <add-to-group group-id="DiffPanel.Toolbar" anchor="after" relative-to-action="$Copy"/>
-    </group>
-
     <group>
       <group id="MarkSourceRootGroup" class="com.intellij.ide.projectView.actions.MarkSourceRootActionGroup"/>
       <action id="MarkExcludeRoot" class="com.intellij.ide.projectView.actions.MarkExcludeRootAction" icon="AllIcons.Modules.ExcludeRoot"/>
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index 92ae704..93aa37c 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -339,6 +339,7 @@
     <stepsBeforeRunProvider implementation="com.intellij.compiler.options.CompileStepBeforeRunNoErrorCheck" id="compileBeforeRunNoErrorCheck" order="after compileBeforeRun"/>
     <stepsBeforeRunProvider implementation="com.intellij.packaging.impl.run.BuildArtifactsBeforeRunTaskProvider" order="after compileBeforeRunNoErrorCheck"/>
     <programRunner id="defaultRunRunner" implementation="com.intellij.execution.impl.DefaultJavaProgramRunner"/>
+    <programRunner implementation="com.intellij.execution.runners.BasicProgramRunner" order="last"/>
 
     <hectorComponentProvider implementation="com.intellij.codeInsight.daemon.impl.ImportPopupHectorComponentProvider"/>
 
@@ -372,6 +373,8 @@
     <projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaTestResourceRootEditHandler"/>
 
     <buildProcess.parametersProvider implementation="com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexerBuilderParametersProvider"/>
+
+    <org.jetbrains.webServerRootsProvider implementation="org.jetbrains.builtInWebServer.ArtifactWebServerRootsProvider" order="last"/>
   </extensions>
 
   <xi:include href="/META-INF/xdebugger.xml" xpointer="xpointer(/idea-plugin/*)"/>
diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
index 52b8560..bb2388b 100644
--- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
+++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
@@ -228,6 +228,8 @@
 keepduplicates
 keychain
 keychains
+keyframe
+keyframes
 kotlin
 labeler
 labelers
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
index 01f7df0..0ddd4cf 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
@@ -17,7 +17,7 @@
         <border type="none"/>
         <children/>
       </xy>
-      <grid id="1b801" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+      <grid id="1b801" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -27,14 +27,14 @@
         <children>
           <scrollpane id="3e3f1" class="com.intellij.ui.components.JBScrollPane" binding="myJBScrollPane" custom-create="true">
             <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <horizontalScrollBarPolicy value="31"/>
             </properties>
             <border type="empty"/>
             <children>
-              <grid id="b4cfb" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+              <grid id="b4cfb" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                 <margin top="0" left="0" bottom="0" right="0"/>
                 <constraints/>
                 <properties/>
@@ -43,7 +43,7 @@
                   <grid id="ca5bb" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                     <margin top="0" left="0" bottom="0" right="0"/>
                     <constraints>
-                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                      <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties/>
                     <border type="none"/>
@@ -185,7 +185,7 @@
                   <grid id="b8acc" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                     <margin top="0" left="0" bottom="0" right="0"/>
                     <constraints>
-                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties/>
                     <border type="none"/>
@@ -277,7 +277,7 @@
                   <grid id="6dece" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                     <margin top="0" left="0" bottom="0" right="0"/>
                     <constraints>
-                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties/>
                     <border type="none"/>
@@ -336,6 +336,15 @@
                       </component>
                     </children>
                   </grid>
+                  <grid id="eb695" binding="myRightMarginPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                    <margin top="0" left="0" bottom="0" right="0"/>
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                    <border type="none"/>
+                    <children/>
+                  </grid>
                 </children>
               </grid>
             </children>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
index ba5a72a..476181f 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.application.options;
 
+import com.intellij.application.options.codeStyle.RightMarginForm;
 import com.intellij.ide.highlighter.XmlHighlighterFactory;
 import com.intellij.openapi.application.ApplicationBundle;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -30,6 +31,7 @@
 import com.intellij.ui.components.JBScrollPane;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.PlatformIcons;
+import com.intellij.util.ui.Centerizer;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -64,6 +66,8 @@
   private JCheckBox myShouldKeepLineBreaksInText;
   private TextFieldWithBrowseButton myDontBreakIfInlineContent;
   private JBScrollPane myJBScrollPane;
+  private JPanel myRightMarginPanel;
+  private RightMarginForm myRightMarginForm;
 
   public CodeStyleHtmlPanel(CodeStyleSettings settings) {
     super(settings);
@@ -95,6 +99,8 @@
   }
 
   private void createUIComponents() {
+    myRightMarginForm = new RightMarginForm(StdFileTypes.HTML.getLanguage(), getSettings());
+    myRightMarginPanel = myRightMarginForm.getTopPanel();
     myJBScrollPane = new JBScrollPane() {
       @Override
       public Dimension getPreferredSize() {
@@ -158,6 +164,7 @@
     settings.HTML_KEEP_WHITESPACES_INSIDE = myKeepWhiteSpacesTagNames.getText();
     settings.HTML_KEEP_LINE_BREAKS = myShouldKeepBlankLines.isSelected();
     settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = myShouldKeepLineBreaksInText.isSelected();
+    myRightMarginForm.apply(settings);
   }
 
   private static int getIntValue(JTextField keepBlankLines) {
@@ -190,6 +197,7 @@
     myInlineElementsTagNames.setText(settings.HTML_INLINE_ELEMENTS);
     myDontBreakIfInlineContent.setText(settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT);
     myKeepWhiteSpacesTagNames.setText(settings.HTML_KEEP_WHITESPACES_INSIDE);
+    myRightMarginForm.reset(settings);
   }
 
   @Override
@@ -260,7 +268,7 @@
       return true;
     }
 
-    return false;
+    return myRightMarginForm.isModified(settings);
   }
 
   @Override
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
index 28d48d0..c789593 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
@@ -17,7 +17,7 @@
         </properties>
         <border type="empty"/>
         <children>
-          <grid id="265f" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+          <grid id="265f" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
             <margin top="0" left="0" bottom="0" right="0"/>
             <constraints/>
             <properties/>
@@ -26,7 +26,7 @@
               <grid id="417cd" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                 <margin top="0" left="0" bottom="0" right="0"/>
                 <constraints>
-                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <border type="none"/>
@@ -114,7 +114,7 @@
               <grid id="e7045" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                 <margin top="0" left="0" bottom="0" right="0"/>
                 <constraints>
-                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <border type="none"/>
@@ -176,7 +176,7 @@
               <grid id="bcc6c" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                 <margin top="0" left="0" bottom="0" right="0"/>
                 <constraints>
-                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <clientProperties>
@@ -215,6 +215,15 @@
                   </component>
                 </children>
               </grid>
+              <grid id="3d661" binding="myRightMarginPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children/>
+              </grid>
             </children>
           </grid>
         </children>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
index ab31261..8767e00 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.application.options;
 
+import com.intellij.application.options.codeStyle.RightMarginForm;
 import com.intellij.ide.highlighter.XmlHighlighterFactory;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
@@ -25,6 +26,7 @@
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
 import com.intellij.ui.components.JBScrollPane;
+import org.apache.xmlbeans.XmlLanguage;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -48,6 +50,8 @@
   private JComboBox myWhiteSpaceAroundCDATA;
   private JCheckBox myKeepWhitespaceInsideCDATACheckBox;
   private JBScrollPane myJBScrollPane;
+  private JPanel myRightMarginPanel;
+  private RightMarginForm myRightMarginForm;
 
   public CodeStyleXmlPanel(CodeStyleSettings settings) {
     super(settings);
@@ -83,6 +87,7 @@
     xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG = myInEmptyTag.isSelected();
     xmlSettings.XML_WHITE_SPACE_AROUND_CDATA = myWhiteSpaceAroundCDATA.getSelectedIndex();
     xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA = myKeepWhitespaceInsideCDATACheckBox.isSelected();
+    myRightMarginForm.apply(settings);
   }
 
   private int getIntValue(JTextField keepBlankLines) {
@@ -109,6 +114,7 @@
     myWrapText.setSelected(wrapText(settings));
     myWhiteSpaceAroundCDATA.setSelectedIndex(xmlSettings.XML_WHITE_SPACE_AROUND_CDATA);
     myKeepWhitespaceInsideCDATACheckBox.setSelected(xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA);
+    myRightMarginForm.reset(settings);
   }
 
   @Override
@@ -156,7 +162,7 @@
       return true;
     }
 
-    return false;
+    return myRightMarginForm.isModified(settings);
   }
 
   private boolean wrapText(final CodeStyleSettings settings) {
@@ -193,5 +199,7 @@
         return new Dimension(prefSize.width + 15, prefSize.height);
       }
     };
+    myRightMarginForm = new RightMarginForm(StdFileTypes.XML.getLanguage(), getSettings());
+    myRightMarginPanel = myRightMarginForm.getTopPanel();
   }
 }
diff --git a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
index aa36d1b..d970ee5 100644
--- a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
+++ b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
@@ -17,10 +17,13 @@
 
 import com.intellij.lang.Language;
 import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Set;
+
 /**
  * @author Rustam Vishnyakov
  */
@@ -37,6 +40,14 @@
   }
 
   @Override
+  public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer,
+                                @NotNull SettingsType settingsType) {
+    if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+      consumer.showStandardOptions("RIGHT_MARGIN");
+    }
+  }
+
+  @Override
   public CommonCodeStyleSettings getDefaultCommonSettings() {
     CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(HTMLLanguage.INSTANCE);
     defaultSettings.initIndentOptions();
diff --git a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
index 651c71e..8931133 100644
--- a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
+++ b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
@@ -17,6 +17,7 @@
 
 import com.intellij.lang.Language;
 import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
 import com.intellij.util.PlatformUtils;
@@ -41,6 +42,14 @@
   }
 
   @Override
+  public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer,
+                                @NotNull SettingsType settingsType) {
+    if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+      consumer.showStandardOptions("RIGHT_MARGIN");
+    }
+  }
+
+  @Override
   public CommonCodeStyleSettings getDefaultCommonSettings() {
     CommonCodeStyleSettings xmlSettings = new CommonCodeStyleSettings(getLanguage());
     CommonCodeStyleSettings.IndentOptions indentOptions = xmlSettings.initIndentOptions();
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
index ec6c806..6d95604 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
@@ -33,7 +33,9 @@
     if (node != null && node.getElementType() == XmlTokenType.XML_DATA_CHARACTERS) {
       PsiElement parent = contextElement.getParent();
       if (parent instanceof XmlText || parent instanceof XmlDocument) {
-        String prefix = contextElement.getText().substring(0, offset - contextElement.getTextRange().getStartOffset());
+        String contextElementText = contextElement.getText();
+        int endOffset = offset - contextElement.getTextRange().getStartOffset();
+        String prefix = contextElementText.substring(0, Math.min(contextElementText.length(), endOffset));
         if (!StringUtil.startsWithChar(prefix, '<') && !StringUtil.startsWithChar(prefix, '&')) {
           return ThreeState.YES;
         }
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
index ceb0d1d..421fbdd 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
@@ -18,6 +18,7 @@
 import com.intellij.codeInsight.template.emmet.nodes.GenerationNode;
 import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
 import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.XmlElementVisitor;
 import com.intellij.psi.xml.XmlDocument;
@@ -25,6 +26,7 @@
 import com.intellij.psi.xml.XmlTagValue;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
@@ -57,18 +59,27 @@
     if (document != null) {
       XmlTag tag = document.getRootTag();
       if (tag != null && !tag.getText().isEmpty()) {
-        new XmlElementVisitor() {
+        tag.accept(new XmlElementVisitor() {
           @Override
-          public void visitXmlTag(XmlTag tag) {
-            if(!tag.isEmpty()) {
-              XmlTagValue tagValue = tag.getValue();
-              tagValue.setText(PATTERN.matcher(tagValue.getText()).replaceAll(""));
+          public void visitXmlTag(final XmlTag tag) {
+            if (!tag.isEmpty()) {
+              final XmlTagValue tagValue = tag.getValue();
+              final Matcher matcher = PATTERN.matcher(tagValue.getText());
+              if (matcher.matches()) {
+                ApplicationManager.getApplication().runWriteAction(new Runnable() {
+                  @Override
+                  public void run() {
+                    tagValue.setText(matcher.replaceAll(""));
+                  }
+                });
+              }
             }
             tag.acceptChildren(this);
           }
-        }.visitXmlTag(tag);
+        });
         return tag.getText();
-      } else {
+      }
+      else {
         return PATTERN.matcher(document.getText()).replaceAll("");
       }
     }
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
index 86d2994..4f7f4ef 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
@@ -18,6 +18,7 @@
 import com.intellij.concurrency.JobScheduler;
 import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.util.ExecUtil;
+import com.intellij.ide.GeneralSettings;
 import com.intellij.ide.IdeBundle;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.options.ShowSettingsUtil;
@@ -25,14 +26,30 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.AppUIUtil;
+import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.net.URI;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 final class BrowserLauncherImpl extends BrowserLauncherAppless {
   @Override
+  protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) {
+    WebBrowserManager browserManager = WebBrowserManager.getInstance();
+    if (browserManager.getDefaultBrowserPolicy() == DefaultBrowserPolicy.FIRST) {
+      WebBrowser browser = browserManager.getFirstActiveBrowser();
+      if (browser != null) {
+        browseUsingPath(uri.toString(), null, browser, project, ArrayUtil.EMPTY_STRING_ARRAY);
+        return;
+      }
+    }
+
+    super.browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project);
+  }
+
+  @Override
   protected void doShowError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, final String title, @Nullable final Runnable launchTask) {
     AppUIUtil.invokeOnEdt(new Runnable() {
       @Override
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
index 3ae67de..af04e58 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
@@ -81,8 +81,8 @@
                             boolean hasFocus) {
         Icon baseIcon;
         if (value == null) {
-          WebBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowser();
-          baseIcon = defaultBrowser == null ? PlatformIcons.WEB_ICON : defaultBrowser.getIcon();
+          WebBrowser firstBrowser = WebBrowserManager.getInstance().getFirstActiveBrowser();
+          baseIcon = firstBrowser == null ? PlatformIcons.WEB_ICON : firstBrowser.getIcon();
         }
         else {
           baseIcon = value.getIcon();
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
index 52d0743..23d7bf2 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
@@ -22,7 +22,7 @@
             </constraints>
             <properties/>
           </component>
-          <component id="95daa" class="com.intellij.openapi.ui.ComboBox" binding="defaultBrowserComboBox">
+          <component id="95daa" class="com.intellij.openapi.ui.ComboBox" binding="defaultBrowserPolicyComboBox">
             <constraints>
               <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
index 477d527..f43c0f6 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
@@ -23,7 +23,6 @@
 import com.intellij.openapi.ui.ComboBox;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.ui.EnumComboBoxModel;
 import com.intellij.ui.ListCellRendererWrapper;
 import com.intellij.ui.TitledSeparator;
 import com.intellij.util.Function;
@@ -34,6 +33,7 @@
 import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.table.IconTableCellRenderer;
 import com.intellij.util.ui.table.TableModelEditor;
+import org.jdesktop.swingx.combobox.ListComboBoxModel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -46,9 +46,9 @@
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
+import java.util.ArrayList;
 import java.util.UUID;
 
-import static com.intellij.ide.browsers.WebBrowserManager.DefaultBrowser;
 import static com.intellij.util.ui.table.TableModelEditor.EditableColumnInfo;
 
 final class BrowserSettingsPanel {
@@ -73,7 +73,7 @@
       }
     };
 
-  private static final ColumnInfo[] COLUMNS = {new EditableColumnInfo<ConfigurableWebBrowser, Boolean>() {
+  private static final EditableColumnInfo<ConfigurableWebBrowser, Boolean> ACTIVE_COLUMN_INFO = new EditableColumnInfo<ConfigurableWebBrowser, Boolean>() {
     @Override
     public Class getColumnClass() {
       return Boolean.class;
@@ -88,44 +88,49 @@
     public void setValue(ConfigurableWebBrowser item, Boolean value) {
       item.setActive(value);
     }
-  }, new EditableColumnInfo<ConfigurableWebBrowser, String>("Name") {
-    @Override
-    public String valueOf(ConfigurableWebBrowser item) {
-      return item.getName();
-    }
+  };
 
-    @Override
-    public void setValue(ConfigurableWebBrowser item, String value) {
-      item.setName(value);
-    }
-  }, new ColumnInfo<ConfigurableWebBrowser, BrowserFamily>("Family") {
-    @Override
-    public Class getColumnClass() {
-      return BrowserFamily.class;
-    }
+  private static final ColumnInfo[] COLUMNS = {ACTIVE_COLUMN_INFO,
+    new EditableColumnInfo<ConfigurableWebBrowser, String>("Name") {
+      @Override
+      public String valueOf(ConfigurableWebBrowser item) {
+        return item.getName();
+      }
 
-    @Override
-    public BrowserFamily valueOf(ConfigurableWebBrowser item) {
-      return item.getFamily();
-    }
+      @Override
+      public void setValue(ConfigurableWebBrowser item, String value) {
+        item.setName(value);
+      }
+    },
+    new ColumnInfo<ConfigurableWebBrowser, BrowserFamily>("Family") {
+      @Override
+      public Class getColumnClass() {
+        return BrowserFamily.class;
+      }
 
-    @Override
-    public void setValue(ConfigurableWebBrowser item, BrowserFamily value) {
-      item.setFamily(value);
-      item.setSpecificSettings(value.createBrowserSpecificSettings());
-    }
+      @Override
+      public BrowserFamily valueOf(ConfigurableWebBrowser item) {
+        return item.getFamily();
+      }
 
-    @Nullable
-    @Override
-    public TableCellRenderer getRenderer(ConfigurableWebBrowser item) {
-      return IconTableCellRenderer.ICONABLE;
-    }
+      @Override
+      public void setValue(ConfigurableWebBrowser item, BrowserFamily value) {
+        item.setFamily(value);
+        item.setSpecificSettings(value.createBrowserSpecificSettings());
+      }
 
-    @Override
-    public boolean isCellEditable(ConfigurableWebBrowser item) {
-      return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
-    }
-  }, PATH_COLUMN_INFO};
+      @Nullable
+      @Override
+      public TableCellRenderer getRenderer(ConfigurableWebBrowser item) {
+        return IconTableCellRenderer.ICONABLE;
+      }
+
+      @Override
+      public boolean isCellEditable(ConfigurableWebBrowser item) {
+        return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
+      }
+    },
+    PATH_COLUMN_INFO};
 
   private JPanel root;
 
@@ -138,7 +143,7 @@
   @SuppressWarnings("UnusedDeclaration")
   private JComponent browsersTable;
 
-  private ComboBox defaultBrowserComboBox;
+  private ComboBox defaultBrowserPolicyComboBox;
 
   private TableModelEditor<ConfigurableWebBrowser> browsersEditor;
 
@@ -148,53 +153,55 @@
     alternativeBrowserPathField.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, APP_FILE_CHOOSER_DESCRIPTOR);
     defaultBrowserPanel.setBorder(TitledSeparator.EMPTY_BORDER);
 
-    //noinspection unchecked
-    defaultBrowserComboBox.setModel(new EnumComboBoxModel<DefaultBrowser>(DefaultBrowser.class));
-    if (BrowserLauncherAppless.canStartDefaultBrowser()) {
-      defaultBrowserComboBox.addItemListener(new ItemListener() {
-        @Override
-        public void itemStateChanged(ItemEvent e) {
-          boolean customPathEnabled = e.getItem() == DefaultBrowser.ALTERNATIVE;
-          if (e.getStateChange() == ItemEvent.DESELECTED) {
-            if (customPathEnabled) {
-              customPathValue = alternativeBrowserPathField.getText();
-            }
-          }
-          else if (e.getStateChange() == ItemEvent.SELECTED) {
-            alternativeBrowserPathField.setEnabled(customPathEnabled);
-            updateCustomPathTextFieldValue((DefaultBrowser)e.getItem());
-          }
-        }
-      });
-
-      defaultBrowserComboBox.setRenderer(new ListCellRendererWrapper<DefaultBrowser>() {
-        @Override
-        public void customize(JList list, DefaultBrowser value, int index, boolean selected, boolean hasFocus) {
-          String name;
-          switch (value) {
-            case SYSTEM:
-              name = "System default";
-              break;
-            case FIRST:
-              name = "First listed";
-              break;
-            case ALTERNATIVE:
-              name = "Custom path";
-              break;
-            default:
-              throw new IllegalStateException();
-          }
-
-          setText(name);
-        }
-      });
-
-      if (UIUtil.isUnderAquaLookAndFeel()) {
-        defaultBrowserComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
-      }
+    ArrayList<DefaultBrowserPolicy> defaultBrowserPolicies = new ArrayList<DefaultBrowserPolicy>();
+    if (BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy()) {
+      defaultBrowserPolicies.add(DefaultBrowserPolicy.SYSTEM);
     }
-    else {
-      defaultBrowserComboBox.setVisible(false);
+    defaultBrowserPolicies.add(DefaultBrowserPolicy.FIRST);
+    defaultBrowserPolicies.add(DefaultBrowserPolicy.ALTERNATIVE);
+
+    //noinspection Since15,unchecked
+    defaultBrowserPolicyComboBox.setModel(new ListComboBoxModel<DefaultBrowserPolicy>(defaultBrowserPolicies));
+    defaultBrowserPolicyComboBox.addItemListener(new ItemListener() {
+      @Override
+      public void itemStateChanged(ItemEvent e) {
+        boolean customPathEnabled = e.getItem() == DefaultBrowserPolicy.ALTERNATIVE;
+        if (e.getStateChange() == ItemEvent.DESELECTED) {
+          if (customPathEnabled) {
+            customPathValue = alternativeBrowserPathField.getText();
+          }
+        }
+        else if (e.getStateChange() == ItemEvent.SELECTED) {
+          alternativeBrowserPathField.setEnabled(customPathEnabled);
+          updateCustomPathTextFieldValue((DefaultBrowserPolicy)e.getItem());
+        }
+      }
+    });
+
+    defaultBrowserPolicyComboBox.setRenderer(new ListCellRendererWrapper<DefaultBrowserPolicy>() {
+      @Override
+      public void customize(JList list, DefaultBrowserPolicy value, int index, boolean selected, boolean hasFocus) {
+        String name;
+        switch (value) {
+          case SYSTEM:
+            name = "System default";
+            break;
+          case FIRST:
+            name = "First listed";
+            break;
+          case ALTERNATIVE:
+            name = "Custom path";
+            break;
+          default:
+            throw new IllegalStateException();
+        }
+
+        setText(name);
+      }
+    });
+
+    if (UIUtil.isUnderAquaLookAndFeel()) {
+      defaultBrowserPolicyComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
     }
 
     clearExtractedFiles.addActionListener(new ActionListener() {
@@ -205,11 +212,11 @@
     });
   }
 
-  private void updateCustomPathTextFieldValue(DefaultBrowser browser) {
-    if (browser == DefaultBrowser.ALTERNATIVE) {
+  private void updateCustomPathTextFieldValue(@NotNull DefaultBrowserPolicy browser) {
+    if (browser == DefaultBrowserPolicy.ALTERNATIVE) {
       alternativeBrowserPathField.setText(customPathValue);
     }
-    else if (browser == DefaultBrowser.FIRST) {
+    else if (browser == DefaultBrowserPolicy.FIRST) {
       setCustomPathToFirstListed();
     }
     else {
@@ -272,18 +279,18 @@
       .modelListener(new TableModelEditor.DataChangedListener<ConfigurableWebBrowser>() {
         @Override
         public void tableChanged(TableModelEvent event) {
-          update(event.getFirstRow());
+          update();
         }
 
         @Override
         public void dataChanged(@NotNull ColumnInfo<ConfigurableWebBrowser, ?> columnInfo, int rowIndex) {
-          if (columnInfo == PATH_COLUMN_INFO) {
-            update(rowIndex);
+          if (columnInfo == PATH_COLUMN_INFO || columnInfo == ACTIVE_COLUMN_INFO) {
+            update();
           }
         }
 
-        private void update(int rowIndex) {
-          if (rowIndex == 0 && getDefaultBrowser() == DefaultBrowser.FIRST) {
+        private void update() {
+          if (getDefaultBrowser() == DefaultBrowserPolicy.FIRST) {
             setCustomPathToFirstListed();
           }
         }
@@ -293,7 +300,15 @@
 
   private void setCustomPathToFirstListed() {
     ListTableModel<ConfigurableWebBrowser> model = browsersEditor.getModel();
-    alternativeBrowserPathField.setText(model.getRowCount() == 0 ? "" : model.getRowValue(0).getPath());
+    for (int i = 0, n = model.getRowCount(); i < n; i++) {
+      ConfigurableWebBrowser browser = model.getRowValue(i);
+      if (browser.isActive() && browser.getPath() != null) {
+        alternativeBrowserPathField.setText(browser.getPath());
+        return;
+      }
+    }
+
+    alternativeBrowserPathField.setText("");
   }
 
   @NotNull
@@ -305,12 +320,12 @@
     WebBrowserManager browserManager = WebBrowserManager.getInstance();
     GeneralSettings generalSettings = GeneralSettings.getInstance();
 
-    DefaultBrowser defaultBrowser = getDefaultBrowser();
-    if (browserManager.getDefaultBrowserMode() != defaultBrowser || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) {
+    DefaultBrowserPolicy defaultBrowserPolicy = getDefaultBrowser();
+    if (browserManager.getDefaultBrowserPolicy() != defaultBrowserPolicy || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) {
       return true;
     }
 
-    if (defaultBrowser == DefaultBrowser.ALTERNATIVE &&
+    if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE &&
         !Comparing.strEqual(generalSettings.getBrowserPath(), alternativeBrowserPathField.getText())) {
       return true;
     }
@@ -321,7 +336,7 @@
   public void apply() {
     GeneralSettings settings = GeneralSettings.getInstance();
 
-    settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowser.SYSTEM);
+    settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowserPolicy.SYSTEM);
 
     if (alternativeBrowserPathField.isEnabled()) {
       settings.setBrowserPath(alternativeBrowserPathField.getText());
@@ -330,26 +345,27 @@
     settings.setConfirmExtractFiles(confirmExtractFiles.isSelected());
 
     WebBrowserManager browserManager = WebBrowserManager.getInstance();
-    browserManager.defaultBrowser = getDefaultBrowser();
+    browserManager.defaultBrowserPolicy = getDefaultBrowser();
     browserManager.setList(browsersEditor.apply());
   }
 
-  private DefaultBrowser getDefaultBrowser() {
-    return (DefaultBrowser)defaultBrowserComboBox.getSelectedItem();
+  private DefaultBrowserPolicy getDefaultBrowser() {
+    return (DefaultBrowserPolicy)defaultBrowserPolicyComboBox.getSelectedItem();
   }
 
   public void reset() {
+    DefaultBrowserPolicy defaultBrowserPolicy = WebBrowserManager.getInstance().getDefaultBrowserPolicy();
+    DefaultBrowserPolicy effectiveDefaultBrowserPolicy = defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy()
+                                                         ? DefaultBrowserPolicy.ALTERNATIVE : defaultBrowserPolicy;
+    defaultBrowserPolicyComboBox.setSelectedItem(effectiveDefaultBrowserPolicy);
+
     GeneralSettings settings = GeneralSettings.getInstance();
-
-    DefaultBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowserMode();
-    defaultBrowserComboBox.setSelectedItem(defaultBrowser);
-
     confirmExtractFiles.setSelected(settings.isConfirmExtractFiles());
     browsersEditor.reset(WebBrowserManager.getInstance().getList());
 
     customPathValue = settings.getBrowserPath();
-    alternativeBrowserPathField.setEnabled(defaultBrowser == DefaultBrowser.ALTERNATIVE);
-    updateCustomPathTextFieldValue(defaultBrowser);
+    alternativeBrowserPathField.setEnabled(effectiveDefaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE);
+    updateCustomPathTextFieldValue(effectiveDefaultBrowserPolicy);
   }
 
   public void selectBrowser(@NotNull WebBrowser browser) {
diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
index 11502b5..9f48b35 100644
--- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
+++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
@@ -56,7 +56,7 @@
   @Override
   public Icon getIcon() {
     if (family == BrowserFamily.CHROME) {
-      if (checkNameAndPath("Yandex")) {
+      if (WebBrowserManager.isYandexBrowser(this)) {
         return AllIcons.Xml.Browsers.Yandex16;
       }
       else if (checkNameAndPath("Dartium") || checkNameAndPath("Chromium")) {
@@ -76,14 +76,7 @@
   }
 
   private boolean checkNameAndPath(@NotNull String what) {
-    if (StringUtil.containsIgnoreCase(name, what)) {
-      return true;
-    }
-    if (path != null) {
-      int index = path.lastIndexOf('/');
-      return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what);
-    }
-    return false;
+    return WebBrowserManager.checkNameAndPath(what, this);
   }
 
   @Nullable
diff --git a/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java
new file mode 100644
index 0000000..4e1f0b2
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+package com.intellij.ide.browsers;
+
+public enum DefaultBrowserPolicy {
+  SYSTEM, FIRST, ALTERNATIVE
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
index ce51ee0..0b2ba6c 100644
--- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
@@ -17,10 +17,7 @@
 
 import com.intellij.openapi.components.*;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Conditions;
-import com.intellij.openapi.util.JDOMUtil;
-import com.intellij.openapi.util.SimpleModificationTracker;
+import com.intellij.openapi.util.*;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.SmartList;
 import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
@@ -36,53 +33,75 @@
   private static final Logger LOG = Logger.getInstance(WebBrowserManager.class);
 
   // default standard browser ID must be constant across all IDE versions on all machines for all users
-  private static final UUID DEFAULT_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3");
+  private static final UUID PREDEFINED_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3");
   // public, but only internal use
-  public static final UUID DEFAULT_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8");
-  private static final UUID DEFAULT_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186");
-  private static final UUID DEFAULT_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776");
-  private static final UUID DEFAULT_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0");
+  public static final UUID PREDEFINED_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8");
+  private static final UUID PREDEFINED_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186");
+  private static final UUID PREDEFINED_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776");
+  private static final UUID PREDEFINED_YANDEX_ID = UUID.fromString("B1B2EC2C-20BD-4EE2-89C4-616DB004BCD4");
+  private static final UUID PREDEFINED_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0");
+
+  private static final List<ConfigurableWebBrowser> PREDEFINED_BROWSERS = Arrays.asList(
+    new ConfigurableWebBrowser(PREDEFINED_CHROME_ID, BrowserFamily.CHROME),
+    new ConfigurableWebBrowser(PREDEFINED_FIREFOX_ID, BrowserFamily.FIREFOX),
+    new ConfigurableWebBrowser(PREDEFINED_SAFARI_ID, BrowserFamily.SAFARI),
+    new ConfigurableWebBrowser(PREDEFINED_OPERA_ID, BrowserFamily.OPERA),
+    new ConfigurableWebBrowser(PREDEFINED_YANDEX_ID, BrowserFamily.CHROME, "Yandex", SystemInfo.isWindows ? "browser" : (SystemInfo.isMac ? "Yandex" : "yandex"), false, BrowserFamily.CHROME.createBrowserSpecificSettings()),
+    new ConfigurableWebBrowser(PREDEFINED_EXPLORER_ID, BrowserFamily.EXPLORER)
+  );
 
   private List<ConfigurableWebBrowser> browsers;
 
-  DefaultBrowser defaultBrowser = DefaultBrowser.SYSTEM;
+  DefaultBrowserPolicy defaultBrowserPolicy = DefaultBrowserPolicy.SYSTEM;
 
   public WebBrowserManager() {
-    browsers = new ArrayList<ConfigurableWebBrowser>();
-    browsers.add(new ConfigurableWebBrowser(DEFAULT_CHROME_ID, BrowserFamily.CHROME));
-    browsers.add(new ConfigurableWebBrowser(DEFAULT_FIREFOX_ID, BrowserFamily.FIREFOX));
-    browsers.add(new ConfigurableWebBrowser(DEFAULT_SAFARI_ID, BrowserFamily.SAFARI));
-    browsers.add(new ConfigurableWebBrowser(DEFAULT_OPERA_ID, BrowserFamily.OPERA));
-    browsers.add(new ConfigurableWebBrowser(DEFAULT_EXPLORER_ID, BrowserFamily.EXPLORER));
+    browsers = new ArrayList<ConfigurableWebBrowser>(PREDEFINED_BROWSERS);
   }
 
   public static WebBrowserManager getInstance() {
     return ServiceManager.getService(WebBrowserManager.class);
   }
 
-  boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) {
-    UUID id = browser.getId();
-    return id.equals(DEFAULT_CHROME_ID) ||
-           id.equals(DEFAULT_FIREFOX_ID) ||
-           id.equals(DEFAULT_SAFARI_ID) ||
-           id.equals(DEFAULT_OPERA_ID) ||
-           id.equals(DEFAULT_EXPLORER_ID);
+  public static boolean isYandexBrowser(@NotNull WebBrowser browser) {
+    return browser.getFamily().equals(BrowserFamily.CHROME) && (browser.getId().equals(PREDEFINED_YANDEX_ID) || checkNameAndPath("Yandex", browser));
   }
 
-  public enum DefaultBrowser {
-    SYSTEM, FIRST, ALTERNATIVE
+  public static boolean isDartium(@NotNull WebBrowser browser) {
+    return browser.getFamily().equals(BrowserFamily.CHROME) && checkNameAndPath("Dartium", browser);
+  }
+
+  static boolean checkNameAndPath(@NotNull String what, @NotNull WebBrowser browser) {
+    if (StringUtil.containsIgnoreCase(browser.getName(), what)) {
+      return true;
+    }
+    String path = browser.getPath();
+    if (path != null) {
+      int index = path.lastIndexOf('/');
+      return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what);
+    }
+    return false;
+  }
+
+  boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) {
+    UUID id = browser.getId();
+    for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) {
+      if (id.equals(predefinedBrowser.getId())) {
+        return true;
+      }
+    }
+    return false;
   }
 
   @NotNull
-  public DefaultBrowser getDefaultBrowserMode() {
-    return defaultBrowser;
+  public DefaultBrowserPolicy getDefaultBrowserPolicy() {
+    return defaultBrowserPolicy;
   }
 
   @Override
   public Element getState() {
     Element state = new Element("state");
-    if (defaultBrowser != DefaultBrowser.SYSTEM) {
-      state.setAttribute("default", defaultBrowser.name().toLowerCase(Locale.ENGLISH));
+    if (defaultBrowserPolicy != DefaultBrowserPolicy.SYSTEM) {
+      state.setAttribute("default", defaultBrowserPolicy.name().toLowerCase(Locale.ENGLISH));
     }
 
     for (ConfigurableWebBrowser browser : browsers) {
@@ -137,19 +156,19 @@
       UUID id;
       switch (family) {
         case CHROME:
-          id = DEFAULT_CHROME_ID;
+          id = PREDEFINED_CHROME_ID;
           break;
         case EXPLORER:
-          id = DEFAULT_EXPLORER_ID;
+          id = PREDEFINED_EXPLORER_ID;
           break;
         case FIREFOX:
-          id = DEFAULT_FIREFOX_ID;
+          id = PREDEFINED_FIREFOX_ID;
           break;
         case OPERA:
-          id = DEFAULT_OPERA_ID;
+          id = PREDEFINED_OPERA_ID;
           break;
         case SAFARI:
-          id = DEFAULT_SAFARI_ID;
+          id = PREDEFINED_SAFARI_ID;
           break;
 
         default:
@@ -180,7 +199,7 @@
     String defaultValue = element.getAttributeValue("default");
     if (!StringUtil.isEmpty(defaultValue)) {
       try {
-        defaultBrowser = DefaultBrowser.valueOf(defaultValue.toUpperCase(Locale.ENGLISH));
+        defaultBrowserPolicy = DefaultBrowserPolicy.valueOf(defaultValue.toUpperCase(Locale.ENGLISH));
       }
       catch (IllegalArgumentException e) {
         LOG.warn(e);
@@ -225,6 +244,18 @@
                                           specificSettings));
     }
 
+    // add removed/new predefined browsers
+    int n = list.size();
+    pb: for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) {
+      //noinspection ForLoopReplaceableByForEach
+      for (int i = 0; i < n; i++) {
+        if (list.get(i).getId().equals(predefinedBrowser.getId())) {
+          continue pb;
+        }
+      }
+      list.add(predefinedBrowser);
+    }
+
     setList(list);
   }
 
@@ -349,9 +380,9 @@
   }
 
   @Nullable
-  public WebBrowser getDefaultBrowser() {
+  public WebBrowser getFirstActiveBrowser() {
     for (ConfigurableWebBrowser browser : browsers) {
-      if (browser.isActive()) {
+      if (browser.isActive() && browser.getPath() != null) {
         return browser;
       }
     }
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
index 8ec2a2e..e3bf3b5 100644
--- a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
@@ -151,7 +151,7 @@
     boolean applicable = false;
     WebBrowserUrlProvider provider = null;
     if (request != null) {
-      applicable = HtmlUtil.isHtmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile);
+      applicable = WebBrowserServiceImpl.isHtmlOrXmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile);
       if (!applicable) {
         provider = WebBrowserServiceImpl.getProvider(request);
         applicable = provider != null;
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
index 45cf021..1ead1b6 100644
--- a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
@@ -16,10 +16,7 @@
 package com.intellij.ide.browsers.actions;
 
 import com.intellij.ide.GeneralSettings;
-import com.intellij.ide.browsers.OpenInBrowserRequest;
-import com.intellij.ide.browsers.WebBrowser;
-import com.intellij.ide.browsers.WebBrowserManager;
-import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.ide.browsers.*;
 import com.intellij.openapi.actionSystem.ActionPlaces;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
@@ -68,10 +65,11 @@
   @Nullable
   private static WebBrowser findUsingBrowser() {
     WebBrowserManager browserManager = WebBrowserManager.getInstance();
-    if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.FIRST) {
-      return browserManager.getDefaultBrowser();
+    DefaultBrowserPolicy defaultBrowserPolicy = browserManager.getDefaultBrowserPolicy();
+    if (defaultBrowserPolicy == DefaultBrowserPolicy.FIRST || (defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy())) {
+      return browserManager.getFirstActiveBrowser();
     }
-    else if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.ALTERNATIVE) {
+    else if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE) {
       String path = GeneralSettings.getInstance().getBrowserPath();
       if (!StringUtil.isEmpty(path)) {
         WebBrowser browser = browserManager.findBrowserById(path);
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
index 5cd056f..3d0451d 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
@@ -18,6 +18,10 @@
 import com.intellij.ide.browsers.OpenInBrowserRequest;
 import com.intellij.ide.browsers.WebBrowserService;
 import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
@@ -34,6 +38,11 @@
 import java.util.Collections;
 
 public class WebBrowserServiceImpl extends WebBrowserService {
+  public static boolean isHtmlOrXmlFile(@NotNull PsiElement element) {
+    Language language = element.getLanguage();
+    return language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE || language == XMLLanguage.INSTANCE;
+  }
+
   @NotNull
   @Override
   public Collection<Url> getUrlsToOpen(@NotNull OpenInBrowserRequest request, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
@@ -42,7 +51,7 @@
       return Collections.singleton(Urls.newFromVirtualFile(virtualFile));
     }
 
-    if (!preferLocalUrl || !HtmlUtil.isHtmlFile(request.getFile())) {
+    if (!preferLocalUrl || !isHtmlOrXmlFile(request.getFile())) {
       WebBrowserUrlProvider provider = getProvider(request);
       if (provider != null) {
         if (request.getResult() != null) {
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
index 6e1b899..b2b5b5f 100644
--- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
@@ -17,6 +17,7 @@
 
 import com.intellij.formatting.*;
 import com.intellij.lang.*;
+import com.intellij.lang.xml.XMLLanguage;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.util.TextRange;
@@ -464,11 +465,28 @@
     return myNode.getElementType() == XmlTokenType.XML_CDATA_END;
   }
 
-  public static boolean containsWhiteSpacesOnly(ASTNode node) {
-    WhiteSpaceFormattingStrategy strategy =  WhiteSpaceFormattingStrategyFactory.getStrategy(node.getPsi().getLanguage());
-    String nodeText = node.getText();
-    int length = nodeText.length();
-    return strategy.check(nodeText, 0, length) >= length;
+  public static boolean containsWhiteSpacesOnly(@NotNull ASTNode node) {
+    PsiElement psiElement = node.getPsi();
+    if (psiElement instanceof PsiWhiteSpace) return true;
+    Language nodeLang = psiElement.getLanguage();
+    if (!nodeLang.isKindOf(XMLLanguage.INSTANCE) ||
+        isTextOnlyNode(node) ||
+        node.getElementType() == XmlElementType.XML_PROLOG) {
+      WhiteSpaceFormattingStrategy strategy = WhiteSpaceFormattingStrategyFactory.getStrategy(nodeLang);
+      int length = node.getTextLength();
+      return strategy.check(node.getChars(), 0, length) >= length;
+    }
+    return false;
+  }
+
+  private static boolean isTextOnlyNode(@NotNull ASTNode node) {
+    if (node.getPsi() instanceof XmlText) return true;
+    ASTNode firstChild = node.getFirstChildNode();
+    ASTNode lastChild = node.getLastChildNode();
+    if (firstChild != null && firstChild == lastChild && firstChild.getPsi() instanceof XmlText) {
+      return true;
+    }
+    return false;
   }
 
 }
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form
new file mode 100644
index 0000000..3aa78b3
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.builtInWebServer.BuiltInServerConfigurableUi">
+  <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="1077" height="321"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="696ad" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="setting.value.builtin.server.port.label"/>
+        </properties>
+      </component>
+      <component id="e47e0" class="com.intellij.ui.PortField" binding="builtInServerPort">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="33218" class="javax.swing.JCheckBox" binding="builtInServerAvailableExternallyCheckBox" default-binding="true">
+        <constraints>
+          <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="messages/XmlBundle" key="setting.value.can.accept.external.connections"/>
+        </properties>
+      </component>
+      <vspacer id="c36c4">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+    </children>
+  </grid>
+</form>
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java
new file mode 100644
index 0000000..edbef65
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java
@@ -0,0 +1,47 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.options.ConfigurableUi;
+import com.intellij.ui.PortField;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+class BuiltInServerConfigurableUi implements ConfigurableUi<BuiltInServerOptions> {
+  private JPanel mainPanel;
+
+  private PortField builtInServerPort;
+  private JCheckBox builtInServerAvailableExternallyCheckBox;
+
+  public BuiltInServerConfigurableUi() {
+    builtInServerPort.setMin(1024);
+  }
+
+  @Override
+  @NotNull
+  public JComponent getComponent() {
+    return mainPanel;
+  }
+
+  @Override
+  public boolean isModified(@NotNull BuiltInServerOptions settings) {
+    return builtInServerPort.getNumber() != settings.builtInServerPort ||
+           builtInServerAvailableExternallyCheckBox.isSelected() != settings.builtInServerAvailableExternally;
+  }
+
+  @Override
+  public void apply(@NotNull BuiltInServerOptions settings) {
+    boolean builtInServerPortChanged = settings.builtInServerPort != builtInServerPort.getNumber() || settings.builtInServerAvailableExternally != builtInServerAvailableExternallyCheckBox.isSelected();
+    if (builtInServerPortChanged) {
+      settings.builtInServerPort = builtInServerPort.getNumber();
+      settings.builtInServerAvailableExternally = builtInServerAvailableExternallyCheckBox.isSelected();
+
+      BuiltInServerOptions.onBuiltInServerPortChanged();
+    }
+  }
+
+  @Override
+  public void reset(@NotNull BuiltInServerOptions settings) {
+    builtInServerPort.setNumber(settings.builtInServerPort);
+    builtInServerAvailableExternallyCheckBox.setSelected(settings.builtInServerAvailableExternally);
+  }
+}
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java
new file mode 100644
index 0000000..5eb65c1
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java
@@ -0,0 +1,116 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationDisplayType;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.ide.BuiltInServerManager;
+import org.jetbrains.ide.CustomPortServerManager;
+import org.jetbrains.io.CustomPortServerManagerBase;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+
+@State(
+  name = "BuiltInServerOptions",
+  storages = {
+    @Storage(
+      file = StoragePathMacros.APP_CONFIG + "/other.xml"
+    )}
+)
+public class BuiltInServerOptions implements PersistentStateComponent<BuiltInServerOptions>, ExportableComponent, Getter<BuiltInServerOptions> {
+  @Attribute
+  public int builtInServerPort = 63342;
+  @Attribute
+  public boolean builtInServerAvailableExternally = false;
+
+  public static BuiltInServerOptions getInstance() {
+    return ServiceManager.getService(BuiltInServerOptions.class);
+  }
+
+  @Override
+  public BuiltInServerOptions get() {
+    return this;
+  }
+
+  static final class BuiltInServerDebuggerConfigurableProvider extends DebuggerConfigurableProvider {
+    @NotNull
+    @Override
+    public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+      if (category == DebuggerSettingsCategory.GENERAL) {
+        return Collections.singletonList(SimpleConfigurable.create("builtInServer", "", BuiltInServerConfigurableUi.class, getInstance()));
+      }
+      return Collections.emptyList();
+    }
+  }
+
+  @NotNull
+  @Override
+  public File[] getExportFiles() {
+    return new File[]{PathManager.getOptionsFile("other")};
+  }
+
+  @NotNull
+  @Override
+  public String getPresentableName() {
+    return "Built-in server";
+  }
+
+  @Nullable
+  @Override
+  public BuiltInServerOptions getState() {
+    return this;
+  }
+
+  @Override
+  public void loadState(BuiltInServerOptions state) {
+    XmlSerializerUtil.copyBean(state, this);
+  }
+
+  public int getEffectiveBuiltInServerPort() {
+    MyCustomPortServerManager portServerManager = CustomPortServerManager.EP_NAME.findExtension(MyCustomPortServerManager.class);
+    if (!portServerManager.isBound()) {
+      return BuiltInServerManager.getInstance().getPort();
+    }
+    return builtInServerPort;
+  }
+
+  public static final class MyCustomPortServerManager extends CustomPortServerManagerBase {
+    @Override
+    public void cannotBind(Exception e, int port) {
+      String groupDisplayId = "Built-in Web Server";
+      Notifications.Bus.register(groupDisplayId, NotificationDisplayType.STICKY_BALLOON);
+      new Notification(groupDisplayId, "Built-in HTTP server on custom port " + port + " disabled",
+                       "Cannot start built-in HTTP server on custom port " + port + ". " +
+                       "Please ensure that port is free (or check your firewall settings) and restart " + ApplicationNamesInfo.getInstance().getFullProductName(),
+                       NotificationType.ERROR).notify(null);
+    }
+
+    @Override
+    public int getPort() {
+      return getInstance().builtInServerPort;
+    }
+
+    @Override
+    public boolean isAvailableExternally() {
+      return getInstance().builtInServerAvailableExternally;
+    }
+  }
+
+  public static void onBuiltInServerPortChanged() {
+    CustomPortServerManager.EP_NAME.findExtension(MyCustomPortServerManager.class).portChanged();
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java
new file mode 100644
index 0000000..f58d425
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java
@@ -0,0 +1,78 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.ide.browsers.OpenInBrowserRequest;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.Url;
+import com.intellij.util.Urls;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.ide.BuiltInServerManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implements DumbAware {
+  @NotNull
+  public static List<Url> getUrls(@NotNull VirtualFile file, @NotNull Project project, @Nullable String currentAuthority) {
+    if (currentAuthority != null && !compareAuthority(currentAuthority)) {
+      return Collections.emptyList();
+    }
+
+    String path = WebServerPathToFileManager.getInstance(project).getPath(file);
+    if (path == null) {
+      return Collections.emptyList();
+    }
+
+    int effectiveBuiltInServerPort = BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort();
+    Url url = Urls.newHttpUrl(currentAuthority == null ? "localhost:" + effectiveBuiltInServerPort : currentAuthority, '/' + project.getName() + '/' + path);
+    int defaultPort = BuiltInServerManager.getInstance().getPort();
+    if (currentAuthority != null || defaultPort == effectiveBuiltInServerPort) {
+      return Collections.singletonList(url);
+    }
+    return Arrays.asList(url, Urls.newHttpUrl("localhost:" + defaultPort, '/' + project.getName() + '/' + path));
+  }
+
+  public static boolean compareAuthority(@Nullable String currentAuthority) {
+    if (currentAuthority == null) {
+      return false;
+    }
+
+    int portIndex = currentAuthority.indexOf(':');
+    if (portIndex < 0) {
+      return false;
+    }
+
+    String host = currentAuthority.substring(0, portIndex);
+    if (!BuiltInWebServer.isOwnHostName(host)) {
+      return false;
+    }
+
+    int port = StringUtil.parseInt(currentAuthority.substring(portIndex + 1), -1);
+    return port == BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort() ||
+           port == BuiltInServerManager.getInstance().getPort();
+  }
+
+  @Override
+  public boolean canHandleElement(@NotNull OpenInBrowserRequest request) {
+    return request.getFile().getViewProvider().isPhysical() && !(request.getVirtualFile() instanceof LightVirtualFile) && isMyLanguage(request.getFile());
+  }
+
+  protected boolean isMyLanguage(PsiFile psiFile) {
+    return HtmlUtil.isHtmlFile(psiFile);
+  }
+
+  @Nullable
+  @Override
+  protected Url getUrl(@NotNull OpenInBrowserRequest request, @NotNull VirtualFile virtualFile) throws BrowserException {
+    return ContainerUtil.getFirstItem(getUrls(virtualFile, request.getProject(), null));
+  }
+}
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java
new file mode 100644
index 0000000..2dc24ba
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.util.SystemInfoRt;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.UriUtil;
+import com.intellij.util.io.URLUtil;
+import com.intellij.util.net.NetUtils;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.ide.HttpRequestHandler;
+import org.jetbrains.io.FileResponses;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import static org.jetbrains.io.Responses.sendOptionsResponse;
+import static org.jetbrains.io.Responses.sendStatus;
+
+public final class BuiltInWebServer extends HttpRequestHandler {
+  static final Logger LOG = Logger.getInstance(BuiltInWebServer.class);
+
+  @Nullable
+  public static VirtualFile findIndexFile(@NotNull VirtualFile basedir) {
+    VirtualFile[] children = basedir.getChildren();
+    if (children == null || children.length == 0) {
+      return null;
+    }
+
+    for (String indexNamePrefix : new String[]{"index.", "default."}) {
+      VirtualFile index = null;
+      String preferredName = indexNamePrefix + "html";
+      for (VirtualFile child : children) {
+        if (!child.isDirectory()) {
+          String name = child.getName();
+          if (name.equals(preferredName)) {
+            return child;
+          }
+          else if (index == null && name.startsWith(indexNamePrefix)) {
+            index = child;
+          }
+        }
+      }
+      if (index != null) {
+        return index;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public boolean isSupported(@NotNull FullHttpRequest request) {
+    return super.isSupported(request) || request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS;
+  }
+
+  @Override
+  public boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) {
+    if (request.method() == HttpMethod.OPTIONS) {
+      sendOptionsResponse("GET, POST, HEAD, OPTIONS", request, context);
+      return true;
+    }
+
+    String host = HttpHeaders.getHost(request);
+    if (StringUtil.isEmpty(host)) {
+      return false;
+    }
+
+    int portIndex = host.indexOf(':');
+    if (portIndex > 0) {
+      host = host.substring(0, portIndex);
+    }
+
+    String projectName;
+    boolean isIpv6 = host.charAt(0) == '[' && host.length() > 2 && host.charAt(host.length() - 1) == ']';
+    if (isIpv6) {
+      host = host.substring(1, host.length() - 1);
+    }
+
+    if (isIpv6 || Character.digit(host.charAt(0), 10) != -1 || host.charAt(0) == ':' || isOwnHostName(host)) {
+      if (urlDecoder.path().length() < 2) {
+        return false;
+      }
+      projectName = null;
+    }
+    else {
+      projectName = host;
+    }
+    return doProcess(request, context.channel(), projectName);
+  }
+
+  public static boolean isOwnHostName(@NotNull String host) {
+    if (NetUtils.isLocalhost(host)) {
+      return true;
+    }
+
+    try {
+      InetAddress address = InetAddress.getByName(host);
+      if (host.equals(address.getHostAddress()) || host.equalsIgnoreCase(address.getCanonicalHostName())) {
+        return true;
+      }
+
+      String localHostName = InetAddress.getLocalHost().getHostName();
+      // WEB-8889
+      // develar.local is own host name: develar. equals to "develar.labs.intellij.net" (canonical host name)
+      return localHostName.equalsIgnoreCase(host) ||
+             (host.endsWith(".local") && localHostName.regionMatches(true, 0, host, 0, host.length() - ".local".length()));
+    }
+    catch (UnknownHostException ignored) {
+      return false;
+    }
+  }
+
+  private static boolean doProcess(@NotNull FullHttpRequest request, @NotNull Channel channel, @Nullable String projectName) {
+    final String decodedPath = URLUtil.unescapePercentSequences(UriUtil.trimParameters(request.uri()));
+    int offset;
+    boolean emptyPath;
+    boolean isCustomHost = projectName != null;
+    if (isCustomHost) {
+      // host mapped to us
+      offset = 0;
+      emptyPath = decodedPath.isEmpty();
+    }
+    else {
+      offset = decodedPath.indexOf('/', 1);
+      projectName = decodedPath.substring(1, offset == -1 ? decodedPath.length() : offset);
+      emptyPath = offset == -1;
+    }
+
+    Project project = findProject(projectName, isCustomHost);
+    if (project == null) {
+      return false;
+    }
+
+    if (emptyPath) {
+      if (!SystemInfoRt.isFileSystemCaseSensitive) {
+        // may be passed path is not correct
+        projectName = project.getName();
+      }
+
+      // we must redirect "jsdebug" to "jsdebug/" as nginx does, otherwise browser will treat it as file instead of directory, so, relative path will not work
+      WebServerPathHandler.redirectToDirectory(request, channel, projectName);
+      return true;
+    }
+
+    final String path = FileUtil.toCanonicalPath(decodedPath.substring(offset + 1), '/');
+    LOG.assertTrue(path != null);
+
+    for (WebServerPathHandler pathHandler : WebServerPathHandler.EP_NAME.getExtensions()) {
+      try {
+        if (pathHandler.process(path, project, request, channel, projectName, decodedPath, isCustomHost)) {
+          return true;
+        }
+      }
+      catch (Throwable e) {
+        LOG.error(e);
+      }
+    }
+    return false;
+  }
+
+  static final class StaticFileHandler extends WebServerFileHandler {
+    @Override
+    public boolean process(@NotNull VirtualFile file,
+                           @NotNull CharSequence canonicalRequestPath,
+                           @NotNull Project project,
+                           @NotNull FullHttpRequest request,
+                           @NotNull Channel channel) throws IOException {
+      File ioFile = VfsUtilCore.virtualToIoFile(file);
+      if (hasAccess(ioFile)) {
+        FileResponses.sendFile(request, channel, ioFile);
+      }
+      else {
+        sendStatus(HttpResponseStatus.FORBIDDEN, channel, request);
+      }
+      return true;
+    }
+
+    private static boolean hasAccess(File result) {
+      // deny access to .htaccess files
+      return !result.isDirectory() && result.canRead() && !(result.isHidden() || result.getName().startsWith(".ht"));
+    }
+  }
+
+  @Nullable
+  private static Project findProject(String projectName, boolean isCustomHost) {
+    // user can rename project directory, so, we should support this case - find project by base directory name
+    Project candidateByDirectoryName = null;
+    for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+      String name = project.getName();
+      // domain name is case-insensitive
+      if (!project.isDisposed() && ((isCustomHost || !SystemInfoRt.isFileSystemCaseSensitive) ? projectName.equalsIgnoreCase(name) : projectName.equals(name))) {
+        return project;
+      }
+
+      if (candidateByDirectoryName == null && compareNameAndProjectBasePath(projectName, project)) {
+        candidateByDirectoryName = project;
+      }
+    }
+    return candidateByDirectoryName;
+  }
+
+  public static boolean compareNameAndProjectBasePath(String projectName, Project project) {
+    String basePath = project.getBasePath();
+    return basePath != null && basePath.length() > projectName.length() && basePath.endsWith(projectName) && basePath.charAt(basePath.length() - projectName.length() - 1) == '/';
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java
new file mode 100644
index 0000000..1b4acb0
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.io.Responses;
+
+final class DefaultWebServerPathHandler extends WebServerPathHandler {
+  @Override
+  public boolean process(@NotNull String path,
+                         @NotNull Project project,
+                         @NotNull FullHttpRequest request,
+                         @NotNull Channel channel,
+                         @Nullable String projectName,
+                         @NotNull String decodedRawPath,
+                         boolean isCustomHost) {
+    WebServerPathToFileManager pathToFileManager = WebServerPathToFileManager.getInstance(project);
+    VirtualFile result = pathToFileManager.pathToFileCache.getIfPresent(path);
+    boolean indexUsed = false;
+    if (result == null || !result.isValid()) {
+      result = pathToFileManager.findByRelativePath(project, path);
+      if (result == null) {
+        if (path.isEmpty()) {
+          Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
+          return true;
+        }
+        else {
+          return false;
+        }
+      }
+      else if (result.isDirectory()) {
+        if (!endsWithSlash(decodedRawPath)) {
+          redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
+          return true;
+        }
+
+        result = BuiltInWebServer.findIndexFile(result);
+        if (result == null) {
+          Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
+          return true;
+        }
+        indexUsed = true;
+      }
+
+      pathToFileManager.pathToFileCache.put(path, result);
+    }
+    else if (!path.endsWith(result.getName())) {
+      if (endsWithSlash(decodedRawPath)) {
+        indexUsed = true;
+      }
+      else {
+        // FallbackResource feature in action, /login requested, /index.php retrieved, we must not redirect /login to /login/
+        if (path.endsWith(result.getParent().getName())) {
+          redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
+          return true;
+        }
+      }
+    }
+
+    StringBuilder canonicalRequestPath = new StringBuilder();
+    canonicalRequestPath.append('/');
+    if (!isCustomHost) {
+      canonicalRequestPath.append(projectName).append('/');
+    }
+    canonicalRequestPath.append(path);
+    if (indexUsed) {
+      canonicalRequestPath.append('/').append(result.getName());
+    }
+
+    for (WebServerFileHandler fileHandler : WebServerFileHandler.EP_NAME.getExtensions()) {
+      try {
+        if (fileHandler.process(result, canonicalRequestPath, project, request, channel)) {
+          return true;
+        }
+      }
+      catch (Throwable e) {
+        BuiltInWebServer.LOG.error(e);
+      }
+    }
+
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
new file mode 100644
index 0000000..b562129
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PairFunction;
+import com.intellij.util.PlatformUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
+  @Nullable
+  @Override
+  public PathInfo resolve(@NotNull String path, @NotNull Project project) {
+    PairFunction<String, VirtualFile, VirtualFile> resolver;
+    if (PlatformUtils.isIntelliJ()) {
+      int index = path.indexOf('/');
+      if (index > 0 && !path.regionMatches(!SystemInfo.isFileSystemCaseSensitive, 0, project.getName(), 0, index)) {
+        String moduleName = path.substring(0, index);
+        AccessToken token = ReadAction.start();
+        Module module;
+        try {
+          module = ModuleManager.getInstance(project).findModuleByName(moduleName);
+        }
+        finally {
+          token.finish();
+        }
+
+        if (module != null && !module.isDisposed()) {
+          path = path.substring(index + 1);
+          resolver = WebServerPathToFileManager.getInstance(project).getResolver(path);
+
+          ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+          PathInfo result = resolve(path, moduleRootManager.getSourceRoots(), resolver, moduleName);
+          if (result == null) {
+            result = resolve(path, moduleRootManager.getContentRoots(), resolver, moduleName);
+          }
+          if (result != null) {
+            return result;
+          }
+        }
+      }
+    }
+
+    Module[] modules;
+    AccessToken token = ReadAction.start();
+    try {
+      modules = ModuleManager.getInstance(project).getModules();
+    }
+    finally {
+      token.finish();
+    }
+
+    resolver = WebServerPathToFileManager.getInstance(project).getResolver(path);
+    PathInfo result = findByRelativePath(project, path, modules, true, resolver);
+    if (result == null) {
+      // let's find in content roots
+      return findByRelativePath(project, path, modules, false, resolver);
+    }
+    else {
+      return result;
+    }
+  }
+
+  @Nullable
+  @Override
+  public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
+    AccessToken token = ReadAction.start();
+    try {
+      VirtualFile root = null;
+      ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+      if (fileIndex.isInSourceContent(file)) {
+        root = fileIndex.getSourceRootForFile(file);
+      }
+      else if (fileIndex.isInContent(file)) {
+        root = fileIndex.getContentRootForFile(file);
+      }
+      else if (fileIndex.isInLibraryClasses(file)) {
+        root = fileIndex.getClassRootForFile(file);
+      }
+      assert root != null : file.getPresentableUrl();
+      return new PathInfo(file, root, getModuleNameQualifier(project, fileIndex.getModuleForFile(file)));
+    }
+    finally {
+      token.finish();
+    }
+  }
+
+  @Nullable
+  private static String getModuleNameQualifier(@NotNull Project project, @Nullable Module module) {
+    if (module != null &&
+        PlatformUtils.isIntelliJ() &&
+        !(module.getName().equalsIgnoreCase(project.getName()) || BuiltInWebServer.compareNameAndProjectBasePath(module.getName(), project))) {
+      return module.getName();
+    }
+    return null;
+  }
+
+  @Nullable
+  private static PathInfo resolve(@NotNull String path, @NotNull VirtualFile[] roots, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver, @Nullable String moduleName) {
+    for (VirtualFile root : roots) {
+      VirtualFile file = resolver.fun(path, root);
+      if (file != null) {
+        return new PathInfo(file, root, moduleName);
+      }
+    }
+    return null;
+  }
+
+  @Nullable
+  private static PathInfo findByRelativePath(@NotNull Project project,
+                                             @NotNull String path,
+                                             @NotNull Module[] modules,
+                                             boolean inSourceRoot,
+                                             @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver) {
+    for (Module module : modules) {
+      if (!module.isDisposed()) {
+        ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+        PathInfo result = resolve(path, inSourceRoot ? moduleRootManager.getSourceRoots() : moduleRootManager.getContentRoots(), resolver, null);
+        if (result != null) {
+          result.moduleName = getModuleNameQualifier(project, module);
+          return result;
+        }
+      }
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java b/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java
new file mode 100644
index 0000000..b55b16b
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java
@@ -0,0 +1,47 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PathInfo {
+  private final VirtualFile child;
+  private final VirtualFile root;
+  String moduleName;
+
+  private String computedPath;
+
+  public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root, @Nullable String moduleName) {
+    this.child = child;
+    this.root = root;
+    this.moduleName = moduleName;
+  }
+
+  public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root) {
+    this(child, root, null);
+  }
+
+  @NotNull
+  public VirtualFile getChild() {
+    return child;
+  }
+
+  @NotNull
+  public VirtualFile getRoot() {
+    return root;
+  }
+
+  @Nullable
+  public String getModuleName() {
+    return moduleName;
+  }
+
+  @NotNull
+  public String getPath() {
+    if (computedPath == null) {
+      computedPath = (moduleName == null ? "" : moduleName + '/') + VfsUtilCore.getRelativePath(child, root, '/');
+    }
+    return computedPath;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java
new file mode 100644
index 0000000..145fded
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java
@@ -0,0 +1,18 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class PrefixlessWebServerRootsProvider extends WebServerRootsProvider {
+  @Nullable
+  @Override
+  public final PathInfo resolve(@NotNull String path, @NotNull Project project) {
+    return resolve(path, project, WebServerPathToFileManager.getInstance(project).getResolver(path));
+  }
+
+  @Nullable
+  public abstract PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver);
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java
new file mode 100644
index 0000000..9035af6
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+
+public abstract class WebServerFileHandler {
+  static final ExtensionPointName<WebServerFileHandler> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerFileHandler");
+
+  public abstract boolean process(@NotNull VirtualFile file,
+                                  @NotNull CharSequence canonicalRequestPath,
+                                  @NotNull Project project,
+                                  @NotNull FullHttpRequest request,
+                                  @NotNull Channel channel) throws IOException;
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java
new file mode 100644
index 0000000..807c3b3
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VfsUtil;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.io.Responses;
+
+import java.net.URI;
+
+/**
+ * By default {@link WebServerPathToFileManager} will be used to map request to file.
+ * If file physically exists in the file system, you must use {@link WebServerRootsProvider}.
+ *
+ * Consider to extend {@link WebServerPathHandlerAdapter} instead of implement low-level {@link #process(String, com.intellij.openapi.project.Project, io.netty.handler.codec.http.FullHttpRequest, io.netty.channel.Channel, String, String, boolean)}
+ */
+public abstract class WebServerPathHandler {
+  static final ExtensionPointName<WebServerPathHandler> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerPathHandler");
+
+  public abstract boolean process(@NotNull String path,
+                                  @NotNull Project project,
+                                  @NotNull FullHttpRequest request,
+                                  @NotNull Channel channel,
+                                  @Nullable String projectName,
+                                  @NotNull String decodedRawPath,
+                                  boolean isCustomHost);
+
+  protected static void redirectToDirectory(@NotNull HttpRequest request, @NotNull Channel channel, @NotNull String path) {
+    FullHttpResponse response = Responses.response(HttpResponseStatus.MOVED_PERMANENTLY);
+    URI url = VfsUtil.toUri("http://" + HttpHeaders.getHost(request) + '/' + path + '/');
+    BuiltInWebServer.LOG.assertTrue(url != null);
+    response.headers().add(HttpHeaders.Names.LOCATION, url.toASCIIString());
+    Responses.send(response, channel, request);
+  }
+
+  protected static boolean endsWithSlash(@NotNull String path) {
+    return path.charAt(path.length() - 1) == '/';
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java
new file mode 100644
index 0000000..a1f1e17
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class WebServerPathHandlerAdapter extends WebServerPathHandler {
+  protected abstract boolean process(@NotNull String path, @NotNull Project project, @NotNull FullHttpRequest request, @NotNull Channel channel);
+
+  @Override
+  public final boolean process(@NotNull String path,
+                               @NotNull Project project,
+                               @NotNull FullHttpRequest request,
+                               @NotNull Channel channel,
+                               @Nullable String projectName,
+                               @NotNull String decodedRawPath,
+                               boolean isCustomHost) {
+    return process(path, project, request, channel);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java
new file mode 100644
index 0000000..987fdcd
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java
@@ -0,0 +1,142 @@
+package org.jetbrains.builtInWebServer;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.intellij.ProjectTopics;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootAdapter;
+import com.intellij.openapi.roots.ModuleRootEvent;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.newvfs.BulkFileListener;
+import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Implement {@link WebServerRootsProvider} to add your provider
+ */
+public class WebServerPathToFileManager {
+  private static final PairFunction<String, VirtualFile, VirtualFile> RELATIVE_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
+    @Nullable
+    @Override
+    public VirtualFile fun(String path, VirtualFile parent) {
+      return parent.findFileByRelativePath(path);
+    }
+  };
+
+  private static final PairFunction<String, VirtualFile, VirtualFile> EMPTY_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
+    @Nullable
+    @Override
+    public VirtualFile fun(String path, VirtualFile parent) {
+      return BuiltInWebServer.findIndexFile(parent);
+    }
+  };
+
+  private final Project project;
+
+  final Cache<String, VirtualFile> pathToFileCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(10, TimeUnit.MINUTES).build();
+  // time to expire should be greater than pathToFileCache
+  private final Cache<VirtualFile, PathInfo> fileToRoot = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(11, TimeUnit.MINUTES).build();
+
+  public static WebServerPathToFileManager getInstance(@NotNull Project project) {
+    return ServiceManager.getService(project, WebServerPathToFileManager.class);
+  }
+
+  public WebServerPathToFileManager(@NotNull Application application, @NotNull Project project) {
+    this.project = project;
+    application.getMessageBus().connect(project).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
+      @Override
+      public void after(@NotNull List<? extends VFileEvent> events) {
+        for (VFileEvent event : events) {
+          if (event instanceof VFileContentChangeEvent) {
+            VirtualFile file = ((VFileContentChangeEvent)event).getFile();
+            for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+              if (rootsProvider.isClearCacheOnFileContentChanged(file)) {
+                clearCache();
+                break;
+              }
+            }
+          }
+          else {
+            clearCache();
+            break;
+          }
+        }
+      }
+    });
+    project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+      @Override
+      public void rootsChanged(ModuleRootEvent event) {
+        clearCache();
+      }
+    });
+  }
+
+  private void clearCache() {
+    pathToFileCache.invalidateAll();
+    fileToRoot.invalidateAll();
+  }
+
+  @Nullable
+  public VirtualFile get(@NotNull String path) {
+    return get(path, true);
+  }
+
+  @Nullable
+  public VirtualFile get(@NotNull String path, boolean cacheResult) {
+    VirtualFile result = pathToFileCache.getIfPresent(path);
+    if (result == null || !result.isValid()) {
+      result = findByRelativePath(project, path);
+      if (cacheResult && result != null && result.isValid()) {
+        pathToFileCache.put(path, result);
+      }
+    }
+    return result;
+  }
+
+  @Nullable
+  public String getPath(@NotNull VirtualFile file) {
+    PathInfo pathInfo = getRoot(file);
+    return pathInfo == null ? null : pathInfo.getPath();
+  }
+
+  @Nullable
+  public PathInfo getRoot(@NotNull VirtualFile child) {
+    PathInfo result = fileToRoot.getIfPresent(child);
+    if (result == null) {
+      for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+        result = rootsProvider.getRoot(child, project);
+        if (result != null) {
+          fileToRoot.put(child, result);
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+  @Nullable
+  VirtualFile findByRelativePath(@NotNull Project project, @NotNull String path) {
+    for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+      PathInfo result = rootsProvider.resolve(path, project);
+      if (result != null) {
+        fileToRoot.put(result.getChild(), result);
+        return result.getChild();
+      }
+    }
+    return null;
+  }
+
+  @NotNull
+  public PairFunction<String, VirtualFile, VirtualFile> getResolver(@NotNull String path) {
+    return path.isEmpty() ? EMPTY_PATH_RESOLVER : RELATIVE_PATH_RESOLVER;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java
new file mode 100644
index 0000000..bb89725
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java
@@ -0,0 +1,21 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class WebServerRootsProvider {
+  static final ExtensionPointName<WebServerRootsProvider> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerRootsProvider");
+
+  @Nullable
+  public abstract PathInfo resolve(@NotNull String path, @NotNull Project project);
+
+  @Nullable
+  public abstract PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project);
+
+  public boolean isClearCacheOnFileContentChanged(@NotNull VirtualFile file) {
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java
new file mode 100644
index 0000000..d240782
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java
@@ -0,0 +1,108 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.util.containers.ConcurrentIntObjectMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.*;
+import org.jetbrains.io.Responses;
+import org.jetbrains.io.SimpleChannelInboundHandlerAdapter;
+
+import static org.jetbrains.io.fastCgi.FastCgiService.LOG;
+
+@ChannelHandler.Sharable
+public class FastCgiChannelHandler extends SimpleChannelInboundHandlerAdapter<FastCgiResponse> {
+  private final ConcurrentIntObjectMap<Channel> requestToChannel;
+
+  public FastCgiChannelHandler(ConcurrentIntObjectMap<Channel> channel) {
+    requestToChannel = channel;
+  }
+
+  @Override
+  protected void messageReceived(ChannelHandlerContext context, FastCgiResponse response) throws Exception {
+    ByteBuf buffer = response.getData();
+    Channel channel = requestToChannel.remove(response.getId());
+    if (channel == null || !channel.isActive()) {
+      if (buffer != null) {
+        buffer.release();
+      }
+      return;
+    }
+
+    if (buffer == null) {
+      Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+      return;
+    }
+
+    HttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buffer);
+    try {
+      parseHeaders(httpResponse, buffer);
+      Responses.addServer(httpResponse);
+      if (!HttpHeaders.isContentLengthSet(httpResponse)) {
+        HttpHeaders.setContentLength(httpResponse, buffer.readableBytes());
+      }
+    }
+    catch (Throwable e) {
+      buffer.release();
+      Responses.sendStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR, channel);
+      LOG.error(e);
+    }
+    channel.writeAndFlush(httpResponse);
+  }
+
+  private static void parseHeaders(HttpResponse response, ByteBuf buffer) {
+    StringBuilder builder = new StringBuilder();
+    while (buffer.isReadable()) {
+      builder.setLength(0);
+
+      String key = null;
+      boolean valueExpected = true;
+      while (true) {
+        int b = buffer.readByte();
+        if (b < 0 || b == '\n') {
+          break;
+        }
+
+        if (b != '\r') {
+          if (valueExpected && b == ':') {
+            valueExpected = false;
+
+            key = builder.toString();
+            builder.setLength(0);
+            skipWhitespace(buffer);
+          }
+          else {
+            builder.append((char)b);
+          }
+        }
+      }
+
+      if (builder.length() == 0) {
+        // end of headers
+        return;
+      }
+
+      // skip standard headers
+      if (StringUtil.isEmpty(key) || StringUtilRt.startsWithIgnoreCase(key, "http") || StringUtilRt.startsWithIgnoreCase(key, "X-Accel-")) {
+        continue;
+      }
+
+      String value = builder.toString();
+      if (key.equalsIgnoreCase("status")) {
+        response.setStatus(HttpResponseStatus.valueOf(Integer.parseInt(value.substring(0, value.indexOf(' ')))));
+      }
+      else if (!(key.startsWith("http") || key.startsWith("HTTP"))) {
+        response.headers().add(key, value);
+      }
+    }
+  }
+
+  private static void skipWhitespace(ByteBuf buffer) {
+    while (buffer.isReadable() && buffer.getByte(buffer.readerIndex()) == ' ') {
+      buffer.skipBytes(1);
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java
new file mode 100644
index 0000000..23a85de
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java
@@ -0,0 +1,5 @@
+package org.jetbrains.io.fastCgi;
+
+public final class FastCgiConstants {
+  public static final int HEADER_LENGTH = 8;
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java
new file mode 100644
index 0000000..1cd7adb
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java
@@ -0,0 +1,149 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.util.Consumer;
+import gnu.trove.TIntObjectHashMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.CompositeByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.CharsetUtil;
+import org.jetbrains.io.Decoder;
+
+import static org.jetbrains.io.fastCgi.FastCgiService.LOG;
+
+public class FastCgiDecoder extends Decoder {
+  private enum State {
+    HEADER, CONTENT
+  }
+
+  private State state = State.HEADER;
+
+  private enum ProtocolStatus {
+    REQUEST_COMPLETE, CANT_MPX_CONN, OVERLOADED, UNKNOWN_ROLE
+  }
+
+  public static final class RecordType {
+    public static final int END_REQUEST = 3;
+    public static final int STDOUT = 6;
+    public static final int STDERR = 7;
+  }
+
+  private int type;
+  private int id;
+  private int contentLength;
+  private int paddingLength;
+
+  private final TIntObjectHashMap<ByteBuf> dataBuffers = new TIntObjectHashMap<ByteBuf>();
+
+  private final Consumer<String> errorOutputConsumer;
+
+  public FastCgiDecoder(Consumer<String> errorOutputConsumer) {
+    this.errorOutputConsumer = errorOutputConsumer;
+  }
+
+  @Override
+  protected void messageReceived(ChannelHandlerContext context, ByteBuf input) throws Exception {
+    while (true) {
+      switch (state) {
+        case HEADER: {
+          if (paddingLength > 0) {
+            if (input.readableBytes() >= paddingLength) {
+              input.skipBytes(paddingLength);
+              paddingLength = 0;
+            }
+            else {
+              paddingLength -= input.readableBytes();
+              input.skipBytes(input.readableBytes());
+              input.release();
+              return;
+            }
+          }
+
+          ByteBuf buffer = getBufferIfSufficient(input, FastCgiConstants.HEADER_LENGTH, context);
+          if (buffer == null) {
+            input.release();
+            return;
+          }
+
+          decodeHeader(buffer);
+          state = State.CONTENT;
+        }
+
+        case CONTENT: {
+          if (contentLength > 0) {
+            ByteBuf buffer = getBufferIfSufficient(input, contentLength, context);
+            if (buffer == null) {
+              input.release();
+              return;
+            }
+
+            FastCgiResponse response = readContent(buffer);
+            if (response != null) {
+              context.fireChannelRead(response);
+            }
+          }
+          state = State.HEADER;
+        }
+      }
+    }
+  }
+
+  private void decodeHeader(ByteBuf buffer) {
+    buffer.skipBytes(1);
+    type = buffer.readUnsignedByte();
+    id = buffer.readUnsignedShort();
+    contentLength = buffer.readUnsignedShort();
+    paddingLength = buffer.readUnsignedByte();
+    buffer.skipBytes(1);
+  }
+
+  private FastCgiResponse readContent(ByteBuf buffer) {
+    switch (type) {
+      case RecordType.END_REQUEST:
+        int appStatus = buffer.readInt();
+        int protocolStatus = buffer.readUnsignedByte();
+        buffer.skipBytes(3);
+        if (appStatus != 0 || protocolStatus != ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+          LOG.warn("Protocol status " + protocolStatus);
+          dataBuffers.remove(id);
+          return new FastCgiResponse(id, null);
+        }
+        else if (protocolStatus == ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+          return new FastCgiResponse(id, dataBuffers.remove(id));
+        }
+        break;
+
+      case RecordType.STDOUT:
+        ByteBuf data = dataBuffers.get(id);
+        ByteBuf sliced = buffer.slice(buffer.readerIndex(), contentLength);
+        if (data == null) {
+          dataBuffers.put(id, sliced);
+        }
+        else if (data instanceof CompositeByteBuf) {
+          ((CompositeByteBuf)data).addComponent(sliced);
+          data.writerIndex(data.writerIndex() + sliced.readableBytes());
+        }
+        else {
+          dataBuffers.put(id, Unpooled.wrappedBuffer(data, sliced));
+        }
+        sliced.retain();
+        buffer.skipBytes(contentLength);
+        break;
+
+      case RecordType.STDERR:
+        try {
+          errorOutputConsumer.consume(buffer.toString(buffer.readerIndex(), contentLength, CharsetUtil.UTF_8));
+        }
+        catch (Throwable e) {
+          LOG.error(e);
+        }
+        buffer.skipBytes(contentLength);
+        break;
+
+      default:
+        LOG.error("Unknown type " + type);
+        break;
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java
new file mode 100644
index 0000000..e92d20e
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java
@@ -0,0 +1,149 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.util.CharsetUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.builtInWebServer.PathInfo;
+import org.jetbrains.builtInWebServer.WebServerPathToFileManager;
+import org.jetbrains.io.Responses;
+
+import java.net.InetSocketAddress;
+import java.util.Locale;
+import java.util.Map;
+
+public class FastCgiRequest {
+  private static final int PARAMS = 4;
+  private static final int BEGIN_REQUEST = 1;
+  private static final int RESPONDER = 1;
+  private static final int FCGI_KEEP_CONNECTION = 1;
+  private static final int STDIN = 5;
+  private static final int VERSION = 1;
+
+  private final ByteBuf buffer;
+  final int requestId;
+
+  public FastCgiRequest(int requestId, @NotNull ByteBufAllocator allocator) {
+    this.requestId = requestId;
+
+    buffer = allocator.buffer();
+    writeHeader(buffer, BEGIN_REQUEST, FastCgiConstants.HEADER_LENGTH);
+    buffer.writeShort(RESPONDER);
+    buffer.writeByte(FCGI_KEEP_CONNECTION);
+    buffer.writeZero(5);
+  }
+
+  public void writeFileHeaders(@NotNull VirtualFile file, @NotNull Project project, @NotNull CharSequence canonicalRequestPath) {
+    PathInfo root = WebServerPathToFileManager.getInstance(project).getRoot(file);
+    FastCgiService.LOG.assertTrue(root != null);
+    addHeader("DOCUMENT_ROOT", root.getRoot().getPath());
+    addHeader("SCRIPT_FILENAME", file.getPath());
+    addHeader("SCRIPT_NAME", canonicalRequestPath);
+  }
+
+  public final void addHeader(@NotNull String key, @Nullable CharSequence value) {
+    if (value == null) {
+      return;
+    }
+
+    int keyLength = key.length();
+    int valLength = value.length();
+    writeHeader(buffer, PARAMS, keyLength + valLength + (keyLength < 0x80 ? 1 : 4) + (valLength < 0x80 ? 1 : 4));
+
+    if (keyLength < 0x80) {
+      buffer.writeByte(keyLength);
+    }
+    else {
+      buffer.writeByte(0x80 | (keyLength >> 24));
+      buffer.writeByte(keyLength >> 16);
+      buffer.writeByte(keyLength >> 8);
+      buffer.writeByte(keyLength);
+    }
+
+    if (valLength < 0x80) {
+      buffer.writeByte(valLength);
+    }
+    else {
+      buffer.writeByte(0x80 | (valLength >> 24));
+      buffer.writeByte(valLength >> 16);
+      buffer.writeByte(valLength >> 8);
+      buffer.writeByte(valLength);
+    }
+
+    buffer.writeBytes(key.getBytes(CharsetUtil.US_ASCII));
+    buffer.writeBytes(Unpooled.copiedBuffer(value, CharsetUtil.UTF_8));
+  }
+
+  public void writeHeaders(FullHttpRequest request, Channel clientChannel) {
+    addHeader("REQUEST_URI", request.uri());
+    addHeader("REQUEST_METHOD", request.method().name());
+
+    InetSocketAddress remote = (InetSocketAddress)clientChannel.remoteAddress();
+    addHeader("REMOTE_ADDR", remote.getAddress().getHostAddress());
+    addHeader("REMOTE_PORT", Integer.toString(remote.getPort()));
+
+    InetSocketAddress local = (InetSocketAddress)clientChannel.localAddress();
+    addHeader("SERVER_SOFTWARE", Responses.getServerHeaderValue());
+    addHeader("SERVER_NAME", Responses.getServerHeaderValue());
+
+    addHeader("SERVER_ADDR", local.getAddress().getHostAddress());
+    addHeader("SERVER_PORT", Integer.toString(local.getPort()));
+
+    addHeader("GATEWAY_INTERFACE", "CGI/1.1");
+    addHeader("SERVER_PROTOCOL", request.protocolVersion().text());
+    addHeader("CONTENT_TYPE", request.headers().get(HttpHeaders.Names.CONTENT_TYPE));
+
+    // PHP only, required if PHP was built with --enable-force-cgi-redirect
+    addHeader("REDIRECT_STATUS", "200");
+
+    String queryString = "";
+    int queryIndex = request.uri().indexOf('?');
+    if (queryIndex != -1) {
+      queryString = request.uri().substring(queryIndex + 1);
+    }
+    addHeader("QUERY_STRING", queryString);
+
+    addHeader("CONTENT_LENGTH", String.valueOf(request.content().readableBytes()));
+
+    for (Map.Entry<String, String> entry : request.headers()) {
+      addHeader("HTTP_" + entry.getKey().replace('-', '_').toUpperCase(Locale.ENGLISH), entry.getValue());
+    }
+  }
+
+  final void writeToServerChannel(ByteBuf content, Channel fastCgiChannel) {
+    writeHeader(buffer, PARAMS, 0);
+    fastCgiChannel.write(buffer);
+
+    if (content.isReadable()) {
+      ByteBuf headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH);
+      writeHeader(headerBuffer, STDIN, content.readableBytes());
+      fastCgiChannel.write(headerBuffer);
+
+      fastCgiChannel.write(content);
+
+      headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH);
+      writeHeader(headerBuffer, STDIN, 0);
+      fastCgiChannel.write(headerBuffer);
+    }
+    else {
+      content.release();
+    }
+
+    fastCgiChannel.flush();
+  }
+
+  private void writeHeader(ByteBuf buffer, int type, int length) {
+    buffer.writeByte(VERSION);
+    buffer.writeByte(type);
+    buffer.writeShort(requestId);
+    buffer.writeShort(length);
+    buffer.writeZero(2);
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java
new file mode 100644
index 0000000..e249f71
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java
@@ -0,0 +1,21 @@
+package org.jetbrains.io.fastCgi;
+
+import io.netty.buffer.ByteBuf;
+
+public class FastCgiResponse {
+  private final int id;
+  private final ByteBuf data;
+
+  public FastCgiResponse(int id, ByteBuf data) {
+    this.id = id;
+    this.data = data;
+  }
+
+  public ByteBuf getData() {
+    return data;
+  }
+
+  public int getId() {
+    return id;
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java
new file mode 100644
index 0000000..54f13c6
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java
@@ -0,0 +1,249 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.concurrency.JobScheduler;
+import com.intellij.execution.filters.TextConsoleBuilder;
+import com.intellij.execution.filters.TextConsoleBuilderFactory;
+import com.intellij.execution.process.OSProcessHandler;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.execution.ui.ConsoleViewContentType;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.AsyncValueLoader;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.ContentFactory;
+import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
+import com.intellij.util.net.NetUtils;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.io.ChannelExceptionHandler;
+import org.jetbrains.io.NettyUtil;
+import org.jetbrains.io.Responses;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+// todo send FCGI_ABORT_REQUEST if client channel disconnected
+public abstract class FastCgiService implements Disposable {
+  static final Logger LOG = Logger.getInstance(FastCgiService.class);
+
+  protected final Project project;
+
+  private final AtomicInteger requestIdCounter = new AtomicInteger();
+  private final StripedLockIntObjectConcurrentHashMap<Channel> requests = new StripedLockIntObjectConcurrentHashMap<Channel>();
+
+  private volatile Channel fastCgiChannel;
+
+  protected final AsyncValueLoader<OSProcessHandler> processHandler = new AsyncValueLoader<OSProcessHandler>() {
+    @Override
+    protected boolean isCancelOnReject() {
+      return true;
+    }
+
+    @Override
+    protected void load(@NotNull final AsyncResult<OSProcessHandler> result) throws IOException {
+      final int port = NetUtils.findAvailableSocketPort();
+      final OSProcessHandler processHandler = createProcessHandler(project, port);
+      if (processHandler == null) {
+        result.setRejected();
+        return;
+      }
+
+      result.doWhenRejected(new Runnable() {
+        @Override
+        public void run() {
+          processHandler.destroyProcess();
+        }
+      });
+
+      final MyProcessAdapter processListener = new MyProcessAdapter();
+      processHandler.addProcessListener(processListener);
+      processHandler.startNotify();
+
+      if (result.isRejected()) {
+        return;
+      }
+
+      JobScheduler.getScheduler().schedule(new Runnable() {
+        @Override
+        public void run() {
+          if (result.isRejected()) {
+            return;
+          }
+
+          ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+            @Override
+            public void run() {
+              if (!result.isRejected()) {
+                try {
+                  connectToProcess(result, port, processHandler, processListener);
+                }
+                catch (Throwable e) {
+                  result.setRejected();
+                  LOG.error(e);
+                }
+              }
+            }
+          });
+        }
+      }, NettyUtil.MIN_START_TIME, TimeUnit.MILLISECONDS);
+    }
+
+    @Override
+    protected void disposeResult(@NotNull OSProcessHandler processHandler) {
+      try {
+        Channel currentFastCgiChannel = fastCgiChannel;
+        if (currentFastCgiChannel != null) {
+          fastCgiChannel = null;
+          NettyUtil.closeAndReleaseFactory(currentFastCgiChannel);
+        }
+        processHandler.destroyProcess();
+      }
+      finally {
+        requestIdCounter.set(0);
+        if (!requests.isEmpty()) {
+          List<Channel> waitingClients = ContainerUtil.toList(requests.elements());
+          requests.clear();
+          for (Channel channel : waitingClients) {
+            try {
+              if (channel.isActive()) {
+                Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+              }
+            }
+            catch (Throwable e) {
+              NettyUtil.log(e, LOG);
+            }
+          }
+        }
+      }
+    }
+  };
+
+  private ConsoleView console;
+
+  protected FastCgiService(Project project) {
+    this.project = project;
+  }
+
+  protected abstract OSProcessHandler createProcessHandler(Project project, int port);
+
+  private void connectToProcess(final AsyncResult<OSProcessHandler> asyncResult, final int port, final OSProcessHandler processHandler, final Consumer<String> errorOutputConsumer) {
+    Bootstrap bootstrap = NettyUtil.oioClientBootstrap();
+    final FastCgiChannelHandler fastCgiChannelHandler = new FastCgiChannelHandler(requests);
+    bootstrap.handler(new ChannelInitializer() {
+      @Override
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(new FastCgiDecoder(errorOutputConsumer), fastCgiChannelHandler, ChannelExceptionHandler.getInstance());
+      }
+    });
+    fastCgiChannel = NettyUtil.connectClient(bootstrap, new InetSocketAddress(NetUtils.getLoopbackAddress(), port), asyncResult);
+    if (fastCgiChannel != null) {
+      asyncResult.setDone(processHandler);
+    }
+  }
+
+  public void send(final FastCgiRequest fastCgiRequest, final ByteBuf content) {
+    content.retain();
+
+    if (processHandler.has()) {
+      fastCgiRequest.writeToServerChannel(content, fastCgiChannel);
+    }
+    else {
+      processHandler.get().doWhenDone(new Runnable() {
+        @Override
+        public void run() {
+          fastCgiRequest.writeToServerChannel(content, fastCgiChannel);
+        }
+      }).doWhenRejected(new Runnable() {
+        @Override
+        public void run() {
+          content.release();
+          Channel channel = requests.get(fastCgiRequest.requestId);
+          if (channel != null && channel.isActive()) {
+            Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+          }
+        }
+      });
+    }
+  }
+
+  public int allocateRequestId(Channel channel) {
+    int requestId = requestIdCounter.getAndIncrement();
+    if (requestId >= Short.MAX_VALUE) {
+      requestIdCounter.set(0);
+      requestId = requestIdCounter.getAndDecrement();
+    }
+    requests.put(requestId, channel);
+    return requestId;
+  }
+
+  @Override
+  public void dispose() {
+    processHandler.reset();
+  }
+
+  protected abstract void buildConsole(@NotNull TextConsoleBuilder consoleBuilder);
+
+  @NotNull
+  protected abstract String getConsoleToolWindowId();
+
+  @NotNull
+  protected abstract Icon getConsoleToolWindowIcon();
+
+  private final class MyProcessAdapter extends ProcessAdapter implements Consumer<String> {
+    private void createConsole() {
+      TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
+      buildConsole(consoleBuilder);
+      console = consoleBuilder.getConsole();
+
+      ApplicationManager.getApplication().invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          ToolWindow toolWindow = ToolWindowManager.getInstance(project).registerToolWindow(getConsoleToolWindowId(), false, ToolWindowAnchor.BOTTOM, project, true);
+          toolWindow.setIcon(getConsoleToolWindowIcon());
+          toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(console.getComponent(), "", false));
+        }
+      }, project.getDisposed());
+    }
+
+    @Override
+    public void onTextAvailable(ProcessEvent event, Key outputType) {
+      print(event.getText(), ConsoleViewContentType.getConsoleViewType(outputType));
+    }
+
+    private void print(String text, ConsoleViewContentType contentType) {
+      if (console == null) {
+        createConsole();
+      }
+      console.print(text, contentType);
+    }
+
+    @Override
+    public void processTerminated(ProcessEvent event) {
+      processHandler.reset();
+      print(getConsoleToolWindowId() + " terminated\n", ConsoleViewContentType.SYSTEM_OUTPUT);
+    }
+
+    @Override
+    public void consume(String message) {
+      print(message, ConsoleViewContentType.ERROR_OUTPUT);
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java b/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java
new file mode 100644
index 0000000..4ea4a10
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java
@@ -0,0 +1,86 @@
+package org.jetbrains.notification;
+
+import com.intellij.notification.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindowManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public final class SingletonNotificationManager {
+  private final AtomicReference<Notification> notification = new AtomicReference<Notification>();
+
+  private final NotificationGroup group;
+  private final NotificationType type;
+  @Nullable
+  private final NotificationListener listener;
+
+  private Runnable expiredListener;
+
+  public SingletonNotificationManager(@NotNull String groupId, @NotNull NotificationType type, @Nullable NotificationListener listener) {
+    this(new NotificationGroup(groupId, NotificationDisplayType.STICKY_BALLOON, true), type, listener);
+  }
+
+  public SingletonNotificationManager(@NotNull NotificationGroup group, @NotNull NotificationType type, @Nullable NotificationListener listener) {
+    this.group = group;
+    this.type = type;
+    this.listener = listener;
+  }
+
+  public boolean notify(@NotNull String title, @NotNull String content) {
+    return notify(title, content, null);
+  }
+
+  public boolean notify(@NotNull String title, @NotNull String content, @Nullable Project project) {
+    return notify(title, content, listener, project);
+  }
+
+  public boolean notify(@NotNull String content, @Nullable Project project) {
+    return notify("", content, listener, project);
+  }
+
+  public boolean notify(@NotNull String title,
+                        @NotNull String content,
+                        @Nullable NotificationListener listener,
+                        @Nullable Project project) {
+    Notification oldNotification = notification.get();
+    // !oldNotification.isExpired() is not enough - notification could be closed, but not expired
+    if (oldNotification != null) {
+      if (!oldNotification.isExpired() && (oldNotification.getBalloon() != null ||
+                                           (project != null &&
+                                            group.getDisplayType() == NotificationDisplayType.TOOL_WINDOW &&
+                                            ToolWindowManager.getInstance(project).getToolWindowBalloon(group.getToolWindowId()) != null))) {
+        return false;
+      }
+      oldNotification.whenExpired(null);
+      oldNotification.expire();
+    }
+
+    if (expiredListener == null) {
+      expiredListener = new Runnable() {
+        @Override
+        public void run() {
+          Notification currentNotification = notification.get();
+          if (currentNotification != null && currentNotification.isExpired()) {
+            notification.compareAndSet(currentNotification, null);
+          }
+        }
+      };
+    }
+
+    Notification newNotification = group.createNotification(title, content, type, listener);
+    newNotification.whenExpired(expiredListener);
+    notification.set(newNotification);
+    newNotification.notify(project);
+    return true;
+  }
+
+  public void clear() {
+    Notification oldNotification = notification.getAndSet(null);
+    if (oldNotification != null) {
+      oldNotification.whenExpired(null);
+      oldNotification.expire();
+    }
+  }
+}
\ No newline at end of file
diff --git a/xml/impl/xml.iml b/xml/impl/xml.iml
index 60e2108..2fb3ee7 100644
--- a/xml/impl/xml.iml
+++ b/xml/impl/xml.iml
@@ -21,6 +21,8 @@
     <orderEntry type="module" module-name="xml-analysis-impl" exported="" />
     <orderEntry type="library" name="swingx" level="project" />
     <orderEntry type="module" module-name="xml-structure-view-impl" exported="" />
+    <orderEntry type="library" name="Netty" level="project" />
+    <orderEntry type="module" module-name="xdebugger-api" />
   </component>
   <component name="copyright">
     <Base>
diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
index 2eee288..d030ccf 100644
--- a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
@@ -47,7 +47,7 @@
 
 @State(name = "ExternalResourceManagerImpl",
        storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml")})
-public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx {
+public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx implements JDOMExternalizable {
   static final Logger LOG = Logger.getInstance("#com.intellij.j2ee.openapi.impl.ExternalResourceManagerImpl");
 
   @NonNls public static final String J2EE_1_3 = "http://java.sun.com/dtd/";
@@ -374,6 +374,7 @@
     return getProjectResources(project).getModificationCount();
   }
 
+  @Override
   public void readExternal(Element element) {
     final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
     myPathMacros.addMacroExpands(macroExpands);
@@ -404,6 +405,7 @@
     }
   }
 
+  @Override
   public void writeExternal(Element element) {
     final String[] urls = getAvailableUrls();
     for (String url : urls) {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
index 86b2368..be3b972 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
@@ -59,10 +59,18 @@
       return null;
     }
 
-    VirtualFile childFile = file.findChild(name);
-    HttpFileSystem fileSystem = (HttpFileSystem)getVirtualFile().getFileSystem();
+    VirtualFile parent = file;
+    if (!parent.isDirectory()) {
+      parent = parent.getParent();
+      if (parent == null) {
+        parent = file;
+      }
+    }
+
+    VirtualFile childFile = parent.findChild(name);
+    HttpFileSystem fileSystem = (HttpFileSystem)parent.getFileSystem();
     if (childFile == null) {
-      childFile = fileSystem.createChild(getVirtualFile(), name, !reference.isLast());
+      childFile = fileSystem.createChild(parent, name, !reference.isLast());
     }
     if (childFile.isDirectory()) {
       // pre create children
@@ -72,7 +80,6 @@
         FileReference childReference = references[i];
         childParent = fileSystem.createChild(childParent, childReference.decode(childReference.getText()), i != (n - 1));
       }
-
       return getManager().findDirectory(childFile);
     }
     else {