Merge "Merge remote-tracking branch 'aosp/snapshot-master' into merge"
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 7294669..babd7be 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -24,7 +24,6 @@
       <module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" group="plugins/GAE" />
       <module fileurl="file://$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" filepath="$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" group="plugins/Android/android-sdk" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/svn4idea/bindSvn/bindSvn.iml" filepath="$PROJECT_DIR$/plugins/svn4idea/bindSvn/bindSvn.iml" group="plugins/VCS" />
       <module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
diff --git a/bin/win/jumplistbridge.dll b/bin/win/jumplistbridge.dll
index 611dd62..4a0cf8a 100644
--- a/bin/win/jumplistbridge.dll
+++ b/bin/win/jumplistbridge.dll
Binary files differ
diff --git a/bin/win/jumplistbridge64.dll b/bin/win/jumplistbridge64.dll
index fad8c52..2d830ce 100644
--- a/bin/win/jumplistbridge64.dll
+++ b/bin/win/jumplistbridge64.dll
Binary files differ
diff --git a/build.txt b/build.txt
index bc0cfb9..7a425c0 100644
--- a/build.txt
+++ b/build.txt
@@ -1 +1 @@
-130.SNAPSHOT
+132.SNAPSHOT
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index db74272..655b0b5 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -323,9 +323,6 @@
     }
 
     layoutPlugin("svn4idea") {
-      jar("bindSvn.jar") {
-        module("bindSvn")
-      }
       fileset(dir: "$home/plugins/svn4idea/lib", excludes: "**/svnkitsrc.zip")
     }
 
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index b4fd69a..f952acd 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -248,7 +248,7 @@
 libraryLicense(name: "XStream", version: "1.4.3", license: "BSD", url: "http://xstream.codehaus.org/", licenseUrl: "http://xstream.codehaus.org/license.html")
 libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "8.0.x", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html")
 libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367")
-libraryLicense(name: "Netty", libraryName: "Netty", version: "4.0.8-SNAPSHOT", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
+libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Alpha1", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
 libraryLicense(name: "Kryo", libraryName: "Kryo", version: "1.04", license: "New BSD License", url: "http://code.google.com/p/kryo/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php")
 libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "1.0.5", license: "Apache 2.0", url: "http://code.google.com/p/snappy-java/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
 libraryLicense(name: "Cucumber-Java", libraryName: "cucumber-java", version: "1.0.14", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html")
diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml
index e76db38..8e36755 100644
--- a/community-resources/src/idea/IdeaApplicationInfo.xml
+++ b/community-resources/src/idea/IdeaApplicationInfo.xml
@@ -2,7 +2,7 @@
   <version codename="Community Edition" major="13" minor="0" eap="true"/>
   <company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
   <build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
-  <install-over minbuild="129.1" maxbuild="130.9999" version="12.1"/>
+  <install-over minbuild="129.1" maxbuild="132.9999" version="12.1"/>
   <logo url="/idea_community_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
   <about url="/idea_community_about.png" foreground="f5f5f5" linkColor="9dc0ff" logoX="300" logoY="265" logoW="75" logoH="30"/>
   <icon size32="/icon_CE.png" size16="/icon_CEsmall.png" size32opaque="/icon_CEwhite.png" size12="/toolwindows/toolWindowProject.png" size128="/icon_CE_128.png" ico="idea_CE.ico"/>
@@ -10,7 +10,7 @@
   <names product="IDEA" fullname="IntelliJ IDEA" script="idea"/>
 
   <welcome-screen logo-url="/Logo_welcomeScreen.png"
-                  caption-url="/welcomeCaption_community.png" 
+                  caption-url="/welcomeCaption_community.png"
                   slogan-url="/developSlogan_community.png"/>
 
   <third-party url="http://www.jetbrains.org/"/>
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsManager.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsFilter.java
similarity index 90%
rename from java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsManager.java
rename to java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsFilter.java
index ed2973a..49ad310 100644
--- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsFilter.java
@@ -29,9 +29,9 @@
  * @author Denis Zhdanov
  * @since 7/18/13 12:40 PM
  */
-public interface CompilerOptionsManager {
+public interface CompilerOptionsFilter {
 
-  ExtensionPointName<CompilerOptionsManager> EP_NAME = ExtensionPointName.create("com.intellij.compiler.optionsManager");
+  ExtensionPointName<CompilerOptionsFilter> EP_NAME = ExtensionPointName.create("com.intellij.compiler.optionsManager");
 
   enum Setting {
     RESOURCE_PATTERNS, CLEAR_OUTPUT_DIR_ON_REBUILD, ADD_NOT_NULL_ASSERTIONS, AUTO_SHOW_FIRST_ERROR_IN_EDITOR,
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java
index 57eb699..38769dc 100644
--- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java
+++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java
@@ -40,7 +40,7 @@
 import java.awt.event.ItemListener;
 import java.util.*;
 
-import static com.intellij.compiler.options.CompilerOptionsManager.*;
+import static com.intellij.compiler.options.CompilerOptionsFilter.*;
 
 public class CompilerUIConfigurable implements SearchableConfigurable, Configurable.NoScroll {
   private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.options.CompilerUIConfigurable");
@@ -110,9 +110,9 @@
   }
 
   private void tweakControls(@NotNull Project project) {
-    CompilerOptionsManager[] managers = CompilerOptionsManager.EP_NAME.getExtensions();
+    CompilerOptionsFilter[] managers = CompilerOptionsFilter.EP_NAME.getExtensions();
     boolean showExternalBuildSetting = true;
-    for (CompilerOptionsManager manager : managers) {
+    for (CompilerOptionsFilter manager : managers) {
       showExternalBuildSetting = manager.isAvailable(Setting.EXTERNAL_BUILD, project);
       if (!showExternalBuildSetting) {
         myDisabledSettings.add(Setting.EXTERNAL_BUILD);
@@ -126,7 +126,7 @@
         myDisabledSettings.add(setting);
       }
       else {
-        for (CompilerOptionsManager manager : managers) {
+        for (CompilerOptionsFilter manager : managers) {
           if (!manager.isAvailable(setting, project)) {
             myDisabledSettings.add(setting);
             break;
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 a15f2de..f981000 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -111,7 +111,7 @@
     if (MAIN_CLASS_NAME == null) {
       return null;
     }
-    return JavaExecutionUtil.getPresentableClassName(MAIN_CLASS_NAME, getConfigurationModule());
+    return JavaExecutionUtil.getPresentableClassName(MAIN_CLASS_NAME);
   }
 
   @Override
diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
index 95a2c2d..0e06157 100644
--- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
+++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -141,12 +141,17 @@
   }
 
   @Nullable
+  public static String getPresentableClassName(final String rtClassName) {
+    return getPresentableClassName(rtClassName, null);
+  }
+
+  /**
+   * {@link JavaExecutionUtil#getPresentableClassName(java.lang.String)} 
+   */
+  @Deprecated
+  @Nullable
   public static String getPresentableClassName(final String rtClassName, final JavaRunConfigurationModule configurationModule) {
     if (StringUtil.isEmpty(rtClassName)) return null;
-    final PsiClass psiClass = configurationModule.findClass(rtClassName);
-    if (psiClass != null) {
-      return psiClass.getName();
-    }
     final int lastDot = rtClassName.lastIndexOf('.');
     if (lastDot == -1 || lastDot == rtClassName.length() - 1) {
       return rtClassName;
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 2ed1ac7..2c6d8d8 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
@@ -30,6 +30,7 @@
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.concurrency.SwingWorker;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
 
 import javax.swing.*;
 import java.awt.*;
@@ -41,12 +42,12 @@
 
 public class JavaContentEntriesEditor extends CommonContentEntriesEditor {
   public JavaContentEntriesEditor(String moduleName, ModuleConfigurationState state) {
-    super(moduleName, state, true, true);
+    super(moduleName, state, JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE);
   }
 
   @Override
   protected ContentEntryEditor createContentEntryEditor(final String contentEntryUrl) {
-    return new JavaContentEntryEditor(contentEntryUrl) {
+    return new JavaContentEntryEditor(contentEntryUrl, getEditHandlers()) {
       @Override
       protected ModifiableRootModel getModel() {
         return JavaContentEntriesEditor.this.getModel();
@@ -55,11 +56,6 @@
   }
 
   @Override
-  protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) {
-    return new ContentEntryTreeEditor(project, true, true);
-  }
-
-  @Override
   protected List<ContentEntry> addContentEntries(VirtualFile[] files) {
     List<ContentEntry> contentEntries = super.addContentEntries(files);
     if (!contentEntries.isEmpty()) {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntryEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntryEditor.java
index 41b8c8d..7d3c535 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntryEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntryEditor.java
@@ -18,28 +18,38 @@
 import com.intellij.openapi.roots.CompilerModuleExtension;
 import com.intellij.openapi.roots.ContentEntry;
 import com.intellij.openapi.roots.ExcludeFolder;
+import com.intellij.openapi.roots.SourceFolder;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
+import java.util.List;
+
 public abstract class JavaContentEntryEditor extends ContentEntryEditor {
   private final CompilerModuleExtension myCompilerExtension;
 
-  public JavaContentEntryEditor(final String contentEntryUrl) {
-    super(contentEntryUrl, true, true);
+  public JavaContentEntryEditor(final String contentEntryUrl, List<ModuleSourceRootEditHandler<?>> moduleSourceRootEditHandlers) {
+    super(contentEntryUrl, moduleSourceRootEditHandlers);
     myCompilerExtension = getModel().getModuleExtension(CompilerModuleExtension.class);
   }
 
   @Override
   protected ContentRootPanel createContentRootPane() {
-    return new JavaContentRootPanel(this) {
+    return new ContentRootPanel(this, getEditHandlers()) {
       @Nullable
       @Override
       protected ContentEntry getContentEntry() {
         return JavaContentEntryEditor.this.getContentEntry();
       }
+
+      @Nullable
+      @Override
+      protected JComponent createRootPropertiesEditor(ModuleSourceRootEditHandler<?> editor, SourceFolder folder) {
+        return editor.createPropertiesEditor(folder, this, myCallback);
+      }
     };
   }
 
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentRootPanel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentRootPanel.java
deleted file mode 100644
index d0af3a1..0000000
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentRootPanel.java
+++ /dev/null
@@ -1,65 +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.openapi.roots.ui.configuration;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.project.ProjectBundle;
-import com.intellij.openapi.roots.ContentFolder;
-import com.intellij.openapi.roots.SourceFolder;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.ui.roots.IconActionComponent;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-
-public abstract class JavaContentRootPanel extends ContentRootPanel {
-
-  public JavaContentRootPanel(ActionCallback callback) {
-    super(callback, true, true);
-  }
-
-  @Override
-  @Nullable
-  protected JComponent createAdditionalComponent(ContentFolder folder) {
-    if (folder instanceof SourceFolder) {
-      return createAddPrefixComponent((SourceFolder)folder);
-    }
-    return null;
-  }
-
-  private JComponent createAddPrefixComponent(final SourceFolder folder) {
-    final IconActionComponent iconComponent = new IconActionComponent(AllIcons.Modules.SetPackagePrefix,
-                                                                      AllIcons.Modules.SetPackagePrefixRollover,
-                                                                      ProjectBundle.message("module.paths.package.prefix.tooltip"), new Runnable() {
-      @Override
-      public void run() {
-        final String message = ProjectBundle.message("module.paths.package.prefix.prompt",
-                                                     toRelativeDisplayPath(folder.getUrl(), getContentEntry().getUrl() + ":"));
-        final String prefix = Messages.showInputDialog(JavaContentRootPanel.this, message,
-                                                       ProjectBundle.message("module.paths.package.prefix.title"), Messages.getQuestionIcon(), folder.getPackagePrefix(), null);
-        if (prefix != null) {
-          myCallback.setPackagePrefix(folder, prefix);
-        }
-      }
-    });
-    final JPanel panel = new JPanel(new BorderLayout());
-    panel.setOpaque(false);
-    panel.add(iconComponent, BorderLayout.CENTER);
-    panel.add(Box.createHorizontalStrut(3), BorderLayout.EAST);
-    return panel;
-  }
-}
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 9c6343a..af34e40 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
@@ -223,8 +223,8 @@
       addArtifactsConfig();
     }
 
-    ProjectStructureConfigurableAdder[] adders = ProjectStructureConfigurableAdder.EP_NAME.getExtensions();
-    for (ProjectStructureConfigurableAdder adder : adders) {
+    ProjectStructureConfigurableContributor[] adders = ProjectStructureConfigurableContributor.EP_NAME.getExtensions();
+    for (ProjectStructureConfigurableContributor adder : adders) {
       for (Configurable configurable : adder.getExtraProjectConfigurables(myProject, myContext)) {
         addConfigurable(configurable, true);
       }
@@ -234,7 +234,7 @@
     addJdkListConfig();
     addGlobalLibrariesConfig();
 
-    for (ProjectStructureConfigurableAdder adder : adders) {
+    for (ProjectStructureConfigurableContributor adder : adders) {
       for (Configurable configurable : adder.getExtraPlatformConfigurables(myProject, myContext)) {
         addConfigurable(configurable, true);
       }
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableAdder.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableContributor.java
similarity index 89%
rename from java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableAdder.java
rename to java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableContributor.java
index 4a79ada..ad68806 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableAdder.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableContributor.java
@@ -24,8 +24,8 @@
 import java.util.Collections;
 import java.util.List;
 
-public abstract class ProjectStructureConfigurableAdder {
-  public static final ExtensionPointName<ProjectStructureConfigurableAdder> EP_NAME = ExtensionPointName.create("com.intellij.projectStructureConfigurableAdder");
+public abstract class ProjectStructureConfigurableContributor {
+  public static final ExtensionPointName<ProjectStructureConfigurableContributor> EP_NAME = ExtensionPointName.create("com.intellij.projectStructureConfigurableAdder");
 
   @NotNull
   public List<? extends Configurable> getExtraProjectConfigurables(@NotNull Project project, @NotNull StructureConfigurableContext context) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java
index daf675a..02a5c57 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
 import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.javadoc.PsiDocTag;
+import com.intellij.psi.util.PsiTreeUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -103,7 +104,12 @@
         final PsiAnnotationMemberValue psiAnnotationMemberValue = pair.getValue();
         if (psiAnnotationMemberValue != null) {
           final String value = psiAnnotationMemberValue.getText();
-          return value.substring(1, value.length() - 1).trim();
+          final String trim = value.substring(1, value.length() - 1).trim();
+          if (trim.equals("itself")) {
+            final PsiMember member = PsiTreeUtil.getParentOfType(annotation, PsiMember.class);
+            if (member != null) return member.getName();
+          }
+          return trim;
         }
       }
     }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
index 9c8cc96..df96d14 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -263,7 +263,7 @@
     }
   }
 
-  private static boolean isExternalizableNoParameterConstructor(PsiMethod method, RefClass refClass) {
+  private static boolean isExternalizableNoParameterConstructor(@NotNull PsiMethod method, RefClass refClass) {
     if (!method.isConstructor()) return false;
     if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return false;
     final PsiParameterList parameterList = method.getParameterList();
@@ -272,7 +272,7 @@
     return aClass == null || isExternalizable(aClass, refClass);
   }
 
-  private static boolean isSerializationImplicitlyUsedField(PsiField field) {
+  private static boolean isSerializationImplicitlyUsedField(@NotNull PsiField field) {
     @NonNls final String name = field.getName();
     if (!HighlightUtilBase.SERIAL_VERSION_UID_FIELD_NAME.equals(name) && !"serialPersistentFields".equals(name)) return false;
     if (!field.hasModifierProperty(PsiModifier.STATIC)) return false;
@@ -280,7 +280,7 @@
     return aClass == null || isSerializable(aClass, null);
   }
 
-  private static boolean isWriteObjectMethod(PsiMethod method, RefClass refClass) {
+  private static boolean isWriteObjectMethod(@NotNull PsiMethod method, RefClass refClass) {
     @NonNls final String name = method.getName();
     if (!"writeObject".equals(name)) return false;
     PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -291,7 +291,7 @@
     return !(aClass != null && !isSerializable(aClass, refClass));
   }
 
-  private static boolean isReadObjectMethod(PsiMethod method, RefClass refClass) {
+  private static boolean isReadObjectMethod(@NotNull PsiMethod method, RefClass refClass) {
     @NonNls final String name = method.getName();
     if (!"readObject".equals(name)) return false;
     PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -302,7 +302,7 @@
     return !(aClass != null && !isSerializable(aClass, refClass));
   }
 
-  private static boolean isWriteReplaceMethod(PsiMethod method, RefClass refClass) {
+  private static boolean isWriteReplaceMethod(@NotNull PsiMethod method, RefClass refClass) {
     @NonNls final String name = method.getName();
     if (!"writeReplace".equals(name)) return false;
     PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -313,7 +313,7 @@
     return !(aClass != null && !isSerializable(aClass, refClass));
   }
 
-  private static boolean isReadResolveMethod(PsiMethod method, RefClass refClass) {
+  private static boolean isReadResolveMethod(@NotNull PsiMethod method, RefClass refClass) {
     @NonNls final String name = method.getName();
     if (!"readResolve".equals(name)) return false;
     PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -329,7 +329,7 @@
     return serializableClass != null && isSerializable(aClass, refClass, serializableClass);
   }
 
-  private static boolean isExternalizable(PsiClass aClass, RefClass refClass) {
+  private static boolean isExternalizable(@NotNull PsiClass aClass, RefClass refClass) {
     final GlobalSearchScope scope = aClass.getResolveScope();
     final PsiClass externalizableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.io.Externalizable", scope);
     return externalizableClass != null && isSerializable(aClass, refClass, externalizableClass);
@@ -537,7 +537,7 @@
             public void visitField(@NotNull final RefField refField) {
               myProcessedSuspicious.add(refField);
               PsiField psiField = refField.getElement();
-              if (isSerializationImplicitlyUsedField(psiField)) {
+              if (psiField != null && isSerializationImplicitlyUsedField(psiField)) {
                 getEntryPointsManager().addEntryPoint(refField, false);
               }
               else {
@@ -560,7 +560,7 @@
               }
               else {
                 PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
-                if (isSerializablePatternMethod(psiMethod, refMethod.getOwnerClass())) {
+                if (psiMethod != null && isSerializablePatternMethod(psiMethod, refMethod.getOwnerClass())) {
                   getEntryPointsManager().addEntryPoint(refMethod, false);
                 }
                 else if (!refMethod.isExternalOverride() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())) {
@@ -614,7 +614,7 @@
     return true;
   }
 
-  private static boolean isSerializablePatternMethod(PsiMethod psiMethod, RefClass refClass) {
+  private static boolean isSerializablePatternMethod(@NotNull PsiMethod psiMethod, RefClass refClass) {
     return isReadObjectMethod(psiMethod, refClass) || isWriteObjectMethod(psiMethod, refClass) || isReadResolveMethod(psiMethod, refClass) ||
            isWriteReplaceMethod(psiMethod, refClass) || isExternalizableNoParameterConstructor(psiMethod, refClass);
   }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java b/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
index 112aee0..e508a77 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -77,7 +77,7 @@
   }
 
   @Nullable
-  private List<ProblemDescriptor> checkCodeBlock(final PsiCodeBlock body, InspectionManager manager, boolean onTheFly) {
+  private List<ProblemDescriptor> checkCodeBlock(final PsiCodeBlock body, final InspectionManager manager, final boolean onTheFly) {
     if (body == null) return null;
     final ControlFlow flow;
     try {
@@ -120,9 +120,17 @@
 
     final List<PsiVariable> writtenVariables = new ArrayList<PsiVariable>(ControlFlowUtil.getWrittenVariables(flow, start, end, false));
 
+    final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
     final HashSet<PsiVariable> ssaVarsSet = new HashSet<PsiVariable>();
     body.accept(new JavaRecursiveElementWalkingVisitor() {
       @Override public void visitCodeBlock(PsiCodeBlock block) {
+        if (block.getParent() instanceof PsiLambdaExpression && block != body) {
+          final List<ProblemDescriptor> descriptors = checkCodeBlock(block, manager, onTheFly);
+          if (descriptors != null) {
+            problems.addAll(descriptors);
+          }
+          return;
+        }
         super.visitCodeBlock(block);
         PsiElement anchor = block;
         if (block.getParent() instanceof PsiSwitchStatement) {
@@ -177,7 +185,7 @@
       }
     });
 
-    ArrayList<PsiVariable> result = new ArrayList<PsiVariable>(ssaVarsSet);
+    final ArrayList<PsiVariable> result = new ArrayList<PsiVariable>(ssaVarsSet);
 
     if (body.getParent() instanceof PsiMethod) {
       PsiMethod method = (PsiMethod)body.getParent();
@@ -215,7 +223,7 @@
         iterator.remove();
       }
     }
-    List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>(result.size());
+
     for (PsiVariable variable : result) {
       final PsiIdentifier nameIdenitier = variable.getNameIdentifier();
       PsiElement problemElement = nameIdenitier != null ? nameIdenitier : variable;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
index 8efcc45..3d45887 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
@@ -21,7 +21,7 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -40,7 +40,7 @@
     // does not work in tests since CodeInsightTestCase copies file into temporary location
     if (ApplicationManager.getApplication().isUnitTestMode()) return null;
     if (file instanceof PsiJavaFile) {
-      if (isInJsp(file)) return null;
+      if (FileTypeUtils.isInServerPageFile(file)) return null;
       PsiJavaFile javaFile = (PsiJavaFile)file;
 
       PsiDirectory directory = javaFile.getContainingDirectory();
@@ -86,10 +86,6 @@
     return null;
   }
 
-  private static boolean isInJsp(PsiFile file) {
-    return PsiUtilCore.getTemplateLanguageFile(file) instanceof ServerPageFile;
-  }
-
   protected void addMoveToPackageFix(PsiFile file, String packName, List<LocalQuickFix> availableFixes) {
   }
 
diff --git a/java/java-impl/src/com/intellij/analysis/JavaAnalysisScope.java b/java/java-impl/src/com/intellij/analysis/JavaAnalysisScope.java
index 6899c7a..1c49c3b 100644
--- a/java/java-impl/src/com/intellij/analysis/JavaAnalysisScope.java
+++ b/java/java-impl/src/com/intellij/analysis/JavaAnalysisScope.java
@@ -31,7 +31,7 @@
 import com.intellij.psi.search.PackageScope;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.util.containers.ContainerUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.HashSet;
diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java
index fe002f6..9f2b486 100644
--- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java
@@ -43,7 +43,7 @@
 import com.intellij.util.FilteredQuery;
 import com.intellij.util.Processor;
 import com.intellij.util.Query;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
index 3ce6050..26b9fdb 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -589,6 +589,11 @@
     return LangBundle.message("completion.no.suggestions") + suffix;
   }
 
+  @Override
+  public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar) {
+    return typeChar == ':' && JavaTokenType.COLON == position.getNode().getElementType();
+  }
+
   private static boolean shouldSuggestSmartCompletion(final PsiElement element) {
     if (shouldSuggestClassNameCompletion(element)) return false;
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
index 9710f75..ac752ed 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
 import com.intellij.codeInsight.lookup.*;
 import com.intellij.openapi.util.Key;
 import com.intellij.patterns.ElementPattern;
+import com.intellij.patterns.ElementPatternCondition;
 import com.intellij.patterns.PsiElementPattern;
 import com.intellij.patterns.PsiJavaPatterns;
 import com.intellij.psi.*;
@@ -28,6 +29,7 @@
 import com.intellij.psi.filters.GeneratorFilter;
 import com.intellij.psi.filters.OrFilter;
 import com.intellij.psi.filters.getters.*;
+import com.intellij.psi.filters.position.FilterPattern;
 import com.intellij.psi.filters.types.AssignableFromFilter;
 import com.intellij.psi.filters.types.AssignableGroupFilter;
 import com.intellij.psi.filters.types.AssignableToFilter;
@@ -92,6 +94,21 @@
       psiElement().withText(")").withParent(PsiTypeCastExpression.class)));
   static final PsiElementPattern.Capture<PsiElement> IN_TYPE_ARGS =
     psiElement().inside(psiElement(PsiReferenceParameterList.class));
+  static final PsiElementPattern.Capture<PsiElement> LAMBDA = psiElement().and(new FilterPattern(new ElementFilter() {
+    @Override
+    public boolean isAcceptable(Object element, @Nullable PsiElement context) {
+      if (context == null) return false;
+      final PsiElement originalElement = context.getOriginalElement();
+      if (originalElement == null) return false;
+      final PsiElement rulezzRef = originalElement.getParent();
+      return LambdaUtil.isValidLambdaContext(rulezzRef.getParent());
+    }
+
+    @Override
+    public boolean isClassAcceptable(Class hintClass) {
+      return true;
+    }
+  }));
 
   @Nullable
   private static ElementFilter getReferenceFilter(PsiElement element) {
@@ -313,6 +330,8 @@
         }
       }
     });
+
+    extend(CompletionType.SMART, LAMBDA, new LambdaCompletionProvider());
   }
 
   private static void addExpectedTypeMembers(CompletionParameters params,
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java
new file mode 100644
index 0000000..eca5453
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java
@@ -0,0 +1,67 @@
+/*
+ * 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.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.ExpectedTypeInfo;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Function;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: anna
+ */
+public class LambdaCompletionProvider extends CompletionProvider<CompletionParameters> {
+  @Override
+  protected void addCompletions(@NotNull CompletionParameters parameters,
+                                ProcessingContext context,
+                                @NotNull CompletionResultSet result) {
+    if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return;
+    final ExpectedTypeInfo[] expectedTypes = JavaSmartCompletionContributor.getExpectedTypes(parameters);
+    for (ExpectedTypeInfo expectedType : expectedTypes) {
+      final PsiType defaultType = expectedType.getDefaultType();
+      if (LambdaHighlightingUtil.checkInterfaceFunctional(defaultType) == null) {
+        final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(defaultType);
+        if (method != null) {
+          final PsiParameter[] params = method.getParameterList().getParameters();
+          final String paramsString = "(" + StringUtil.join(params, new Function<PsiParameter, String>() {
+            @Override
+            public String fun(PsiParameter parameter) {
+              return parameter.getName();
+            }
+          }, ",") + ")";
+          final LookupElementBuilder builder =
+            LookupElementBuilder.create(paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler<LookupElement>() {
+              @Override
+              public void handleInsert(InsertionContext context, LookupElement item) {
+                final Editor editor = context.getEditor();
+                EditorModificationUtil.insertStringAtCaret(editor, " -> ");
+                PsiDocumentManager.getInstance(context.getProject()).commitDocument(editor.getDocument());
+              }
+            });
+          result.addElement(builder.withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE));
+        }
+      }
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index c32a30c..7cc7879 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -32,7 +32,7 @@
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Processor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 612d4704..3266e96 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -915,7 +915,7 @@
     if (!hasNoBody) {
       QuickFixAction.registerQuickFixAction(info, new DeleteMethodBodyFix(method));
     }
-    if (method.hasModifierProperty(PsiModifier.ABSTRACT) && isInterface) {
+    if (method.hasModifierProperty(PsiModifier.ABSTRACT) && !isInterface) {
       QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.ABSTRACT, false, false));
     }
     for (IntentionAction intentionAction : additionalFixes) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 5657a40..a3fb892 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -61,7 +61,7 @@
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.xml.util.XmlStringUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import gnu.trove.THashMap;
 import org.intellij.lang.annotations.Language;
 import org.jetbrains.annotations.NonNls;
@@ -808,7 +808,8 @@
         }
         else if (PsiModifier.STATIC.equals(modifier) || PsiModifier.PRIVATE.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) ||
                  PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
-          isAllowed = modifierOwnerParent instanceof PsiClass && ((PsiClass)modifierOwnerParent).getQualifiedName() != null;
+          isAllowed = modifierOwnerParent instanceof PsiClass &&
+                      ((PsiClass)modifierOwnerParent).getQualifiedName() != null || FileTypeUtils.isInServerPageFile(modifierOwnerParent);
         }
 
         if (aClass.isEnum()) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 5c9e198..40e2eaa 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -29,7 +29,7 @@
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
+import com.intellij.openapi.projectRoots.JavaVersionService;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.pom.java.LanguageLevel;
@@ -147,7 +147,7 @@
     boolean success = true;
     try {
       myLanguageLevel = PsiUtil.getLanguageLevel(file);
-      myJavaSdkVersion = ObjectUtils.notNull(JavaSdkVersionUtil.getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
+      myJavaSdkVersion = ObjectUtils.notNull(JavaVersionService.getInstance().getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
       if (updateWholeFile) {
         Project project = file.getProject();
         DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddNewArrayExpressionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddNewArrayExpressionFix.java
index 13921e9..d564d3a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddNewArrayExpressionFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddNewArrayExpressionFix.java
@@ -32,7 +32,7 @@
 public class AddNewArrayExpressionFix implements IntentionAction {
   private final PsiArrayInitializerExpression myInitializer;
 
-  public AddNewArrayExpressionFix(PsiArrayInitializerExpression initializer) {
+  public AddNewArrayExpressionFix(@NotNull PsiArrayInitializerExpression initializer) {
     myInitializer = initializer;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
index 67952e1..b9c5d21 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
@@ -40,7 +40,7 @@
 public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement {
   private final PsiType myType;
 
-  public AddTypeCastFix(PsiType type, PsiExpression expression) {
+  public AddTypeCastFix(@NotNull PsiType type, @NotNull PsiExpression expression) {
     super(expression);
     myType = type;
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java
index 0683af7..513cb78 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java
@@ -36,7 +36,7 @@
   private final PsiType myLhsType;
   private final PsiAssignmentExpression myAssignmentExpression;
 
-  public ChangeToAppendFix(IElementType eqOpSign, PsiType lType, PsiAssignmentExpression assignmentExpression) {
+  public ChangeToAppendFix(@NotNull IElementType eqOpSign, @NotNull PsiType lType, @NotNull PsiAssignmentExpression assignmentExpression) {
     myTokenType = eqOpSign;
     myLhsType = lType;
     myAssignmentExpression = assignmentExpression;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java
index a996525..dab9a3b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java
@@ -40,7 +40,7 @@
 public class ConvertSwitchToIfIntention implements IntentionAction {
   private final PsiSwitchStatement mySwitchExpression;
 
-  public ConvertSwitchToIfIntention(PsiSwitchStatement switchStatement) {
+  public ConvertSwitchToIfIntention(@NotNull PsiSwitchStatement switchStatement) {
     mySwitchExpression = switchStatement;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java
index 139a605..939b8b6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java
@@ -32,8 +32,7 @@
  * @author Mike
  */
 public class CreateFieldFromUsageFix extends CreateVarFromUsageFix {
-
-  public CreateFieldFromUsageFix(PsiReferenceExpression referenceElement) {
+  public CreateFieldFromUsageFix(@NotNull PsiReferenceExpression referenceElement) {
     super(referenceElement);
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java
index 35d25d8..ec6e0c3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteCatchFix.java
@@ -27,7 +27,7 @@
 public class DeleteCatchFix implements IntentionAction {
   private final PsiParameter myCatchParameter;
 
-  public DeleteCatchFix(PsiParameter myCatchParameter) {
+  public DeleteCatchFix(@NotNull PsiParameter myCatchParameter) {
     this.myCatchParameter = myCatchParameter;
   }
 
@@ -45,9 +45,7 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    return myCatchParameter != null
-           && myCatchParameter.isValid()
-           && PsiManager.getInstance(project).isInProject(myCatchParameter.getContainingFile());
+    return myCatchParameter.isValid() && PsiManager.getInstance(project).isInProject(myCatchParameter.getContainingFile());
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteMultiCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteMultiCatchFix.java
index 41e08d6..c85e613 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteMultiCatchFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteMultiCatchFix.java
@@ -32,7 +32,7 @@
 public class DeleteMultiCatchFix implements IntentionAction {
   private final PsiTypeElement myTypeElement;
 
-  public DeleteMultiCatchFix(final PsiTypeElement typeElement) {
+  public DeleteMultiCatchFix(@NotNull PsiTypeElement typeElement) {
     myTypeElement = typeElement;
   }
 
@@ -50,9 +50,7 @@
 
   @Override
   public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
-    return myTypeElement != null &&
-           myTypeElement.isValid() &&
-           PsiManager.getInstance(project).isInProject(myTypeElement.getContainingFile());
+    return myTypeElement.isValid() && PsiManager.getInstance(project).isInProject(myTypeElement.getContainingFile());
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java
index b0c9790..64ad438 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java
@@ -32,7 +32,7 @@
   private PsiTryStatement myTryStatement;
   private PsiParameter myCatchParameter;
 
-  public GeneralizeCatchFix(PsiElement element, PsiClassType unhandledException) {
+  public GeneralizeCatchFix(@NotNull PsiElement element, @NotNull PsiClassType unhandledException) {
     myElement = element;
     myUnhandledException = unhandledException;
   }
@@ -53,9 +53,7 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    if (!(myElement != null
-          && myElement.isValid()
-          && myUnhandledException != null
+    if (!(myElement.isValid()
           && myUnhandledException.isValid()
           && myElement.getManager().isInProject(myElement))) return false;
     // find enclosing try
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index 1a2683e..abc31adf 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -41,12 +41,12 @@
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.psi.util.FileTypeUtils;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
-import com.siyeh.ig.psiutils.FileTypeUtils;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java
index 48fae89..4110c91 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveCatchUpFix.java
@@ -35,10 +35,10 @@
   private final PsiCatchSection myCatchSection;
   private final PsiCatchSection myMoveBeforeSection;
 
-    public MoveCatchUpFix(PsiCatchSection catchSection, PsiCatchSection moveBeforeSection) {
+  public MoveCatchUpFix(@NotNull PsiCatchSection catchSection, @NotNull PsiCatchSection moveBeforeSection) {
     this.myCatchSection = catchSection;
-        myMoveBeforeSection = moveBeforeSection;
-    }
+    myMoveBeforeSection = moveBeforeSection;
+  }
 
   @Override
   @NotNull
@@ -56,10 +56,8 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    return myCatchSection != null
-           && myCatchSection.isValid()
+    return myCatchSection.isValid()
            && myCatchSection.getManager().isInProject(myCatchSection)
-           && myMoveBeforeSection != null
            && myMoveBeforeSection.isValid()
            && myCatchSection.getCatchType() != null
            && PsiUtil.resolveClassInType(myCatchSection.getCatchType()) != null
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java
index dcbdd44..b628b9f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/NegationBroadScopeFix.java
@@ -33,7 +33,7 @@
 public class NegationBroadScopeFix implements IntentionAction {
   private final PsiPrefixExpression myPrefixExpression;
 
-  public NegationBroadScopeFix(PsiPrefixExpression prefixExpression) {
+  public NegationBroadScopeFix(@NotNull PsiPrefixExpression prefixExpression) {
     myPrefixExpression = prefixExpression;
   }
 
@@ -70,7 +70,7 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    if (myPrefixExpression == null || !myPrefixExpression.isValid()) return false;
+    if (!myPrefixExpression.isValid()) return false;
 
     PsiElement parent = myPrefixExpression.getParent();
     if (parent instanceof PsiInstanceOfExpression && ((PsiInstanceOfExpression)parent).getOperand() == myPrefixExpression) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveParameterListFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveParameterListFix.java
index 3fdf639..19f5359 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveParameterListFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveParameterListFix.java
@@ -29,7 +29,7 @@
 
   private final PsiMethod myMethod;
 
-  public RemoveParameterListFix(PsiMethod method) {
+  public RemoveParameterListFix(@NotNull PsiMethod method) {
     myMethod = method;
   }
 
@@ -47,7 +47,7 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    return myMethod != null && myMethod.isValid();
+    return myMethod.isValid();
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveQualifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveQualifierFix.java
index 063f1b7..35a053e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveQualifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveQualifierFix.java
@@ -35,7 +35,7 @@
   private final PsiReferenceExpression myExpression;
   private final PsiClass myResolved;
 
-  public RemoveQualifierFix(final PsiExpression qualifier, final PsiReferenceExpression expression, final PsiClass resolved) {
+  public RemoveQualifierFix(@NotNull PsiExpression qualifier, @NotNull PsiReferenceExpression expression, @NotNull PsiClass resolved) {
     myQualifier = qualifier;
     myExpression = expression;
     myResolved = resolved;
@@ -56,14 +56,10 @@
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
     return
-      myQualifier != null
-      && myQualifier.isValid()
+      myQualifier.isValid()
       && myQualifier.getManager().isInProject(myQualifier)
-      && myExpression != null
       && myExpression.isValid()
-      && myResolved != null
-      && myResolved.isValid()
-      ;
+      && myResolved.isValid();
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameWrongRefFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameWrongRefFix.java
index 42d42a4..6dc619d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameWrongRefFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameWrongRefFix.java
@@ -49,11 +49,11 @@
   @NonNls private static final String OTHER_VARIABLE_NAME = "OTHERVAR";
   private final boolean myUnresolvedOnly;
 
-  public RenameWrongRefFix(PsiReferenceExpression refExpr) {
+  public RenameWrongRefFix(@NotNull PsiReferenceExpression refExpr) {
     this(refExpr, false);
   }
 
-  public RenameWrongRefFix(PsiReferenceExpression refExpr, final boolean unresolvedOnly) {
+  public RenameWrongRefFix(@NotNull PsiReferenceExpression refExpr, final boolean unresolvedOnly) {
     myRefExpr = refExpr;
     myUnresolvedOnly = unresolvedOnly;
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceWithListAccessFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceWithListAccessFix.java
index 59d6f70..7e8161e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceWithListAccessFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceWithListAccessFix.java
@@ -33,7 +33,7 @@
 public class ReplaceWithListAccessFix implements IntentionAction {
   private final PsiArrayAccessExpression myArrayAccessExpression;
 
-  public ReplaceWithListAccessFix(PsiArrayAccessExpression arrayAccessExpression) {
+  public ReplaceWithListAccessFix(@NotNull PsiArrayAccessExpression arrayAccessExpression) {
     myArrayAccessExpression = arrayAccessExpression;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java
index 78c0275..bc1aafd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReuseVariableDeclarationFix.java
@@ -36,7 +36,7 @@
 public class ReuseVariableDeclarationFix implements IntentionAction {
   private final PsiLocalVariable myVariable;
 
-  public ReuseVariableDeclarationFix(final PsiLocalVariable variable) {
+  public ReuseVariableDeclarationFix(@NotNull PsiLocalVariable variable) {
     this.myVariable = variable;
   }
 
@@ -54,7 +54,7 @@
 
   @Override
   public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
-    if (myVariable == null || !myVariable.isValid()) {
+    if (!myVariable.isValid()) {
       return false;
     }
     final PsiVariable previousVariable = findPreviousVariable();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ShowModulePropertiesFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ShowModulePropertiesFix.java
index 1912230..203612e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ShowModulePropertiesFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ShowModulePropertiesFix.java
@@ -21,7 +21,6 @@
 import com.intellij.openapi.actionSystem.IdeActions;
 import com.intellij.openapi.editor.Editor;
 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.ui.configuration.ProjectSettingsService;
@@ -33,13 +32,9 @@
 public class ShowModulePropertiesFix implements IntentionAction {
   private final String myModuleName;
 
-  public ShowModulePropertiesFix(String moduleName) {
-    myModuleName = moduleName;
-  }
-
-  public ShowModulePropertiesFix(PsiElement context) {
+  public ShowModulePropertiesFix(@NotNull PsiElement context) {
     Module module = ModuleUtilCore.findModuleForPsiElement(context);
-    myModuleName = module != null ? module.getName() : null;
+    myModuleName = module == null ? null : module.getName();
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SurroundWithTryCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SurroundWithTryCatchFix.java
index 1e91f9d..d617c8d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SurroundWithTryCatchFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SurroundWithTryCatchFix.java
@@ -40,7 +40,7 @@
 
   private PsiStatement myStatement = null;
 
-  public SurroundWithTryCatchFix(PsiElement element) {
+  public SurroundWithTryCatchFix(@NotNull PsiElement element) {
     final PsiMethodReferenceExpression methodReferenceExpression = PsiTreeUtil.getParentOfType(element, PsiMethodReferenceExpression.class, false);
     if (methodReferenceExpression == null) {
       final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
index a8b3b28..60ba678 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
@@ -20,7 +20,7 @@
 import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
+import com.intellij.openapi.projectRoots.JavaVersionService;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
@@ -40,7 +40,7 @@
     PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject());
     PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(manager.getProject()));
     PsiElementFactory factory = facade.getElementFactory();
-    JavaSdkVersion version = JavaSdkVersionUtil.getJavaSdkVersion(parameterList);
+    JavaSdkVersion version = JavaVersionService.getInstance().getJavaSdkVersion(parameterList);
     for (PsiClass aClass : classes) {
       if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) {
         PsiType[] actualTypeParameters = parameterList.getTypeArguments();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
index 38fd5a9..bcfd4d0 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
@@ -24,7 +24,7 @@
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 
 class JavaWithIfExpressionSurrounder extends JavaExpressionSurrounder{
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNullCheckSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNullCheckSurrounder.java
index c6a1221..a5e3f48 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNullCheckSurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNullCheckSurrounder.java
@@ -24,7 +24,7 @@
 import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 
 class JavaWithNullCheckSurrounder extends JavaExpressionSurrounder{
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/AbstractGenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/AbstractGenerateEqualsWizard.java
new file mode 100644
index 0000000..12e6903
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/AbstractGenerateEqualsWizard.java
@@ -0,0 +1,200 @@
+package com.intellij.codeInsight.generation.ui;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.ide.wizard.AbstractWizard;
+import com.intellij.ide.wizard.Step;
+import com.intellij.ide.wizard.StepAdapter;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.classMembers.MemberInfoBase;
+import com.intellij.refactoring.ui.AbstractMemberSelectionPanel;
+import com.intellij.util.containers.HashMap;
+
+import javax.swing.*;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import java.awt.*;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Nikolay.Tropin
+ * 8/20/13
+ */
+public abstract class AbstractGenerateEqualsWizard <C extends PsiElement, M extends PsiElement, I extends MemberInfoBase<M>> 
+  extends AbstractWizard<Step> {
+  
+  protected final C myClass;
+
+  protected final AbstractMemberSelectionPanel<M, I> myEqualsPanel;
+  protected final AbstractMemberSelectionPanel<M, I> myHashCodePanel;
+  protected final AbstractMemberSelectionPanel<M, I> myNonNullPanel;
+  protected final HashMap<M, I> myFieldsToHashCode;
+  protected final HashMap<M, I> myFieldsToNonNull;
+
+  private int myNonNullStepCode;
+  private int myEqualsStepCode;
+  private int myHashCodeStepCode;
+
+  protected int getHashCodeStepCode() {
+    return myHashCodeStepCode;
+  }
+
+  protected int getEqualsStepCode() {
+    return myEqualsStepCode;
+  }
+
+  protected int getNonNullStepCode() {
+    return myNonNullStepCode;
+  }
+
+  protected final List<I> myClassFields;
+
+  protected final Builder<C, M, I> myBuilder;
+
+  public static abstract class Builder<C extends PsiElement, M extends PsiElement, I extends MemberInfoBase<M>> {
+    protected abstract C getPsiClass();
+    protected abstract List<I> getClassFields();
+    protected abstract HashMap<M, I> getFieldsToHashCode();
+    protected abstract HashMap<M, I> getFieldsToNonNull();
+    protected abstract AbstractMemberSelectionPanel<M, I> getEqualsPanel();
+    protected abstract AbstractMemberSelectionPanel<M, I> getHashCodePanel();
+    protected abstract AbstractMemberSelectionPanel<M, I> getNonNullPanel();
+    protected abstract void updateHashCodeMemberInfos(Collection<I> equalsMemberInfos);
+    protected abstract void updateNonNullMemberInfos(Collection<I> equalsMemberInfos);
+  }
+
+  public AbstractGenerateEqualsWizard(Project project, Builder<C, M, I> builder) {
+    super(CodeInsightBundle.message("generate.equals.hashcode.wizard.title"), project);
+    myBuilder = builder;
+    myClass = builder.getPsiClass();
+    myClassFields = builder.getClassFields();
+    myFieldsToHashCode = builder.getFieldsToHashCode();
+    myFieldsToNonNull = builder.getFieldsToNonNull();
+    myEqualsPanel = builder.getEqualsPanel();
+    myHashCodePanel = builder.getHashCodePanel();
+    myNonNullPanel = builder.getNonNullPanel();
+
+    addTableListeners();
+    addSteps();
+    init();
+    updateButtons();
+  }
+
+  protected void addSteps() {
+    myEqualsStepCode = addStepForPanel(myEqualsPanel);
+    myHashCodeStepCode = addStepForPanel(myHashCodePanel);
+    myNonNullStepCode = addStepForPanel(myNonNullPanel);
+  }
+
+  protected int addStepForPanel(AbstractMemberSelectionPanel<M, I> panel) {
+    if (panel != null) {
+      addStep(new MyStep(panel));
+      return getStepCount() - 1;
+    } else {
+      return -1;
+    }
+  }
+
+  protected void addTableListeners() {
+    final MyTableModelListener listener = new MyTableModelListener();
+    if (myEqualsPanel != null) myEqualsPanel.getTable().getModel().addTableModelListener(listener);
+    if (myHashCodePanel != null) myHashCodePanel.getTable().getModel().addTableModelListener(listener);
+  }
+
+  @Override
+  protected void doNextAction() {
+    if (getCurrentStep() == getEqualsStepCode() && myEqualsPanel != null) {
+      equalsFieldsSelected();
+    }
+    else if (getCurrentStep() == getHashCodeStepCode() && myHashCodePanel != null) {
+      Collection<I> selectedMemberInfos = myEqualsPanel != null ? myEqualsPanel.getTable().getSelectedMemberInfos()
+                                                                : myHashCodePanel.getTable().getSelectedMemberInfos();
+      updateNonNullMemberInfos(selectedMemberInfos);
+    }
+
+    super.doNextAction();
+    updateButtons();
+  }
+
+  @Override
+  protected String getHelpID() {
+    return "editing.altInsert.equals";
+  }
+
+  private void equalsFieldsSelected() {
+    Collection<I> selectedMemberInfos = myEqualsPanel.getTable().getSelectedMemberInfos();
+    updateHashCodeMemberInfos(selectedMemberInfos);
+    updateNonNullMemberInfos(selectedMemberInfos);
+  }
+
+  @Override
+  protected void doOKAction() {
+    if (myEqualsPanel != null) {
+      equalsFieldsSelected();
+    }
+    super.doOKAction();
+  }
+
+  protected void updateHashCodeMemberInfos(Collection<I> equalsMemberInfos) {
+    myBuilder.updateHashCodeMemberInfos(equalsMemberInfos);
+  }
+
+  protected void updateNonNullMemberInfos(Collection<I> equalsMemberInfos) {
+    myBuilder.updateNonNullMemberInfos(equalsMemberInfos);
+  }
+
+  @Override
+  protected boolean canGoNext() {
+    if (getCurrentStep() == myEqualsStepCode) {
+      for (I classField : myClassFields) {
+        if (classField.isChecked()) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    final Component stepComponent = getCurrentStepComponent();
+    if (stepComponent instanceof AbstractMemberSelectionPanel) {
+      return ((AbstractMemberSelectionPanel)stepComponent).getTable();
+    }
+    else {
+      return null;
+    }
+  }
+
+  private class MyTableModelListener implements TableModelListener {
+    public void tableChanged(TableModelEvent modelEvent) {
+      updateButtons();
+    }
+  }
+
+  private static class MyStep extends StepAdapter {
+    final AbstractMemberSelectionPanel myPanel;
+
+    public MyStep(AbstractMemberSelectionPanel panel) {
+      myPanel = panel;
+    }
+
+    @Override
+    public Icon getIcon() {
+      return null;
+    }
+
+    @Override
+    public JComponent getComponent() {
+      return myPanel;
+    }
+
+    @Override
+    public JComponent getPreferredFocusedComponent() {
+      return myPanel.getTable();
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
index bd7203f..d76caed 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
@@ -18,16 +18,15 @@
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.CodeInsightSettings;
 import com.intellij.codeInsight.generation.GenerateEqualsHelper;
-import com.intellij.ide.wizard.AbstractWizard;
 import com.intellij.ide.wizard.StepAdapter;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.VerticalFlowLayout;
 import com.intellij.psi.*;
+import com.intellij.refactoring.classMembers.AbstractMemberInfoModel;
 import com.intellij.refactoring.classMembers.MemberInfoBase;
-import com.intellij.refactoring.classMembers.MemberInfoChange;
-import com.intellij.refactoring.classMembers.MemberInfoModel;
 import com.intellij.refactoring.classMembers.MemberInfoTooltipManager;
+import com.intellij.refactoring.ui.AbstractMemberSelectionPanel;
 import com.intellij.refactoring.ui.MemberSelectionPanel;
 import com.intellij.refactoring.util.classMembers.MemberInfo;
 import com.intellij.ui.NonFocusableCheckBox;
@@ -36,108 +35,144 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
-import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.*;
-import java.util.List;
 
 /**
  * @author dsl
  */
-public class GenerateEqualsWizard extends AbstractWizard {
+public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass, PsiMember, MemberInfo> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.ui.GenerateEqualsWizard");
-  private final PsiClass myClass;
 
-  private final MemberSelectionPanel myEqualsPanel;
-  private final MemberSelectionPanel myHashCodePanel;
-  private final HashMap myFieldsToHashCode;
-  private final MemberSelectionPanel myNonNullPanel;
-  private final HashMap<PsiElement, MemberInfo> myFieldsToNonNull;
-
-  private final int myTestBoxedStep;
-  private final int myEqualsStepCode;
-  private final int myHashcodeStepCode;
-
-  private final List<MemberInfo> myClassFields;
   private static final MyMemberInfoFilter MEMBER_INFO_FILTER = new MyMemberInfoFilter();
 
+  public static class JavaGenerateEqualsWizardBuilder extends AbstractGenerateEqualsWizard.Builder<PsiClass, PsiMember, MemberInfo> {
+    private final PsiClass myClass;
 
-  public GenerateEqualsWizard(Project project, PsiClass aClass, boolean needEquals, boolean needHashCode) {
-    super(CodeInsightBundle.message("generate.equals.hashcode.wizard.title"), project);
-    LOG.assertTrue(needEquals || needHashCode);
-    myClass = aClass;
+    private final MemberSelectionPanel myEqualsPanel;
+    private final MemberSelectionPanel myHashCodePanel;
+    private final MemberSelectionPanel myNonNullPanel;
+    private final HashMap<PsiMember, MemberInfo> myFieldsToHashCode;
+    private final HashMap<PsiMember, MemberInfo> myFieldsToNonNull;
+    private final List<MemberInfo> myClassFields;
 
-    myClassFields = MemberInfo.extractClassMembers(myClass, MEMBER_INFO_FILTER, false);
-    for (MemberInfo myClassField : myClassFields) {
-      myClassField.setChecked(true);
-    }
-    int testBoxedStep = 0;
-    if (needEquals) {
-      myEqualsPanel =
-        new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.equals.fields.chooser.title"), myClassFields, null);
-      myEqualsPanel.getTable().setMemberInfoModel(new EqualsMemberInfoModel());
-      testBoxedStep+=2;
-    }
-    else {
-      myEqualsPanel = null;
-    }
-    if (needHashCode) {
-      final List<MemberInfo> hashCodeMemberInfos;
+    private JavaGenerateEqualsWizardBuilder(PsiClass aClass, boolean needEquals, boolean needHashCode) {
+      LOG.assertTrue(needEquals || needHashCode);
+      myClass = aClass;
+      myClassFields = MemberInfo.extractClassMembers(myClass, MEMBER_INFO_FILTER, false);
+      for (MemberInfo myClassField : myClassFields) {
+        myClassField.setChecked(true);
+      }
       if (needEquals) {
-        myFieldsToHashCode = createFieldToMemberInfoMap(true);
-        hashCodeMemberInfos = Collections.emptyList();
+        myEqualsPanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.equals.fields.chooser.title"),
+                                                 myClassFields, null);
+        myEqualsPanel.getTable().setMemberInfoModel(new EqualsMemberInfoModel());
       }
       else {
-        hashCodeMemberInfos = myClassFields;
+        myEqualsPanel = null;
+      }
+      if (needHashCode) {
+        final List<MemberInfo> hashCodeMemberInfos;
+        if (needEquals) {
+          myFieldsToHashCode = createFieldToMemberInfoMap(true);
+          hashCodeMemberInfos = Collections.emptyList();
+        }
+        else {
+          hashCodeMemberInfos = myClassFields;
+          myFieldsToHashCode = null;
+        }
+        myHashCodePanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.hashcode.fields.chooser.title"), hashCodeMemberInfos, null);
+        myHashCodePanel.getTable().setMemberInfoModel(new HashCodeMemberInfoModel());
+        if (needEquals) {
+          updateHashCodeMemberInfos(myClassFields);
+        }
+      }
+      else {
+        myHashCodePanel = null;
         myFieldsToHashCode = null;
       }
-      myHashCodePanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.hashcode.fields.chooser.title"),
-                                                 hashCodeMemberInfos, null);
-      myHashCodePanel.getTable().setMemberInfoModel(new HashCodeMemberInfoModel());
-      if (needEquals) {
-        updateHashCodeMemberInfos(myClassFields);
+      myNonNullPanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.non.null.fields.chooser.title"), Collections.<MemberInfo>emptyList(), null);
+      myFieldsToNonNull = createFieldToMemberInfoMap(false);
+      for (final Map.Entry<PsiMember, MemberInfo> entry : myFieldsToNonNull.entrySet()) {
+        entry.getValue().setChecked(entry.getKey().getModifierList().findAnnotation(NotNull.class.getName()) != null);
       }
-      testBoxedStep++;
-    }
-    else {
-      myHashCodePanel = null;
-      myFieldsToHashCode = null;
-    }
-    myTestBoxedStep=testBoxedStep;
-    myNonNullPanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.non.null.fields.chooser.title"),
-                                              Collections.<MemberInfo>emptyList(), null);
-    myFieldsToNonNull = createFieldToMemberInfoMap(false);
-    for (final Map.Entry<PsiElement, MemberInfo> entry : myFieldsToNonNull.entrySet()) {
-      entry.getValue().setChecked(((PsiField)entry.getKey()).getModifierList().findAnnotation(NotNull.class.getName()) != null);
     }
 
-    final MyTableModelListener listener = new MyTableModelListener();
-    if (myEqualsPanel != null) {
-      myEqualsPanel.getTable().getModel().addTableModelListener(listener);
-      addStep(new InstanceofOptionStep());
-      addStep(new MyStep(myEqualsPanel));
-      myEqualsStepCode = 1;
-    }
-    else {
-      myEqualsStepCode = -1;
+    @Override
+    protected List<MemberInfo> getClassFields() {
+      return myClassFields;
     }
 
-    if (myHashCodePanel != null) {
-      myHashCodePanel.getTable().getModel().addTableModelListener(listener);
-      addStep(new MyStep(myHashCodePanel));
-      myHashcodeStepCode = myEqualsStepCode > 0 ? myEqualsStepCode + 1 : 0;
-    }
-    else {
-      myHashcodeStepCode = -1;
+    @Override
+    protected HashMap<PsiMember, MemberInfo> getFieldsToHashCode() {
+      return myFieldsToHashCode;
     }
 
-    addStep(new MyStep(myNonNullPanel));
+    @Override
+    protected HashMap<PsiMember, MemberInfo> getFieldsToNonNull() {
+      return myFieldsToNonNull;
+    }
 
-    init();
-    updateButtons();
+    @Override
+    protected AbstractMemberSelectionPanel<PsiMember, MemberInfo> getEqualsPanel() {
+      return myEqualsPanel;
+    }
+
+    @Override
+    protected AbstractMemberSelectionPanel<PsiMember, MemberInfo> getHashCodePanel() {
+      return myHashCodePanel;
+    }
+
+    @Override
+    protected AbstractMemberSelectionPanel<PsiMember, MemberInfo> getNonNullPanel() {
+      return myNonNullPanel;
+    }
+
+    @Override
+    protected PsiClass getPsiClass() {
+      return myClass;
+    }
+
+    @Override
+    protected void updateHashCodeMemberInfos(Collection<MemberInfo> equalsMemberInfos) {
+      if (myHashCodePanel == null) return;
+      List<MemberInfo> hashCodeFields = new ArrayList<MemberInfo>();
+
+      for (MemberInfo equalsMemberInfo : equalsMemberInfos) {
+        hashCodeFields.add(myFieldsToHashCode.get(equalsMemberInfo.getMember()));
+      }
+
+      myHashCodePanel.getTable().setMemberInfos(hashCodeFields);
+    }
+
+    @Override
+    protected void updateNonNullMemberInfos(Collection<MemberInfo> equalsMemberInfos) {
+      final ArrayList<MemberInfo> list = new ArrayList<MemberInfo>();
+
+      for (MemberInfo equalsMemberInfo : equalsMemberInfos) {
+        PsiField field = (PsiField)equalsMemberInfo.getMember();
+        if (!(field.getType() instanceof PsiPrimitiveType)) {
+          list.add(myFieldsToNonNull.get(equalsMemberInfo.getMember()));
+        }
+      }
+      myNonNullPanel.getTable().setMemberInfos(list);
+    }
+
+    private HashMap<PsiMember, MemberInfo> createFieldToMemberInfoMap(boolean checkedByDefault) {
+      Collection<MemberInfo> memberInfos = MemberInfo.extractClassMembers(myClass, MEMBER_INFO_FILTER, false);
+      final HashMap<PsiMember, MemberInfo> result = new HashMap<PsiMember, MemberInfo>();
+      for (MemberInfo memberInfo : memberInfos) {
+        memberInfo.setChecked(checkedByDefault);
+        result.put(memberInfo.getMember(), memberInfo);
+      }
+      return result;
+    }
+
+  }
+
+  public GenerateEqualsWizard(Project project, PsiClass aClass, boolean needEquals, boolean needHashCode) {
+    super(project, new JavaGenerateEqualsWizardBuilder(aClass, needEquals, needHashCode));
   }
 
   public PsiField[] getEqualsFields() {
@@ -171,21 +206,6 @@
   }
 
   @Override
-  protected void doNextAction() {
-    if (getCurrentStep() == myEqualsStepCode && myEqualsPanel != null) {
-      equalsFieldsSelected();
-    }
-    else if (getCurrentStep() == myHashcodeStepCode && myHashCodePanel != null) {
-      Collection<MemberInfo> selectedMemberInfos = myEqualsPanel != null ? myEqualsPanel.getTable().getSelectedMemberInfos() 
-                                                                         : myHashCodePanel.getTable().getSelectedMemberInfos();
-      updateNonNullMemberInfos(selectedMemberInfos);
-    }
-
-    super.doNextAction();
-    updateButtons();
-  }
-
-  @Override
   protected String getHelpID() {
     return "editing.altInsert.equals";
   }
@@ -204,47 +224,14 @@
     super.doOKAction();
   }
 
-  private HashMap<PsiElement, MemberInfo> createFieldToMemberInfoMap(boolean checkedByDefault) {
-    Collection<MemberInfo> memberInfos = MemberInfo.extractClassMembers(myClass, MEMBER_INFO_FILTER, false);
-    final HashMap<PsiElement, MemberInfo> result = new HashMap<PsiElement, MemberInfo>();
-    for (MemberInfo memberInfo : memberInfos) {
-      memberInfo.setChecked(checkedByDefault);
-      result.put(memberInfo.getMember(), memberInfo);
-    }
-    return result;
-  }
-
-  private void updateHashCodeMemberInfos(Collection<MemberInfo> equalsMemberInfos) {
-    if (myHashCodePanel == null) return;
-    List<MemberInfo> hashCodeFields = new ArrayList<MemberInfo>();
-
-    for (MemberInfo equalsMemberInfo : equalsMemberInfos) {
-      hashCodeFields.add((MemberInfo)myFieldsToHashCode.get(equalsMemberInfo.getMember()));
-    }
-
-    myHashCodePanel.getTable().setMemberInfos(hashCodeFields);
-  }
-
-  private void updateNonNullMemberInfos(Collection<MemberInfo> equalsMemberInfos) {
-    final ArrayList<MemberInfo> list = new ArrayList<MemberInfo>();
-
-    for (MemberInfoBase<PsiMember> equalsMemberInfo : equalsMemberInfos) {
-      PsiField field = (PsiField)equalsMemberInfo.getMember();
-      if (!(field.getType() instanceof PsiPrimitiveType)) {
-        list.add(myFieldsToNonNull.get(equalsMemberInfo.getMember()));
-      }
-    }
-    myNonNullPanel.getTable().setMemberInfos(list);
-  }
-
   @Override
   protected int getNextStep(int step) {
-    if (step + 1 == myTestBoxedStep) {
+    if (step + 1 == getNonNullStepCode()) {
       for (MemberInfo classField : myClassFields) {
         if (classField.isChecked()) {
           PsiField field = (PsiField)classField.getMember();
           if (!(field.getType() instanceof PsiPrimitiveType)) {
-            return myTestBoxedStep;
+            return getNonNullStepCode();
           }
         }
       }
@@ -255,88 +242,11 @@
   }
 
   @Override
-  protected boolean canGoNext() {
-    if (getCurrentStep() == myEqualsStepCode) {
-      for (MemberInfo classField : myClassFields) {
-        if (classField.isChecked()) {
-          return true;
-        }
-      }
-      return false;
+  protected void addSteps() {
+    if (myEqualsPanel != null) {
+      addStep(new InstanceofOptionStep());
     }
-
-    return true;
-  }
-
-  @Override
-  public JComponent getPreferredFocusedComponent() {
-    final Component stepComponent = getCurrentStepComponent();
-    if (stepComponent instanceof MemberSelectionPanel) {
-      return ((MemberSelectionPanel)stepComponent).getTable();
-    }
-    else {
-      return null;
-    }
-  }
-
-  private class MyTableModelListener implements TableModelListener {
-    @Override
-    public void tableChanged(TableModelEvent e) {
-      updateButtons();
-    }
-  }
-
-  private static class InstanceofOptionStep extends StepAdapter {
-    private final JComponent myPanel;
-
-    private InstanceofOptionStep() {
-      final JCheckBox checkbox = new NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses"));
-      checkbox.setSelected(CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER);
-      checkbox.addActionListener(new ActionListener() {
-        @Override
-        public void actionPerformed(final ActionEvent e) {
-          CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER = checkbox.isSelected();
-        }
-      });
-
-      myPanel = new JPanel(new VerticalFlowLayout());
-      myPanel.add(checkbox);
-      myPanel.add(new JLabel(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses.explanation")));
-    }
-
-    @Override
-    public JComponent getComponent() {
-      return myPanel;
-    }
-
-    @Override
-    @Nullable
-    public Icon getIcon() {
-      return null;
-    }
-  }
-
-  private static class MyStep extends StepAdapter {
-    final MemberSelectionPanel myPanel;
-
-    public MyStep(MemberSelectionPanel panel) {
-      myPanel = panel;
-    }
-
-    @Override
-    public Icon getIcon() {
-      return null;
-    }
-
-    @Override
-    public JComponent getComponent() {
-      return myPanel;
-    }
-
-    @Override
-    public JComponent getPreferredFocusedComponent() {
-      return myPanel.getTable();
-    }
+    super.addSteps();
   }
 
   private static class MyMemberInfoFilter implements MemberInfoBase.Filter<PsiMember> {
@@ -346,9 +256,9 @@
     }
   }
 
-
-  private static class EqualsMemberInfoModel implements MemberInfoModel<PsiMember, MemberInfo> {
-    MemberInfoTooltipManager<PsiMember, MemberInfo> myTooltipManager = new MemberInfoTooltipManager<PsiMember, MemberInfo>(new MemberInfoTooltipManager.TooltipProvider<PsiMember, MemberInfo>() {
+  private static class EqualsMemberInfoModel extends AbstractMemberInfoModel<PsiMember, MemberInfo> {
+    MemberInfoTooltipManager<PsiMember, MemberInfo> myTooltipManager =
+      new MemberInfoTooltipManager<PsiMember, MemberInfo>(new MemberInfoTooltipManager.TooltipProvider<PsiMember, MemberInfo>() {
       @Override
       public String getTooltip(MemberInfo memberInfo) {
         if (checkForProblems(memberInfo) == OK) return null;
@@ -372,26 +282,6 @@
     }
 
     @Override
-    public boolean isCheckedWhenDisabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public boolean isAbstractEnabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public boolean isAbstractWhenDisabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public Boolean isFixedAbstract(MemberInfo member) {
-      return null;
-    }
-
-    @Override
     public int checkForProblems(@NotNull MemberInfo member) {
       if (!(member.getMember() instanceof PsiField)) return ERROR;
       final PsiType type = ((PsiField)member.getMember()).getType();
@@ -401,16 +291,12 @@
     }
 
     @Override
-    public void memberInfoChanged(MemberInfoChange<PsiMember, MemberInfo> event) {
-    }
-
-    @Override
     public String getTooltipText(MemberInfo member) {
       return myTooltipManager.getTooltip(member);
     }
   }
 
-  private static class HashCodeMemberInfoModel implements MemberInfoModel<PsiMember, MemberInfo> {
+  private static class HashCodeMemberInfoModel extends AbstractMemberInfoModel<PsiMember, MemberInfo> {
     private final MemberInfoTooltipManager<PsiMember, MemberInfo> myTooltipManager = new MemberInfoTooltipManager<PsiMember, MemberInfo>(new MemberInfoTooltipManager.TooltipProvider<PsiMember, MemberInfo>() {
       @Override
       public String getTooltip(MemberInfo memberInfo) {
@@ -429,37 +315,37 @@
     }
 
     @Override
-    public boolean isCheckedWhenDisabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public boolean isAbstractEnabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public boolean isAbstractWhenDisabled(MemberInfo member) {
-      return false;
-    }
-
-    @Override
-    public Boolean isFixedAbstract(MemberInfo member) {
-      return null;
-    }
-
-    @Override
-    public int checkForProblems(@NotNull MemberInfo member) {
-      return OK;
-    }
-
-    @Override
-    public void memberInfoChanged(MemberInfoChange<PsiMember, MemberInfo> event) {
-    }
-
-    @Override
     public String getTooltipText(MemberInfo member) {
       return myTooltipManager.getTooltip(member);
     }
   }
+
+  private static class InstanceofOptionStep extends StepAdapter {
+    private final JComponent myPanel;
+
+    private InstanceofOptionStep() {
+      final JCheckBox checkbox = new NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses"));
+      checkbox.setSelected(CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER);
+      checkbox.addActionListener(new ActionListener() {
+        public void actionPerformed(@NotNull final ActionEvent M) {
+          CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER = checkbox.isSelected();
+        }
+      });
+
+      myPanel = new JPanel(new VerticalFlowLayout());
+      myPanel.add(checkbox);
+      myPanel.add(new JLabel(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses.explanation")));
+    }
+
+    @Override
+    public JComponent getComponent() {
+      return myPanel;
+    }
+
+    @Override
+    @Nullable
+    public Icon getIcon() {
+      return null;
+    }
+  }
 }
diff --git a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
index 18ba50a..c67f925 100644
--- a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
@@ -21,7 +21,6 @@
 package com.intellij.codeInspection;
 
 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInspection.ex.InspectionManagerEx;
 import com.intellij.psi.PsiDocCommentOwner;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiModifierListOwner;
@@ -45,7 +44,7 @@
     return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<SuppressQuickFix, SuppressIntentionAction>() {
       @Override
       public SuppressIntentionAction fun(SuppressQuickFix fix) {
-        return InspectionManagerEx.convertBatchToSuppressIntentionAction(fix);
+        return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction(fix);
       }
     });
   }
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
index e01c21c..4dacb84 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallHierarchyNodeDescriptor.java
@@ -39,7 +39,7 @@
 import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.ui.LayeredIcon;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
index 76e9875..1a3ce4e 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
@@ -27,4 +27,9 @@
   public boolean isAtLeast(@NotNull PsiElement element, @NotNull JavaSdkVersion version) {
     return JavaSdkVersionUtil.isAtLeast(element, version);
   }
+
+  @Override
+  public JavaSdkVersion getJavaSdkVersion(@NotNull PsiElement element) {
+    return JavaSdkVersionUtil.getJavaSdkVersion(element);
+  }
 }
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
index ad59dda..eb3ea75 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
@@ -109,25 +109,25 @@
   }
 
   @Override
-  public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
+  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
   }
 
   @Override
   @SuppressWarnings({"HardCodedStringLiteral"})
-  public String getBinPath(Sdk sdk) {
+  public String getBinPath(@NotNull Sdk sdk) {
     return getConvertedHomePath(sdk) + "bin";
   }
 
   @Override
   @NonNls
-  public String getToolsPath(Sdk sdk) {
+  public String getToolsPath(@NotNull Sdk sdk) {
     final String versionString = sdk.getVersionString();
     final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1"));
     return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x? "classes.zip" : "tools.jar");
   }
 
   @Override
-  public String getVMExecutablePath(Sdk sdk) {
+  public String getVMExecutablePath(@NotNull Sdk sdk) {
     /*
     if ("64".equals(System.getProperty("sun.arch.data.model"))) {
       return getBinPath(sdk) + File.separator + System.getProperty("os.arch") + File.separator + VM_EXE_NAME;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
index 39a8cdc..852c729 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi.impl.source.codeStyle;
 
+import com.intellij.codeInsight.ImportFilter;
 import com.intellij.lang.ASTNode;
 import com.intellij.lang.java.JavaLanguage;
 import com.intellij.openapi.diagnostic.Logger;
@@ -368,6 +369,10 @@
 
     String className = refClass.getQualifiedName();
     if (className == null) return true;
+
+    if (!ImportFilter.shouldImport(className)) {
+      return false;
+    }
     String packageName = getPackageOrClassName(className);
     String shortName = PsiNameHelper.getShortClassName(className);
 
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
index 2822fcf..fbf7ec3 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
@@ -38,7 +38,7 @@
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.ContainerUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -752,7 +752,7 @@
     int pLength = prefix.length();
     if (pLength > 0 && name.startsWith(prefix) && name.length() > pLength &&
         // check it's not just a long camel word that happens to begin with the specified prefix
-        (!Character.isJavaIdentifierPart(prefix.charAt(pLength - 1)) || Character.isUpperCase(name.charAt(pLength)))) {
+        (!Character.isLetter(prefix.charAt(pLength - 1)) || Character.isUpperCase(name.charAt(pLength)))) {
       name = name.substring(pLength);
       doDecapitalize = true;
     }
diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java
index 346ed4c..390ac0e 100644
--- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java
@@ -37,7 +37,7 @@
 import com.intellij.refactoring.util.CommonRefactoringUtil;
 import com.intellij.refactoring.util.classMembers.ElementNeedsThis;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
index bfbe8b2..df0afa8 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
@@ -30,6 +30,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.ValidationInfo;
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
@@ -660,12 +661,12 @@
     final String oldModifier = VisibilityUtil.getVisibilityModifier(modifierList);
     final String newModifier = getVisibility();
     String newModifierStr = VisibilityUtil.getVisibilityString(newModifier);
-    if (!newModifier.equals(oldModifier)) {
+    if (!Comparing.equal(newModifier, oldModifier)) {
       int index = modifiers.indexOf(oldModifier);
       if (index >= 0) {
         final StringBuilder buf = new StringBuilder(modifiers);
         buf.replace(index,
-                    index + oldModifier.length() + ("".equals(newModifierStr) ? 1 : 0),
+                    index + oldModifier.length() + (StringUtil.isEmpty(newModifierStr) ? 1 : 0),
                     newModifierStr);
         modifiers = buf.toString();
       } else {
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java
index 5657803..a57b996 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -89,7 +89,7 @@
     final PsiClass containingClass = method.getContainingClass();
     final PsiReferenceExpression refExpr = editor != null ? TargetElementUtil.findReferenceExpression(editor) : null;
     final boolean allowDelegation = containingClass != null && !containingClass.isInterface();
-    final DialogWrapper dialog = new JavaChangeSignatureDialog(project, method, allowDelegation, refExpr);
+    final DialogWrapper dialog = new JavaChangeSignatureDialog(project, method, allowDelegation, refExpr == null ? method : refExpr);
     dialog.show();
   }
 
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 1aac71d..be633c4 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
@@ -67,7 +67,7 @@
 import com.intellij.refactoring.util.occurrences.OccurrenceManager;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.VisibilityUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
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 08a6bf6..cb027ac 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
@@ -38,7 +38,7 @@
 import com.intellij.refactoring.util.RefactoringUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.VisibilityUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java
index b859be9..0b84dfe 100644
--- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java
@@ -33,6 +33,7 @@
 import com.intellij.util.Query;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.containers.HashSet;
+import com.intellij.util.containers.MultiMap;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -69,6 +70,18 @@
 
   @Override
   protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
+    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
+    for (UsageInfo info : myToInvert.keySet()) {
+      final PsiElement element = info.getElement();
+      if (element instanceof PsiMethodReferenceExpression) {
+        conflicts.putValue(element, "Method is used in method reference expression");
+      }
+    }
+
+    if (!conflicts.isEmpty())  {
+      return showConflicts(conflicts, null);
+    }
+
     if (myRenameProcessor.preprocessUsages(refUsages)) {
       prepareSuccessful();
       return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java
index 930eafc..41e0a2b 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveDirectoryWithClassesHelper.java
@@ -10,7 +10,7 @@
 import com.intellij.usageView.UsageInfo;
 import com.intellij.util.Function;
 import com.intellij.util.containers.MultiMap;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 
 import java.util.*;
 
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java
index 5f3471f..c2cd0af 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java
@@ -38,7 +38,7 @@
 import com.intellij.usageView.UsageInfo;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.HashMap;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
index 3134f39..258c263 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java
@@ -29,7 +29,7 @@
 import com.intellij.refactoring.util.MoveRenameUsageInfo;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java
index 72231dc..0f290cf 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaVetoRenameCondition.java
@@ -20,7 +20,7 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiJavaFile;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 
 public class JavaVetoRenameCondition implements Condition<PsiElement> {
   @Override
diff --git a/java/java-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionPanel.java b/java/java-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionPanel.java
new file mode 100644
index 0000000..0e9397a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionPanel.java
@@ -0,0 +1,14 @@
+package com.intellij.refactoring.ui;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.classMembers.MemberInfoBase;
+
+import javax.swing.*;
+
+/**
+ * Nikolay.Tropin
+ * 8/20/13
+ */
+public abstract class AbstractMemberSelectionPanel<T extends PsiElement, M extends MemberInfoBase<T>> extends JPanel {
+  public abstract AbstractMemberSelectionTable<T, M> getTable();
+}
diff --git a/java/java-impl/src/com/intellij/refactoring/ui/MemberSelectionPanel.java b/java/java-impl/src/com/intellij/refactoring/ui/MemberSelectionPanel.java
index 05dd6f8..c503a86 100644
--- a/java/java-impl/src/com/intellij/refactoring/ui/MemberSelectionPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/ui/MemberSelectionPanel.java
@@ -24,18 +24,16 @@
  */
 package com.intellij.refactoring.ui;
 
+import com.intellij.psi.PsiMember;
 import com.intellij.refactoring.util.classMembers.MemberInfo;
 import com.intellij.ui.ScrollPaneFactory;
 import com.intellij.ui.SeparatorFactory;
-import com.intellij.ui.TableUtil;
 
 import javax.swing.*;
 import java.awt.*;
-import java.awt.event.FocusAdapter;
-import java.awt.event.FocusEvent;
 import java.util.List;
 
-public class MemberSelectionPanel extends JPanel {
+public class MemberSelectionPanel extends AbstractMemberSelectionPanel<PsiMember, MemberInfo> {
   private final MemberSelectionTable myTable;
 
   /**
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
index add3fe2..e8af76b 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
@@ -32,7 +32,7 @@
 import com.intellij.usages.UsageView;
 import com.intellij.usages.rules.PsiElementUsage;
 import com.intellij.usages.rules.UsageGroupingRule;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
index 233bb42..be4c4f8 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
@@ -83,6 +83,17 @@
     });
   }
 
+  public interface InheritanceChecker {
+    boolean checkInheritance(@NotNull PsiClass subClass, @NotNull PsiClass parentClass);
+
+    InheritanceChecker DEFAULT = new InheritanceChecker() {
+      @Override
+      public boolean checkInheritance(@NotNull PsiClass subClass, @NotNull PsiClass parentClass) {
+        return subClass.isInheritor(parentClass, false);
+      }
+    };
+  }
+
   public static class SearchParameters {
     private final PsiClass myClass;
     private final SearchScope myScope;
@@ -90,6 +101,7 @@
     private final boolean myCheckInheritance;
     private final boolean myIncludeAnonymous;
     private final Condition<String> myNameCondition;
+    private final InheritanceChecker myInheritanceChecker;
 
     public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
       this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, Condition.TRUE);
@@ -97,12 +109,18 @@
 
     public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance,
                             boolean includeAnonymous, @NotNull final Condition<String> nameCondition) {
+      this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, nameCondition, InheritanceChecker.DEFAULT);
+    }
+
+    public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance,
+                            boolean includeAnonymous, @NotNull final Condition<String> nameCondition, @NotNull InheritanceChecker inheritanceChecker) {
       myClass = aClass;
       myScope = scope;
       myCheckDeep = checkDeep;
       myCheckInheritance = checkInheritance;
       myIncludeAnonymous = includeAnonymous;
       myNameCondition = nameCondition;
+      myInheritanceChecker = inheritanceChecker;
     }
 
     @NotNull
@@ -204,7 +222,7 @@
           public void run() {
             fqn[0] = candidate.getQualifiedName();
             if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) {
-              if (!candidate.isInheritor(currentBase.get(), false)) {
+              if (!parameters.myInheritanceChecker.checkInheritance(candidate, currentBase.get())) {
                 result.set(true);
                 return;
               }
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java
new file mode 100644
index 0000000..4863b82
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java
@@ -0,0 +1,22 @@
+package com.intellij.codeInsight;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class ImportFilter {
+  public static final ExtensionPointName<ImportFilter> EP_NAME = new ExtensionPointName<ImportFilter>("com.intellij.importFilter");
+
+  public abstract boolean shouldUseFullyQualifiedName(@NotNull String classQualifiedName);
+
+  public static boolean shouldImport(@NotNull String classQualifiedName) {
+    for (ImportFilter filter : EP_NAME.getExtensions()) {
+      if (filter.shouldUseFullyQualifiedName(classQualifiedName)) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/TestFrameworks.java b/java/java-psi-api/src/com/intellij/codeInsight/TestFrameworks.java
index 9f7e024..248aad7 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/TestFrameworks.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/TestFrameworks.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -35,4 +35,13 @@
 
   @Nullable
   public abstract PsiMethod findSetUpMethod(PsiClass psiClass);
+
+  @Nullable
+  public abstract PsiMethod findTearDownMethod(PsiClass psiClass);
+
+  protected abstract boolean hasConfigMethods(PsiClass psiClass);
+
+  public boolean isTestOrConfig(PsiClass psiClass) {
+    return isTestClass(psiClass) || hasConfigMethods(psiClass);
+  }
 }
diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java
index 9e8338e..5108c59 100644
--- a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java
+++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java
@@ -32,4 +32,8 @@
   public boolean isAtLeast(@NotNull PsiElement element, @NotNull JavaSdkVersion version) {
     return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel());
   }
+
+  public JavaSdkVersion getJavaSdkVersion(@NotNull PsiElement element) {
+    return JavaSdkVersion.fromLanguageLevel(PsiUtil.getLanguageLevel(element));
+  }
 }
\ No newline at end of file
diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
index 2bfe470..b0a0149 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -93,7 +93,7 @@
     return initialSubst;
   }
 
-  public static boolean isValidLambdaContext(PsiElement context) {
+  public static boolean isValidLambdaContext(@Nullable PsiElement context) {
     return context instanceof PsiTypeCastExpression ||
            context instanceof PsiAssignmentExpression ||
            context instanceof PsiVariable ||
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
index 17117c4..a2a75bc 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -107,6 +107,15 @@
     }
     return new QualifierResolveResult(containingClass, substitutor, false);
   }
+  
+  public static boolean isStaticallyReferenced(@NotNull PsiMethodReferenceExpression methodReferenceExpression) {
+    final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
+    if (qualifierExpression != null) {
+      return qualifierExpression instanceof PsiReferenceExpression &&
+             ((PsiReferenceExpression)qualifierExpression).resolve() instanceof PsiClass;
+    }
+    return true;
+  }
 
   public static boolean isAcceptable(@Nullable final PsiMethodReferenceExpression methodReferenceExpression, PsiType left) {
     if (methodReferenceExpression == null) return false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java b/java/java-psi-api/src/com/intellij/psi/util/FileTypeUtils.java
similarity index 91%
rename from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java
rename to java/java-psi-api/src/com/intellij/psi/util/FileTypeUtils.java
index 7888121..0080248 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/FileTypeUtils.java
@@ -13,11 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.siyeh.ig.psiutils;
+package com.intellij.psi.util;
 
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.ServerPageFile;
-import com.intellij.psi.util.PsiUtilCore;
 
 public class FileTypeUtils {
   public static boolean isInServerPageFile(PsiElement file) {
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
index 3504ef8..e3e2511 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
@@ -19,7 +19,6 @@
 import com.intellij.lang.java.parser.JavaParser;
 import com.intellij.lang.java.parser.JavaParserUtil;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.LowMemoryWatcher;
 import com.intellij.openapi.util.Pair;
@@ -251,9 +250,9 @@
 
       MostlySingularMultiMap<String, AnnotationData> fileData = getDataFromFile(file);
 
-      addAnnotations(result, externalName, file, fileData);
+      ContainerUtil.addAll(result, fileData.get(externalName));
       if (oldExternalName != null && !externalName.equals(oldExternalName)) {
-        addAnnotations(result, oldExternalName, file, fileData);
+        ContainerUtil.addAll(result, fileData.get(oldExternalName));
       }
     }
     if (result.isEmpty()) {
@@ -263,24 +262,6 @@
     return result;
   }
 
-  private void addAnnotations(@NotNull List<AnnotationData> result,
-                                     @NotNull String externalName,
-                                     @NotNull PsiFile file,
-                                     @NotNull MostlySingularMultiMap<String, AnnotationData> fileData) {
-    Iterable<AnnotationData> data = fileData.get(externalName);
-    for (AnnotationData ad : data) {
-      if (result.contains(ad)) {
-        // there can be compatible annotations in different files
-        if (Comparing.equal(ad.virtualFile, file.getVirtualFile())) {
-          duplicateError(file, externalName, "Duplicate signature");
-        }
-      }
-      else {
-        result.add(ad);
-      }
-    }
-  }
-
   @Override
   @Nullable
   public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
@@ -414,13 +395,11 @@
   private static class AnnotationData {
     @NotNull private final String annotationClassFqName;
     @NotNull private final String annotationParameters;
-    private final VirtualFile virtualFile;
     private volatile PsiAnnotation annotation;
 
-    private AnnotationData(@NotNull String annotationClassFqName, @NotNull String annotationParameters, VirtualFile virtualFile) {
+    private AnnotationData(@NotNull String annotationClassFqName, @NotNull String annotationParameters) {
       this.annotationClassFqName = annotationClassFqName;
       this.annotationParameters = annotationParameters;
-      this.virtualFile = virtualFile;
     }
 
     @NotNull
@@ -514,7 +493,7 @@
               duplicateError(file, externalName, "Duplicate annotation '" + annotationFQN + "' ");
             }
           }
-          AnnotationData annData = internAnnotationData(new AnnotationData(annotationFQN, argumentsString, file.getVirtualFile()));
+          AnnotationData annData = internAnnotationData(new AnnotationData(annotationFQN, argumentsString));
           data.add(externalName, annData);
           annotationFQN = null;
           arguments = null;
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/TestFrameworksImpl.java b/java/java-psi-impl/src/com/intellij/codeInsight/TestFrameworksImpl.java
index 08c7cd2..7671eae 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/TestFrameworksImpl.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/TestFrameworksImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -76,4 +76,28 @@
     }
     return null;
   }
+  
+  @Override
+  @Nullable
+  public PsiMethod findTearDownMethod(final PsiClass psiClass) {
+    final TestFramework[] testFrameworks = Extensions.getExtensions(TestFramework.EXTENSION_NAME);
+    for (TestFramework framework : testFrameworks) {
+      if (framework.isTestClass(psiClass)) {
+        final PsiMethod setUpMethod = (PsiMethod)framework.findTearDownMethod(psiClass);
+        if (setUpMethod != null) {
+          return setUpMethod;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  protected boolean hasConfigMethods(PsiClass psiClass) {
+    final TestFramework[] testFrameworks = Extensions.getExtensions(TestFramework.EXTENSION_NAME);
+    for (TestFramework framework : testFrameworks) {
+      if (framework.findSetUpMethod(psiClass) != null || framework.findTearDownMethod(psiClass) != null) return true;
+    }
+    return false;
+  }
 }
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
index 1df6096..dd39040 100644
--- a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
+++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
@@ -26,10 +26,7 @@
 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;
+import java.util.*;
 
 /**
  * @author yole
@@ -138,36 +135,48 @@
         if (classes.length == 1) {
           PsiClass curClass = classes[0];
 
-          if (bucks > 0) {
-            int newComponentStart = 0;
-            int lookupStart = 0;
+            if (bucks > 0) {
+              Stack<ClassAndOffsets> currentPath = new Stack<ClassAndOffsets>();
+              currentPath.add(new ClassAndOffsets(curClass, 0, 0));
+              currentPath.add(currentPath.peek());
 
-            while (lookupStart <= className.length()) {
-              int b = className.indexOf("$", lookupStart);
-              b =  b < 0 ? className.length(): b;
+              while (currentPath.size() > 1) {
+                ClassAndOffsets classAndOffset = currentPath.pop();
+                int newComponentStart = classAndOffset.componentStart;
+                int lookupStart = classAndOffset.lookupStart;
+                curClass = currentPath.peek().clazz; //owner class
 
-              String component = className.substring(newComponentStart, b);
-              PsiClass inner = curClass.findInnerClassByName(component, false);
+                while (lookupStart <= className.length()) {
+                  int bucksIndex = className.indexOf("$", lookupStart);
+                  bucksIndex =  bucksIndex < 0 ? className.length(): bucksIndex;
 
-              lookupStart = b + 1;
-              if (inner == null) {
-                continue;
+                  String component = className.substring(newComponentStart, bucksIndex);
+                  PsiClass inner = curClass.findInnerClassByName(component, false);
+
+                  lookupStart = bucksIndex + 1;
+                  if (inner == null) {
+                    continue;
+                  }
+
+                  currentPath.add(new ClassAndOffsets(inner, newComponentStart, lookupStart));
+
+                  newComponentStart = lookupStart;
+                  curClass = inner;
+                }
+
+                if (lookupStart == newComponentStart) {
+                  return curClass;
+                }
               }
 
-              newComponentStart = lookupStart;
-              curClass = inner;
-            }
-
-            if (lookupStart != newComponentStart) {
               return null;
+
+            } else {
+              return curClass;
             }
           }
-
-
-          return curClass;
         }
       }
-    }
 
     return null;
   }
@@ -196,4 +205,17 @@
   public void addToClasspath(VirtualFile root) {
     myClasspath.add(root);
   }
+
+  private static class ClassAndOffsets {
+
+    final PsiClass clazz;
+    final int componentStart;
+    final int lookupStart;
+
+    ClassAndOffsets(PsiClass clazz, int componentStart, int lookupStart) {
+      this.clazz = clazz;
+      this.componentStart = componentStart;
+      this.lookupStart = lookupStart;
+    }
+  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java
index 333ed4c..b5c0f8e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java
@@ -47,7 +47,7 @@
     }
     if (codeFragment == null) return null;
     if (myCodeFragment.getContainingFile() == codeFragment.getContainingFile() &&  // in order for jsp includes to work
-        !myCodeFragment.equals(codeFragment)) {
+        !myCodeFragment.equals(codeFragment) && !(myCodeFragment.getParent() instanceof PsiLambdaExpression)) {
       return null;
     }
     return (PsiVariable)refElement;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
index 0100ccc..03a14f4 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsAnnotationParameterListImpl.java
@@ -31,14 +31,20 @@
   public ClsAnnotationParameterListImpl(@NotNull PsiAnnotation parent, @NotNull PsiNameValuePair[] psiAttributes) {
     myParent = parent;
     myAttributes = new ClsNameValuePairImpl[psiAttributes.length];
-    for (int i = 0; i < myAttributes.length; i++) {
+    for (int i = 0; i < psiAttributes.length; i++) {
       String name = psiAttributes[i].getName();
+
       PsiAnnotationMemberValue value = psiAttributes[i].getValue();
       if (value == null) {
         String anno = parent instanceof ClsAnnotationImpl ? ((ClsAnnotationImpl)parent).getStub().getText() : parent.getText();
-        Logger.getInstance(getClass()).error("name=" + name + " anno=[" + anno + "]");
+        Logger.getInstance(getClass()).error("name=" + name + " anno=[" + anno + "] file=" + parent.getContainingFile());
         value = new ClsLiteralExpressionImpl(this, "null", PsiType.NULL, null);
       }
+
+      if (psiAttributes.length == 1 && "value".equals(name)) {
+        name = null;  // cosmetics - omit default attribute name
+      }
+
       myAttributes[i] = new ClsNameValuePairImpl(this, name, value);
     }
   }
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 8e79478..7324f7b 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
@@ -17,9 +17,7 @@
 
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiNameHelper;
-import com.intellij.psi.PsiReferenceList;
+import com.intellij.psi.*;
 import com.intellij.psi.impl.cache.ModifierFlags;
 import com.intellij.psi.impl.cache.TypeInfo;
 import com.intellij.psi.impl.java.stubs.*;
@@ -340,7 +338,7 @@
 
     byte flags = PsiFieldStubImpl.packFlags((access & Opcodes.ACC_ENUM) != 0, (access & Opcodes.ACC_DEPRECATED) != 0, false);
     TypeInfo type = fieldType(desc, signature);
-    String initializer = constToString(value, "boolean".equals(type.text.getString()), false);
+    String initializer = constToString(value, type.text.getString(), false);
     PsiFieldStub stub = new PsiFieldStubImpl(myResult, name, type, initializer, flags);
     PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packFieldFlags(access));
     return new AnnotationCollectingVisitor(modList);
@@ -537,7 +535,7 @@
     @Override
     public void visit(final String name, final Object value) {
       valuePairPrefix(name);
-      myBuilder.append(constToString(value, false, true));
+      myBuilder.append(constToString(value, null, true));
     }
 
     @Override
@@ -556,7 +554,7 @@
         myBuilder.append(',');
       }
 
-      if (name != null && !"value".equals(name)) {
+      if (name != null) {
         myBuilder.append(name).append('=');
       }
     }
@@ -697,18 +695,34 @@
   }
 
   @Nullable
-  private static String constToString(@Nullable Object value, boolean isBoolean, boolean anno) {
+  private static String constToString(@Nullable Object value, @Nullable String type, boolean anno) {
     if (value == null) return null;
 
-    if (value instanceof String) return "\"" + StringUtil.escapeStringCharacters((String)value) + "\"";
-    if (value instanceof Boolean) return value.toString();
-    if (value instanceof Long) return value.toString() + "L";
+    if (value instanceof String) {
+      return "\"" + StringUtil.escapeStringCharacters((String)value) + "\"";
+    }
+
+    if (value instanceof Boolean || value instanceof Short || value instanceof Byte) {
+      return value.toString();
+    }
+
+    if (value instanceof Character) {
+      return "'" + StringUtil.escapeCharCharacters(value.toString()) + "'";
+    }
+
+    if (value instanceof Long) {
+      return value.toString() + "L";
+    }
 
     if (value instanceof Integer) {
-      if (isBoolean) {
+      if ("boolean".equals(type)) {
         if (value.equals(0)) return "false";
         if (value.equals(1)) return "true";
       }
+      if ("char".equals(type)) {
+        char ch = (char)((Integer)value).intValue();
+        return "'" + StringUtil.escapeCharCharacters(String.valueOf(ch)) + "'";
+      }
       return value.toString();
     }
 
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 4c799c6..25ff273 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -427,7 +427,9 @@
 
         boolean hasReceiver = false;
         final PsiType[] parameterTypes = mySignature.getParameterTypes();
-        if (parameterTypes.length > 0 && PsiMethodReferenceUtil.isReceiverType(parameterTypes[0], myContainingClass, mySubstitutor)) {
+        if (parameterTypes.length > 0 && 
+            PsiMethodReferenceUtil.isReceiverType(parameterTypes[0], myContainingClass, mySubstitutor) && 
+            PsiMethodReferenceUtil.isStaticallyReferenced(PsiMethodReferenceExpressionImpl.this)) {
           hasReceiver = true;
         }
 
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java
new file mode 100644
index 0000000..8b6864c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java
@@ -0,0 +1,3 @@
+class Test {
+  Runnable r = () -> <caret>
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java
new file mode 100644
index 0000000..8bda0af
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java
@@ -0,0 +1,3 @@
+class Test {
+  Runnable r = <caret>
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ExprReceiver.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ExprReceiver.java
new file mode 100644
index 0000000..f3bc8d4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ExprReceiver.java
@@ -0,0 +1,15 @@
+class ThreadExample {
+    interface Function<T, R> {
+
+        R apply(T t);
+    }
+    {
+        A a = new A();
+        <error descr="Incompatible types. Found: '<method reference>', required: 'ThreadExample.Function<? super ThreadExample.A,? extends java.lang.String>'">Function<? super A,? extends String> foo = a::foo;</error>
+    }
+
+    static class A {
+        public String foo() { return "a"; }
+    }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/after37.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/after37.java
new file mode 100644
index 0000000..97dcfd5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/after37.java
@@ -0,0 +1,8 @@
+// "Make 'a' not abstract" "true"
+import java.io.*;
+
+abstract class A {
+  void a<caret>() {
+  }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before37.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before37.java
new file mode 100644
index 0000000..6be3122
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before37.java
@@ -0,0 +1,8 @@
+// "Make 'a' not abstract" "true"
+import java.io.*;
+
+abstract class A {
+  abstract void a<caret>() {
+  }
+}
+
diff --git a/java/java-tests/testData/codeInsight/generateConstructor/afterFieldPrefixCoincidence1.java b/java/java-tests/testData/codeInsight/generateConstructor/afterFieldPrefixCoincidence1.java
new file mode 100644
index 0000000..29be0de
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generateConstructor/afterFieldPrefixCoincidence1.java
@@ -0,0 +1,7 @@
+class Test {
+  private int _foo;
+
+    Test(int foo) {
+        _foo = foo;
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generateConstructor/beforeFieldPrefixCoincidence1.java b/java/java-tests/testData/codeInsight/generateConstructor/beforeFieldPrefixCoincidence1.java
new file mode 100644
index 0000000..8acd4dc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generateConstructor/beforeFieldPrefixCoincidence1.java
@@ -0,0 +1,4 @@
+class Test {
+  private int _foo;
+  <caret>
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/guarded/itself.java b/java/java-tests/testData/inspection/guarded/itself.java
new file mode 100644
index 0000000..35b7845
--- /dev/null
+++ b/java/java-tests/testData/inspection/guarded/itself.java
@@ -0,0 +1,19 @@
+import net.jcip.annotations.GuardedBy;
+
+import java.lang.String;
+
+class A {
+
+    @GuardedBy("itself")
+    private String _foo;
+
+    public String getFoo() {
+        synchronized (_foo) {
+            return _foo;
+        }
+    }
+
+    public void setFoo(String foo) {
+        <warning descr="Access to field '_foo' outside of declared guards">_foo</warning> = foo;
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/expected.xml b/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/expected.xml
new file mode 100644
index 0000000..1da1935
--- /dev/null
+++ b/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/expected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+  <problem>
+    <file>Junk.java</file>
+    <line>4</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Local variable or parameter can be final</problem_class>
+    <description>Variable &lt;code&gt;i&lt;/code&gt; can have &lt;code&gt;final&lt;/code&gt; modifier</description>
+  </problem>
+  <problem>
+    <file>Junk.java</file>
+    <line>3</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Local variable or parameter can be final</problem_class>
+    <description>Variable &lt;code&gt;r&lt;/code&gt; can have &lt;code&gt;final&lt;/code&gt; modifier</description>
+  </problem>
+</problems>
+
diff --git a/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/src/Junk.java b/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/src/Junk.java
new file mode 100644
index 0000000..f89a1e2
--- /dev/null
+++ b/java/java-tests/testData/inspection/localCanBeFinal/LambdaBody/src/Junk.java
@@ -0,0 +1,10 @@
+public final class Junk {
+  public void sillyMethod() {
+    Runnable r = () -> {
+      int i = 0;
+      System.out.println(i);
+    };
+  }
+}
+
+
diff --git a/java/java-tests/testData/psi/cls/mirror/Annotations.txt b/java/java-tests/testData/psi/cls/mirror/Annotations.txt
index 9bbe384..58f2792 100644
--- a/java/java-tests/testData/psi/cls/mirror/Annotations.txt
+++ b/java/java-tests/testData/psi/cls/mirror/Annotations.txt
@@ -25,6 +25,9 @@
     @pkg.Annotations.A4(ids = {42, 84})
     abstract void m4b();
 
+    @pkg.Annotations.A5(b = true, value = java.lang.Integer.class)
+    abstract void m5();
+
     static @interface IndeterminateAnno {
         float f1() default -1.0f / 0.0;
 
@@ -39,6 +42,12 @@
         double d3() default 1.0 / 0.0;
     }
 
+    static @interface A5 {
+        boolean b() default false;
+
+        java.lang.Class<? extends java.lang.Number> value() default java.lang.Integer.class;
+    }
+
     static @interface A4 {
         int[] ids() default {};
     }
diff --git a/java/java-tests/testData/psi/cls/mirror/Booleans.txt b/java/java-tests/testData/psi/cls/mirror/Booleans.txt
deleted file mode 100644
index 8def7d9..0000000
--- a/java/java-tests/testData/psi/cls/mirror/Booleans.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-  // IntelliJ API Decompiler stub source generated from a class file
-  // Implementation of methods is not available
-
-package pkg;
-
-class Booleans {
-    public static final boolean TRUE = true;
-    public static final boolean FALSE = false;
-
-    Booleans() { /* compiled code */ }
-
-    @pkg.BooleanAnno(true)
-    public static boolean TRUE() { /* compiled code */ }
-
-    @pkg.BooleanAnno(false)
-    public static boolean FALSE() { /* compiled code */ }
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/cls/mirror/Primitives.txt b/java/java-tests/testData/psi/cls/mirror/Primitives.txt
new file mode 100644
index 0000000..4eb6750d
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/Primitives.txt
@@ -0,0 +1,30 @@
+
+  // IntelliJ API Decompiler stub source generated from a class file
+  // Implementation of methods is not available
+
+package pkg;
+
+class Primitives {
+    public static final boolean TRUE = true;
+    public static final boolean FALSE = false;
+    public static final byte BYTE = 1;
+    public static final char CHAR = '\'';
+    public static final short SHORT = 42;
+    public static final int INT = 42;
+    public static final long LONG = 42L;
+
+    Primitives() { /* compiled code */ }
+
+    @pkg.BooleanAnno(true)
+    public static boolean TRUE() { /* compiled code */ }
+
+    @pkg.BooleanAnno(false)
+    public static boolean FALSE() { /* compiled code */ }
+
+    @pkg.ByteAnno(1)
+    @pkg.CharAnno('\\')
+    @pkg.ShortAnno(42)
+    @pkg.IntAnno(42)
+    @pkg.LongAnno(42L)
+    public static void m() { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A1.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A1.class
index 6120960..00c4747 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A1.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A1.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A2.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A2.class
index 8d94afe..96bda0c 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A2.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A2.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A3.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A3.class
index 630cfd9..c23cb7c 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A3.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A3.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A4.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A4.class
index 040a84c..e00c95b 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A4.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A4.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A5.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A5.class
new file mode 100644
index 0000000..b85d9d0
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$A5.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$IndeterminateAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$IndeterminateAnno.class
index d77b499..101bbd2 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$IndeterminateAnno.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations$IndeterminateAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations.class b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations.class
index 03f1f52..a5293f0 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Annotations.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Annotations.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/BooleanAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/BooleanAnno.class
index 64ba86f..118a4c4 100644
--- a/java/java-tests/testData/psi/cls/mirror/pkg/BooleanAnno.class
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/BooleanAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Booleans.class b/java/java-tests/testData/psi/cls/mirror/pkg/Booleans.class
deleted file mode 100644
index 1a71ca0..0000000
--- a/java/java-tests/testData/psi/cls/mirror/pkg/Booleans.class
+++ /dev/null
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/ByteAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/ByteAnno.class
new file mode 100644
index 0000000..6250428
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/ByteAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/CharAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/CharAnno.class
new file mode 100644
index 0000000..17e8b67
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/CharAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/IntAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/IntAnno.class
new file mode 100644
index 0000000..e3e7eed
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/IntAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/LongAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/LongAnno.class
new file mode 100644
index 0000000..6314705
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/LongAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Primitives.class b/java/java-tests/testData/psi/cls/mirror/pkg/Primitives.class
new file mode 100644
index 0000000..1e2d9f0
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Primitives.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/ShortAnno.class b/java/java-tests/testData/psi/cls/mirror/pkg/ShortAnno.class
new file mode 100644
index 0000000..e5583b1
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/ShortAnno.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Annotations.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Annotations.java
index 5aeda68..dafd4dc 100644
--- a/java/java-tests/testData/psi/cls/mirror/src/pkg/Annotations.java
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/Annotations.java
@@ -16,6 +16,11 @@
     int[] ids() default { };
   }
 
+  @interface A5 {
+    boolean b() default false;
+    Class<? extends Number> value() default Integer.class;
+  }
+
   @A1 abstract void m1();
 
   @A2() abstract void m2a();
@@ -26,6 +31,8 @@
   @A4 abstract void m4a();
   @A4(ids = {42, 84}) abstract void m4b();
 
+  @A5(b = true, value = Integer.class) abstract void m5();
+
   @interface IndeterminateAnno {
     float f1() default Float.NEGATIVE_INFINITY;
     float f2() default Float.NaN;
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Booleans.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Booleans.java
deleted file mode 100644
index 495e1ac..0000000
--- a/java/java-tests/testData/psi/cls/mirror/src/pkg/Booleans.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package pkg;
-
-class Booleans  {
-  public static final boolean TRUE = true;
-  public static final boolean FALSE = false;
-
-  @BooleanAnno(true) public static boolean TRUE() { return TRUE; }
-  @BooleanAnno(false) public static boolean FALSE() { return FALSE; }
-}
-
-@interface BooleanAnno {
-  boolean value();
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Primitives.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Primitives.java
new file mode 100644
index 0000000..4ffcf4a
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/Primitives.java
@@ -0,0 +1,42 @@
+package pkg;
+
+class Primitives  {
+  public static final boolean TRUE = true;
+  public static final boolean FALSE = false;
+
+  @BooleanAnno(true) public static boolean TRUE() { return TRUE; }
+  @BooleanAnno(false) public static boolean FALSE() { return FALSE; }
+
+  public static final byte BYTE = 1;
+  public static final char CHAR = '\'';
+  public static final short SHORT = 42;
+  public static final int INT = 42;
+  public static final long LONG = 42L;
+
+  @ByteAnno(1) @CharAnno('\\') @ShortAnno(42) @IntAnno(42) @LongAnno(42L)
+  public static void m() { }
+}
+
+@interface BooleanAnno {
+  boolean value();
+}
+
+@interface ByteAnno {
+  byte value();
+}
+
+@interface CharAnno {
+  char value();
+}
+
+@interface ShortAnno {
+  short value();
+}
+
+@interface IntAnno {
+  int value();
+}
+
+@interface LongAnno {
+  long value();
+}
diff --git a/java/java-tests/testData/psi/cls/stubBuilder/Nullable.txt b/java/java-tests/testData/psi/cls/stubBuilder/Nullable.txt
index 277fe14..5f492a7 100644
--- a/java/java-tests/testData/psi/cls/stubBuilder/Nullable.txt
+++ b/java/java-tests/testData/psi/cls/stubBuilder/Nullable.txt
@@ -2,8 +2,8 @@
   PsiClassStub[interface annotation name=Nullable fqn=org.jetbrains.annotations.Nullable]
     PsiModifierListStub[mask=1025]
       PsiAnnotationStub[@java.lang.annotation.Documented]
-      PsiAnnotationStub[@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)]
-      PsiAnnotationStub[@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD,java.lang.annotation.ElementType.PARAMETER,java.lang.annotation.ElementType.LOCAL_VARIABLE})]
+      PsiAnnotationStub[@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.CLASS)]
+      PsiAnnotationStub[@java.lang.annotation.Target(value={java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD,java.lang.annotation.ElementType.PARAMETER,java.lang.annotation.ElementType.LOCAL_VARIABLE})]
     PsiTypeParameterListStub
     PsiRefListStub[EXTENDS_LIST:]
     PsiRefListStub[IMPLEMENTS_LIST:]
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1.java
similarity index 76%
copy from plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
copy to java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1.java
index 6830246..fcb14a8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
+++ b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1.java
@@ -13,13 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn.properties;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/12/12
- * Time: 8:40 PM
- */
-public class SvnPropDetailsProvider {
+class Test {
+  public void foo(int ii) {
+    Runnable r = () -> {
+      <selection>System.out.println(ii);</selection>
+    };
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1_after.java
similarity index 76%
rename from plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
rename to java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1_after.java
index 6830246..6debfde 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
+++ b/java/java-tests/testData/refactoring/extractMethod/FromLambdaBody1_after.java
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn.properties;
+class Test {
+  public void foo(int ii) {
+    Runnable r = () -> {
+        newMethod(ii);
+    };
+  }
 
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/12/12
- * Time: 8:40 PM
- */
-public class SvnPropDetailsProvider {
+    private void newMethod(int ii) {
+        System.out.println(ii);
+    }
 }
diff --git a/java/java-tests/testData/refactoring/invertBoolean/methodRefs.java b/java/java-tests/testData/refactoring/invertBoolean/methodRefs.java
new file mode 100644
index 0000000..b7477fc
--- /dev/null
+++ b/java/java-tests/testData/refactoring/invertBoolean/methodRefs.java
@@ -0,0 +1,14 @@
+abstract class A{
+    static boolean isB<caret>ool() {
+        return false;
+    }
+    
+    
+    interface I {
+        boolean b();
+    }
+    
+    {
+        I i = A::isBool;
+    }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateConstructorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateConstructorTest.java
index 3fb5b7c..5ef9e70 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateConstructorTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateConstructorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -55,6 +55,11 @@
     doTest();
   }
 
+  public void testFieldPrefixCoincidence1() throws Exception {
+    CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings().FIELD_NAME_PREFIX = "_";
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
index 6690708..d626cba 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -83,6 +83,20 @@
     assert lookup.focused
   }
 
+  public void testAfterDblColon() {
+    myFixture.configureByText("a.java", """
+      class Foo {
+        void foo() {
+          Runnable::<caret>
+        }
+      }
+    """)
+    type('r')
+    def les = myFixture.lookupElementStrings
+    assert 'run' in les
+    assert lookup.focused
+  }
+
   def assertContains(String... items) {
     myFixture.assertPreferredCompletionItems(0, items)
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
index f8ea1ba..c386bd3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -66,6 +66,10 @@
     doTest();
   }
 
+  public void testInLambdaPosition() throws Exception {
+    doTest();
+  }
+
   private void doTest() {
     configureByFile("/" + getTestName(false) + ".java");
     assertNotNull(myItems);
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 064b2c3..a1016d7 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
@@ -78,6 +78,7 @@
   public void testAbstractMethod() { doTest(); }
   public void testMethodRefAcceptance() { doTest(); }
   public void testVarargsMethodRef() { doTest(); }
+  public void testExprReceiver() { doTest(); }
 
   public void testTypeParameterWithExtendsList() throws Exception {
     doTest();
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java
new file mode 100644
index 0000000..88fd4ce
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/FieldAccessedNotGuardedInspectionTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.intellij.codeInspection;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInspection.concurrencyAnnotations.FieldAccessNotGuardedInspection;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+public class FieldAccessedNotGuardedInspectionTest extends LightCodeInsightFixtureTestCase {
+  public void testItself() throws Exception {
+    myFixture.addClass("package net.jcip.annotations;\n" +
+                       "@java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})\n" +
+                       "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" +
+                       "public @interface GuardedBy {\n" +
+                       "    java.lang.String value();\n" +
+                       "}");
+    myFixture.testHighlighting(true, false, false, getTestName(true) + ".java");
+  }
+
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    myFixture.enableInspections(new FieldAccessNotGuardedInspection());
+  }
+
+  @NotNull
+   @Override
+   protected String getTestDataPath() {
+     return JavaTestUtil.getJavaTestDataPath() + "/inspection/guarded";
+   }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/LocalCanBeFinalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/LocalCanBeFinalTest.java
index c8e5ecf..7dfa608 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/LocalCanBeFinalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/LocalCanBeFinalTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.intellij.codeInspection;
 
 import com.intellij.JavaTestUtil;
@@ -102,4 +117,10 @@
     myTool.REPORT_VARIABLES = true;
     doTest();
   }
+
+  public void testLambdaBody() throws Exception {
+    myTool.REPORT_PARAMETERS = true;
+    myTool.REPORT_VARIABLES = true;
+    doTest();
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index 65092f2..e579fbb 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -32,6 +32,7 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.testFramework.LightVirtualFile;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.testFramework.PsiTestUtil;
 import com.intellij.testFramework.fixtures.TempDirTestFixture;
@@ -434,5 +435,116 @@
     }
   }
 
+  public void testFindInCommentsAndLiterals() throws Exception{
+    FindManager findManager = FindManager.getInstance(myProject);
 
+    FindModel findModel = new FindModel();
+    findModel.setStringToFind("done");
+    findModel.setWholeWordsOnly(false);
+    findModel.setFromCursor(false);
+    findModel.setGlobal(true);
+    findModel.setMultipleFiles(false);
+    findModel.setProjectScope(true);
+
+    String text = "\"done done done\" /* done done done */";
+
+    runFindInCommentsAndLiterals(findManager, findModel, text);
+
+    findModel.setRegularExpressions(true);
+    runFindInCommentsAndLiterals(findManager, findModel, text);
+  }
+
+  private static void runFindInCommentsAndLiterals(FindManager findManager, FindModel findModel, String text) {
+    runFindInCommentsAndLiterals(findManager, findModel, text, "java");
+  }
+
+  private static void runFindInCommentsAndLiterals(FindManager findManager,
+                                                   FindModel findModel,
+                                                   String text,
+                                                   String ext) {
+    findModel.setInStringLiteralsOnly(true);
+    findModel.setInCommentsOnly(false);
+    runFindForwardAndBackward(findManager, findModel, text, ext);
+
+    findModel.setInStringLiteralsOnly(false);
+    findModel.setInCommentsOnly(true);
+    runFindForwardAndBackward(findManager, findModel, text, ext);
+  }
+
+  private static void runFindForwardAndBackward(FindManager findManager, FindModel findModel, String text) {
+    runFindForwardAndBackward(findManager, findModel, text, "java");
+  }
+
+  private static void runFindForwardAndBackward(FindManager findManager, FindModel findModel, String text, String ext) {
+    findModel.setForward(true);
+    LightVirtualFile file = new LightVirtualFile("A."+ext, text);
+    int prevousOffset;
+
+    FindResult findResult = findManager.findString(text, 0, findModel, file);
+    assertTrue(findResult.isStringFound());
+    prevousOffset = findResult.getStartOffset();
+
+    findResult = findManager.findString(text, findResult.getEndOffset(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prevousOffset);
+    prevousOffset = findResult.getStartOffset();
+
+    findResult = findManager.findString(text, findResult.getEndOffset(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(findResult.getStartOffset() > prevousOffset);
+
+    findModel.setForward(false);
+
+    findResult = findManager.findString(text, text.length(), findModel, file);
+    assertTrue(findResult.isStringFound());
+    prevousOffset = findResult.getStartOffset();
+
+    findResult = findManager.findString(text, prevousOffset, findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(prevousOffset > findResult.getStartOffset() );
+
+    prevousOffset = findResult.getStartOffset();
+
+    findResult = findManager.findString(text, prevousOffset, findModel, file);
+    assertTrue(findResult.isStringFound());
+    assertTrue(prevousOffset > findResult.getStartOffset() );
+  }
+
+  public void testFindInJavaDocs() throws Exception{
+    FindManager findManager = FindManager.getInstance(myProject);
+
+    FindModel findModel = new FindModel();
+    findModel.setStringToFind("done");
+    findModel.setWholeWordsOnly(false);
+    findModel.setFromCursor(false);
+    findModel.setGlobal(true);
+    findModel.setMultipleFiles(false);
+    findModel.setProjectScope(true);
+
+    String text = "/** done done done */";
+
+    findModel.setInCommentsOnly(true);
+    runFindForwardAndBackward(findManager, findModel, text);
+
+    findModel.setRegularExpressions(true);
+    runFindForwardAndBackward(findManager, findModel, text);
+  }
+
+  public void testFindInUserFileType() throws Exception{
+    FindManager findManager = FindManager.getInstance(myProject);
+
+    FindModel findModel = new FindModel();
+    findModel.setStringToFind("done");
+    findModel.setWholeWordsOnly(false);
+    findModel.setFromCursor(false);
+    findModel.setGlobal(true);
+    findModel.setMultipleFiles(false);
+    findModel.setProjectScope(true);
+
+    String text = "\"done done\"; 'done'; // done\n" +
+                  "/* done\n" +
+                  "done */";
+
+    runFindInCommentsAndLiterals(findManager, findModel, text, "cs");
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
index 0217607..a7deee8 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
@@ -40,7 +40,7 @@
   public void testMethodReceiver() { doTest(); }
   public void testPackageInfo() { doTest("package-info"); }
   public void testEA40568() { doTest(); }
-  public void testBooleans() { doTest(); }
+  public void testPrimitives() { doTest(); }
   public void testClassRefs() { doTest(); }
   public void testEA46236() { doTest("ValuedEnum"); }
 
diff --git a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java
index 1cd630c..5c12aff 100644
--- a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java
@@ -22,26 +22,35 @@
 import com.intellij.testFramework.PsiTestCase;
 import com.intellij.testFramework.PsiTestUtil;
 
+import java.util.LinkedList;
+import java.util.Queue;
+
 
 public class CoreJavaFileManagerTest extends PsiTestCase {
 
-  public void testNotNullInnerClass() throws Exception {
+  private VirtualFile prepareClasses(String clazzName, String clazzData) throws Exception {
     VirtualFile root = PsiTestUtil.createTestProjectStructure(myProject, myModule, myFilesToDelete);
     VirtualFile pkg = root.createChildDirectory(this, "foo");
     PsiDirectory dir = myPsiManager.findDirectory(pkg);
     assertNotNull(dir);
+    dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText(clazzName + ".java", JavaFileType.INSTANCE, clazzData));
+    return root;
+  }
+
+  public void testNotNullInnerClass() throws Exception {
     String text = "package foo;\n\n" +
                   "public class Nested {\n" +
                   "public class InnerGeneral {}\n" +
-                  "public class Inner$ {}\n" +
+                  "public class Inner$ {" +
+                  "}\n" +
                   "\n" +
                   "public Inner$ inner() {\n" +
                   "   return  new Inner$();\n" +
                   "}\n" +
                   "\n" +
                   "}";
-    PsiElement created = dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText("Nested.java", JavaFileType.INSTANCE, text));
 
+    VirtualFile root = prepareClasses("Nested", text);
     GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
     CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
     manager.addToClasspath(root);
@@ -65,4 +74,90 @@
     assertNull(clazzInner$Wrong3);
   }
 
+
+  public void testNotNullInnerClass2() throws Exception {
+    String text = "package foo;\n\n" +
+                  "public class Nested {\n" +
+
+                  "public class Inner {" +
+                  "   public class XInner{}" +
+                  "   public class XInner${}" +
+                  "}\n" +
+                  "public class Inner$ {" +
+                  "   public class XInner{}" +
+                  "   public class XInner${}" +
+                  "}\n" +
+                  "\n" +
+                  "}";
+
+    VirtualFile root = prepareClasses("Nested", text);
+    GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
+    CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
+    manager.addToClasspath(root);
+
+    PsiClass clazzInner = manager.findClass("foo.Nested.Inner", scope);
+    assertNotNull(clazzInner);
+
+    PsiClass clazzXInner = manager.findClass("foo.Nested.Inner.XInner", scope);
+    assertNotNull(clazzXInner);
+
+    PsiClass clazzXInner$ = manager.findClass("foo.Nested.Inner.XInner$", scope);
+    assertNotNull(clazzXInner$);
+
+    PsiClass clazz$XInner = manager.findClass("foo.Nested.Inner$.XInner", scope);
+    assertNotNull(clazz$XInner);
+
+    PsiClass clazz$XInner$ = manager.findClass("foo.Nested.Inner$.XInner$", scope);
+    assertNotNull(clazz$XInner$);
+  }
+
+
+  public void testNotNullInnerClass3() throws Exception {
+    String text = "package foo;\n\n" +
+                  "public class NestedX {\n" +
+
+                  "public class XX {" +
+                  "   public class XXX{" +
+                  "     public class XXXX{ }" +
+                  "     public class XXXX${ }" +
+                  "   }" +
+                  "   public class XXX${" +
+                  "     public class XXXX{ }" +
+                  "     public class XXXX${ }" +
+                  "   }" +
+                  "}\n" +
+                  "public class XX$ {" +
+                  "   public class XXX{" +
+                  "     public class XXXX{ }" +
+                  "     public class XXXX${ }" +
+                  "   }" +
+                  "   public class XXX${" +
+                  "     public class XXXX{ }" +
+                  "     public class XXXX${ }" +
+                  "   }" +
+                  "}\n" +
+                  "\n" +
+                  "}";
+
+    VirtualFile root = prepareClasses("NestedX", text);
+    GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
+    CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager);
+    manager.addToClasspath(root);
+
+    Queue<String> queue = new LinkedList<String>();
+    queue.add("foo.NestedX");
+
+    while(!queue.isEmpty()) {
+      String head = queue.remove();
+      PsiClass clazzInner = manager.findClass(head, scope);
+      assertNotNull(head, clazzInner);      
+      String lastSegment = head.substring(head.lastIndexOf('.'));
+      String xs = lastSegment.substring(lastSegment.indexOf("X")).replace("$", "");
+      if (xs.length() < 4) {
+        queue.add(head + "." + xs + "X");
+        queue.add(head + "." + xs + "X$");
+      }
+    }
+  }
+
 }
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
index b566465..0700225 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
@@ -547,6 +547,10 @@
     doTest();
   }
 
+  public void testFromLambdaBody1() throws Exception {
+    doTest();
+  }
+
   public void testOneLineLambda() throws Exception {
     doTest();
   }
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
index 236ac1a..1755770 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
@@ -30,6 +30,15 @@
 
   public void testInnerClasses() throws Exception {doTest();}
   public void testAnonymousClasses() throws Exception {doTest();}
+  public void testMethodRefs() throws Exception {
+    try {
+      doTest();
+      fail("Conflict expected.");
+    }
+    catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
+      assertEquals("Method is used in method reference expression", e.getMessage());
+    }
+  }
 
   private void doTest() throws Exception {
     configureByFile(TEST_ROOT + getTestName(true) + ".java");
diff --git a/java/java-tests/testSrc/com/intellij/roots/ManagingContentRootsTest.java b/java/java-tests/testSrc/com/intellij/roots/ManagingContentRootsTest.java
index b0ed71e..d6468e3 100644
--- a/java/java-tests/testSrc/com/intellij/roots/ManagingContentRootsTest.java
+++ b/java/java-tests/testSrc/com/intellij/roots/ManagingContentRootsTest.java
@@ -83,7 +83,7 @@
     assertEquals(root, findContentEntry(url).getFile());
   }
 
-  public void testGettingMofifiableModelCorrectlySetsRootModelForContentEntries() throws Exception {
+  public void testGettingModifiableModelCorrectlySetsRootModelForContentEntries() {
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
diff --git a/java/openapi/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/openapi/src/com/intellij/codeInsight/intention/QuickFixFactory.java
index 5dca4c34..b422156 100644
--- a/java/openapi/src/com/intellij/codeInsight/intention/QuickFixFactory.java
+++ b/java/openapi/src/com/intellij/codeInsight/intention/QuickFixFactory.java
@@ -31,38 +31,53 @@
     return ServiceManager.getService(QuickFixFactory.class);
   }
 
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierList modifierList,
                                                                                     @PsiModifier.ModifierConstant @NotNull String modifier,
                                                                                     boolean shouldHave,
                                                                                     final boolean showContainingClass);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierListOwner owner,
                                                                                     @PsiModifier.ModifierConstant @NotNull String modifier,
                                                                                     boolean shouldHave,
                                                                                     final boolean showContainingClass);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createMethodReturnFix(@NotNull PsiMethod method, @NotNull PsiType toReturn, boolean fixWholeHierarchy);
-
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddMethodFix(@NotNull PsiMethod method, @NotNull PsiClass toClass);
-  public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddMethodFix(@NotNull String methodText, @NotNull PsiClass toClass, String... exceptions);
+  @NotNull
+  public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddMethodFix(@NotNull String methodText, @NotNull PsiClass toClass, @NotNull String... exceptions);
 
   /**
    * @param psiElement psiClass or enum constant without class initializer
    */
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createImplementMethodsFix(@NotNull PsiElement psiElement);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createImplementMethodsFix(@NotNull PsiClass psiElement);
+  @NotNull
   public abstract LocalQuickFixOnPsiElement createMethodThrowsFix(@NotNull PsiMethod method, @NotNull PsiClassType exceptionClass, boolean shouldThrow, boolean showContainingClass);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddDefaultConstructorFix(@NotNull PsiClass aClass);
   @Nullable
-  public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddConstructorFix(@NotNull PsiClass aClass, @PsiModifier.ModifierConstant String modifier);
+  public abstract LocalQuickFixAndIntentionActionOnPsiElement createAddConstructorFix(@NotNull PsiClass aClass, @PsiModifier.ModifierConstant @NotNull String modifier);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createMethodParameterTypeFix(@NotNull PsiMethod method, int index, @NotNull PsiType newType, boolean fixWholeHierarchy);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createMakeClassInterfaceFix(@NotNull PsiClass aClass);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createMakeClassInterfaceFix(@NotNull PsiClass aClass, final boolean makeInterface);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createExtendsListFix(@NotNull PsiClass aClass, @NotNull PsiClassType typeToExtendFrom, boolean toAdd);
+  @NotNull
   public abstract LocalQuickFixAndIntentionActionOnPsiElement createRemoveUnusedParameterFix(@NotNull PsiParameter parameter);
+  @NotNull
   public abstract IntentionAction createRemoveUnusedVariableFix(@NotNull PsiVariable variable);
 
   @Nullable
   public abstract IntentionAction createCreateClassOrPackageFix(@NotNull PsiElement context, @NotNull String qualifiedName, final boolean createClass, final String superClass);
   @Nullable
   public abstract IntentionAction createCreateClassOrInterfaceFix(@NotNull PsiElement context, @NotNull String qualifiedName, final boolean createClass, final String superClass);
-  public abstract IntentionAction createCreateFieldOrPropertyFix(final PsiClass aClass, final String name, final PsiType type, final PropertyMemberType targetMember, final PsiAnnotation... annotations);
+  @NotNull
+  public abstract IntentionAction createCreateFieldOrPropertyFix(@NotNull PsiClass aClass, @NotNull String name, @NotNull PsiType type, @NotNull PropertyMemberType targetMember, @NotNull PsiAnnotation... annotations);
 }
diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java
index 88a5c55..51ae01f 100644
--- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java
+++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java
@@ -25,7 +25,7 @@
 import java.io.File;
 
 public abstract class JavaSdk extends SdkType implements JavaSdkType, ApplicationComponent {
-  public JavaSdk(@NonNls String name) {
+  public JavaSdk(@NotNull @NonNls String name) {
     super(name);
   }
 
diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
index cfd68e9..03ec968 100644
--- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
@@ -139,11 +139,11 @@
     return configureByFile(vFile, projectFile);
   }
 
-  protected PsiFile configureByText(final FileType fileType, @NonNls final String text) throws Exception {
+  protected PsiFile configureByText(@NotNull FileType fileType, @NonNls final String text) throws Exception {
     return configureByText(fileType, text, null);
   }
 
-  protected PsiFile configureByText(final FileType fileType, @NonNls final String text, @Nullable String _extension) throws Exception {
+  protected PsiFile configureByText(@NotNull final FileType fileType, @NonNls final String text, @Nullable String _extension) throws Exception {
     final String extension = _extension == null ? fileType.getDefaultExtension():_extension;
 
     File dir = createTempDirectory();
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
index 83b1ce2..fdc84ab 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
@@ -16,6 +16,8 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
+import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.asm4.Opcodes;
@@ -235,7 +237,7 @@
     this.myContext = context;
     myFileName = fn;
     mySuperClass = TypeRepr.createClassType(context, sup);
-    myInterfaces = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, i, new HashSet<TypeRepr.AbstractType>());
+    myInterfaces = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, i, new THashSet<TypeRepr.AbstractType>(1));
     myFields = f;
     myMethods = m;
     this.myAnnotationTargets = targets;
@@ -250,41 +252,45 @@
     super(in);
     try {
       this.myContext = context;
-      myFileName = in.readInt();
+      myFileName = DataInputOutputUtil.readINT(in);
       mySuperClass = (TypeRepr.ClassType)TypeRepr.externalizer(context).read(in);
-      myInterfaces = (Set<TypeRepr.AbstractType>)RW.read(TypeRepr.externalizer(context), new HashSet<TypeRepr.AbstractType>(), in);
-      myFields = (Set<FieldRepr>)RW.read(FieldRepr.externalizer(context), new HashSet<FieldRepr>(), in);
-      myMethods = (Set<MethodRepr>)RW.read(MethodRepr.externalizer(context), new HashSet<MethodRepr>(), in);
+      myInterfaces = (Set<TypeRepr.AbstractType>)RW.read(TypeRepr.externalizer(context), new THashSet<TypeRepr.AbstractType>(1), in);
+      myFields = (Set<FieldRepr>)RW.read(FieldRepr.externalizer(context), new THashSet<FieldRepr>(), in);
+      myMethods = (Set<MethodRepr>)RW.read(MethodRepr.externalizer(context), new THashSet<MethodRepr>(), in);
       myAnnotationTargets = (Set<ElemType>)RW.read(UsageRepr.AnnotationUsage.elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
 
-      final String s = in.readUTF();
+      final String s = RW.readUTF(in);
 
       myRetentionPolicy = s.length() == 0 ? null : RetentionPolicy.valueOf(s);
 
-      myOuterClassName = in.readInt();
-      myIsLocal = in.readBoolean();
-      myIsAnonymous = in.readBoolean();
-      myUsages =(Set<UsageRepr.Usage>)RW.read(UsageRepr.externalizer(context), new HashSet<UsageRepr.Usage>(), in);
+      myOuterClassName = DataInputOutputUtil.readINT(in);
+      int flags = DataInputOutputUtil.readINT(in);
+      myIsLocal = (flags & LOCAL_MASK) != 0;
+      myIsAnonymous = (flags & ANONYMOUS_MASK) != 0;
+      myUsages =(Set<UsageRepr.Usage>)RW.read(UsageRepr.externalizer(context), new THashSet<UsageRepr.Usage>(), in);
     }
     catch (IOException e) {
       throw new RuntimeException(e);
     }
   }
 
+  private static final int LOCAL_MASK = 1;
+  private static final int ANONYMOUS_MASK = 2;
+
   @Override
   public void save(final DataOutput out) {
     try {
       super.save(out);
-      out.writeInt(myFileName);
+      DataInputOutputUtil.writeINT(out, myFileName);
       mySuperClass.save(out);
       RW.save(myInterfaces, out);
       RW.save(myFields, out);
       RW.save(myMethods, out);
       RW.save(myAnnotationTargets, UsageRepr.AnnotationUsage.elementTypeExternalizer, out);
-      out.writeUTF(myRetentionPolicy == null ? "" : myRetentionPolicy.toString());
-      out.writeInt(myOuterClassName);
-      out.writeBoolean(myIsLocal);
-      out.writeBoolean(myIsAnonymous);
+      RW.writeUTF(out, myRetentionPolicy == null ? "" : myRetentionPolicy.toString());
+      DataInputOutputUtil.writeINT(out, myOuterClassName);
+      DataInputOutputUtil.writeINT(out, (myIsLocal ? LOCAL_MASK:0) | (myIsAnonymous ? ANONYMOUS_MASK : 0));
+
       RW.save(myUsages, UsageRepr.externalizer(myContext), out);
     }
     catch (IOException e) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java
index ebcb39a..98dffab 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java
@@ -16,6 +16,8 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.openapi.util.Pair;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.asm4.*;
 import org.jetbrains.asm4.signature.SignatureReader;
@@ -302,14 +304,14 @@
       myAnonymousClassFlag.set(false);
     }
 
-    private final Set<MethodRepr> myMethods = new HashSet<MethodRepr>();
-    private final Set<FieldRepr> myFields = new HashSet<FieldRepr>();
-    private final Set<UsageRepr.Usage> myUsages = new HashSet<UsageRepr.Usage>();
+    private final Set<MethodRepr> myMethods = new THashSet<MethodRepr>();
+    private final Set<FieldRepr> myFields = new THashSet<FieldRepr>();
+    private final Set<UsageRepr.Usage> myUsages = new THashSet<UsageRepr.Usage>();
     private final Set<ElemType> myTargets = EnumSet.noneOf(ElemType.class);
     private RetentionPolicy myRetentionPolicy = null;
 
-    final Map<TypeRepr.ClassType, TIntHashSet> myAnnotationArguments = new HashMap<TypeRepr.ClassType, TIntHashSet>();
-    final Map<TypeRepr.ClassType, Set<ElemType>> myAnnotationTargets = new HashMap<TypeRepr.ClassType, Set<ElemType>>();
+    final Map<TypeRepr.ClassType, TIntHashSet> myAnnotationArguments = new THashMap<TypeRepr.ClassType, TIntHashSet>();
+    final Map<TypeRepr.ClassType, Set<ElemType>> myAnnotationTargets = new THashMap<TypeRepr.ClassType, Set<ElemType>>();
 
     public ClassCrawler(final int fn) {
       super(Opcodes.ASM4);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java
deleted file mode 100644
index 3488352..0000000
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMaplet.java
+++ /dev/null
@@ -1,164 +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.java.dependencyView;
-
-import com.intellij.util.Processor;
-import com.intellij.util.containers.SLRUCache;
-import com.intellij.util.io.DataExternalizer;
-import com.intellij.util.io.KeyDescriptor;
-import com.intellij.util.io.PersistentHashMap;
-import gnu.trove.TIntIntProcedure;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * @author: db
- * Date: 05.11.11
- */
-public class IntIntPersistentMaplet extends IntIntMaplet {
-  private static final Object NULL_OBJ = new Object();
-  private static final int CACHE_SIZE = 512;
-  private final PersistentHashMap<Integer, Integer> myMap;
-  private final SLRUCache<Integer, Object> myCache;
-
-  public IntIntPersistentMaplet(final File file, final KeyDescriptor<Integer> k) {
-    try {
-      myMap = new PersistentHashMap<Integer, Integer>(file, k, new DataExternalizer<Integer>() {
-        @Override
-        public void save(DataOutput out, Integer value) throws IOException {
-          out.writeInt(value);
-        }
-
-        @Override
-        public Integer read(DataInput in) throws IOException {
-          return in.readInt();
-        }
-      });
-      myCache = new SLRUCache<Integer, Object>(CACHE_SIZE, CACHE_SIZE) {
-        @NotNull
-        @Override
-        public Object createValue(Integer key) {
-          try {
-            final Integer v1 = myMap.get(key);
-            return v1 == null? NULL_OBJ : v1;
-          }
-          catch (IOException e) {
-            throw new RuntimeException(e);
-          }
-        }
-      };
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  @Override
-  public boolean containsKey(final int key) {
-    try {
-      return myMap.containsMapping(key);
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  @Override
-  public int get(final int key) {
-    final Object obj = myCache.get(key);
-    return obj == NULL_OBJ? 0 : (Integer)obj;
-  }
-
-  @Override
-  public void put(final int key, final int value) {
-    try {
-      myCache.remove(key);
-      myMap.put(key, value);
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  @Override
-  public void putAll(final IntIntMaplet m) {
-    m.forEachEntry(new TIntIntProcedure() {
-      @Override
-      public boolean execute(int key, int value) {
-        put(key, value);
-        return true;
-      }
-    });
-  }
-
-  @Override
-  public void remove(final int key) {
-    try {
-      myCache.remove(key);
-      myMap.remove(key);
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  @Override
-  public void close() {
-    try {
-      myCache.clear();
-      myMap.close();
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  public void flush(boolean memoryCachesOnly) {
-    if (memoryCachesOnly) {
-      if (myMap.isDirty()) {
-        myMap.dropMemoryCaches();
-      }
-    }
-    else {
-      myMap.force();
-    }
-  }
-
-  @Override
-  public void forEachEntry(final TIntIntProcedure proc) {
-    try {
-      myMap.processKeysWithExistingMapping(new Processor<Integer>() {
-        @Override
-        public boolean process(Integer key) {
-          try {
-            final Integer value = myMap.get(key);
-            return value == null? proc.execute(key, -1) : proc.execute(key, value);
-          }
-          catch (IOException e) {
-            throw new RuntimeException(e);
-          }
-        }
-      });
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
index 1d724cf..f37ce8f 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
@@ -19,6 +19,7 @@
 import com.intellij.util.Processor;
 import com.intellij.util.containers.SLRUCache;
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
 import com.intellij.util.io.KeyDescriptor;
 import com.intellij.util.io.PersistentHashMap;
 import gnu.trove.TIntHashSet;
@@ -98,7 +99,7 @@
             @Override
             public boolean execute(int value) {
               try {
-                out.writeInt(value);
+                DataInputOutputUtil.writeINT(out, value);
               }
               catch (IOException e) {
                 exRef.set(e);
@@ -125,7 +126,7 @@
       myCache.remove(key);
       myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
         public void append(final DataOutput out) throws IOException {
-          out.writeInt(value);
+          DataInputOutputUtil.writeINT(out, value);
         }
       });
     }
@@ -260,7 +261,7 @@
         @Override
         public boolean execute(int elem) {
           try {
-            out.writeInt(elem);
+            DataInputOutputUtil.writeINT(out, elem);
           }
           catch (IOException e) {
             exRef.set(e);
@@ -280,7 +281,7 @@
       final TIntHashSet result = new TIntHashSet();
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
-        result.add(in.readInt());
+        result.add(DataInputOutputUtil.readINT(in));
       }
       return result;
     }
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 f81f6c1..346b65b 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
@@ -52,7 +52,8 @@
   private static final float DEFAULT_SET_LOAD_FACTOR = 0.98f;
   private static final CollectionFactory<ClassRepr> ourClassSetConstructor = new CollectionFactory<ClassRepr>() {
     public Set<ClassRepr> create() {
-      return new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+      // for IDEA codebase on average there is no more than 2.5 classes out of one source file, so we use smaller estimate
+      return new THashSet<ClassRepr>(5, DEFAULT_SET_LOAD_FACTOR);
     }
   };
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
index 62d8118..b358e11 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
@@ -16,16 +16,15 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
+import gnu.trove.THashSet;
 import org.jetbrains.asm4.Type;
 
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author: db
@@ -127,7 +126,9 @@
                     final String[] e,
                     final Object value) {
     super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value);
-    myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, new HashSet<TypeRepr.AbstractType>());
+    Set<TypeRepr.AbstractType> typeCollection =
+      e != null ? new THashSet<TypeRepr.AbstractType>(e.length) : Collections.<TypeRepr.AbstractType>emptySet();
+    myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, typeCollection);
     myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d));
   }
 
@@ -135,9 +136,9 @@
     super(context, in);
     try {
       final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
-      final int size = in.readInt();
+      final int size = DataInputOutputUtil.readINT(in);
       myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[size]);
-      myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new HashSet<TypeRepr.AbstractType>(), in);
+      myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new THashSet<TypeRepr.AbstractType>(0), in);
     }
     catch (IOException e) {
       throw new RuntimeException(e);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
index 593128e..62e0ebf 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.jps.builders.java.dependencyView;
 
+import com.intellij.util.io.DataInputOutputUtil;
 import org.jetbrains.asm4.Opcodes;
 
 import java.io.DataInput;
@@ -39,9 +40,9 @@
 
   protected Proto(final DataInput in) {
     try {
-      access = in.readInt();
-      signature = in.readInt();
-      name = in.readInt();
+      access = DataInputOutputUtil.readINT(in);
+      signature = DataInputOutputUtil.readINT(in);
+      name = DataInputOutputUtil.readINT(in);
     }
     catch (IOException e) {
       throw new RuntimeException(e);
@@ -51,9 +52,9 @@
   @Override
   public void save(final DataOutput out) {
     try {
-      out.writeInt(access);
-      out.writeInt(signature);
-      out.writeInt(name);
+      DataInputOutputUtil.writeINT(out, access);
+      DataInputOutputUtil.writeINT(out, signature);
+      DataInputOutputUtil.writeINT(out, name);
     }
     catch (IOException e) {
       throw new RuntimeException(e);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
index ff430e0..fb3cb47 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.jps.builders.java.dependencyView;
 
+import com.intellij.util.io.DataInputOutputUtil;
 import org.jetbrains.asm4.Type;
 
 import java.io.DataInput;
@@ -52,11 +53,11 @@
     try {
       switch (in.readByte()) {
         case STRING:
-          return in.readUTF();
+          return RW.readUTF(in);
         case NONE:
           return null;
         case INTEGER:
-          return in.readInt();
+          return DataInputOutputUtil.readINT(in);
         case LONG:
           return in.readLong();
         case FLOAT:
@@ -64,7 +65,7 @@
         case DOUBLE:
           return in.readDouble();
         case TYPE :
-          return Type.getType(in.readUTF());
+          return Type.getType(RW.readUTF(in));
       }
     }
     catch (IOException e) {
@@ -94,11 +95,12 @@
     try {
       if (myValue instanceof String) {
         out.writeByte(STRING);
-        out.writeUTF((String)myValue);
+        String value = (String)myValue;
+        RW.writeUTF(out, value);
       }
       else if (myValue instanceof Integer) {
         out.writeByte(INTEGER);
-        out.writeInt(((Integer)myValue).intValue());
+        DataInputOutputUtil.writeINT(out, ((Integer)myValue).intValue());
       }
       else if (myValue instanceof Long) {
         out.writeByte(LONG);
@@ -114,7 +116,7 @@
       }
       else if (myValue instanceof Type) {
         out.writeByte(TYPE);
-        out.writeUTF(((Type)myValue).getDescriptor());
+        RW.writeUTF(out, ((Type)myValue).getDescriptor());
       }
       else {
         out.writeByte(NONE);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
index 4387181..f9d32b0 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
@@ -16,6 +16,8 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
+import com.intellij.util.io.IOUtil;
 import gnu.trove.TIntHashSet;
 import gnu.trove.TIntProcedure;
 
@@ -27,17 +29,31 @@
  * Date: 29.01.11
  */
 public class RW {
+  private static final byte[] ourStringBuffer = IOUtil.allocReadWriteUTFBuffer();
+
   private RW() {
 
   }
 
+  protected static String readUTF(DataInput in) throws IOException {
+    synchronized (ourStringBuffer) {
+      return IOUtil.readUTFFast(ourStringBuffer, in);
+    }
+  }
+
+  protected static void writeUTF(DataOutput out, String value) throws IOException {
+    synchronized (ourStringBuffer) {
+      IOUtil.writeUTFFast(ourStringBuffer, out, value);
+    }
+  }
+
   public interface Savable {
     void save(DataOutput out);
   }
 
   public static <X extends Savable> void save(final X[] x, final DataOutput out) {
     try {
-      out.writeInt(x.length);
+      DataInputOutputUtil.writeINT(out, x.length);
       for (Savable s : x) {
         s.save(out);
       }
@@ -49,12 +65,12 @@
 
   public static <X> void save(final TIntHashSet x, final DataOutput out) {
     try {
-      out.writeInt(x.size());
+      DataInputOutputUtil.writeINT(out, x.size());
       x.forEach(new TIntProcedure() {
         @Override
         public boolean execute(int value) {
           try {
-            out.writeInt(value);
+            DataInputOutputUtil.writeINT(out, value);
             return true;
           }
           catch (IOException e) {
@@ -70,7 +86,7 @@
 
   public static <X> void save(final Collection<X> x, final DataExternalizer<X> e, final DataOutput out) {
     try {
-      out.writeInt(x.size());
+      DataInputOutputUtil.writeINT(out, x.size());
 
       for (X y : x) {
         e.save(out, y);
@@ -85,7 +101,7 @@
     try {
       final int size = x.size();
 
-      out.writeInt(size);
+      DataInputOutputUtil.writeINT(out, size);
 
       for (X s : x) {
         s.save(out);
@@ -111,10 +127,10 @@
 
   public static TIntHashSet read(final TIntHashSet acc, final DataInput in) {
     try {
-      final int size = in.readInt();
+      final int size = DataInputOutputUtil.readINT(in);
 
       for (int i = 0; i<size; i++) {
-        acc.add(in.readInt());
+        acc.add(DataInputOutputUtil.readINT(in));
       }
 
       return acc;
@@ -126,7 +142,7 @@
 
   public static <X> Collection<X> read(final DataExternalizer<X> e, final Collection<X> acc, final DataInput in) {
     try {
-      final int size = in.readInt();
+      final int size = DataInputOutputUtil.readINT(in);
 
       for (int i = 0; i<size; i++) {
         acc.add(e.read(in));
@@ -143,32 +159,6 @@
     void write(BufferedWriter w);
   }
 
-  public static <T extends Comparable> void writeln(final BufferedWriter w, final Collection<T> c, final ToWritable<T> t) {
-    if (c == null) {
-      writeln(w, "0");
-      return;
-    }
-
-    writeln(w, Integer.toString(c.size()));
-
-    for (T e : c) {
-      t.convert(e).write(w);
-    }
-  }
-
-  public static void writeln(final BufferedWriter w, final Collection<? extends Writable> c) {
-    if (c == null) {
-      writeln(w, "0");
-      return;
-    }
-
-    writeln(w, Integer.toString(c.size()));
-
-    for (Writable e : c) {
-      e.write(w);
-    }
-  }
-
   public interface ToWritable<T> {
     Writable convert(T x);
   }
@@ -202,51 +192,6 @@
     }
   };
 
-  public static Reader<String> myStringReader = new Reader<String>() {
-    public String read(final BufferedReader r) {
-      try {
-        return r.readLine();
-      }
-      catch (IOException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  };
-
-  public static <T> Collection<T> readMany(final BufferedReader r, final Reader<T> c, final Collection<T> acc) {
-    final int size = readInt(r);
-
-    for (int i = 0; i < size; i++) {
-      acc.add(c.read(r));
-    }
-
-    return acc;
-  }
-
-  public static String lookString(final BufferedReader r) {
-    try {
-      r.mark(256);
-      final String s = r.readLine();
-      r.reset();
-
-      return s;
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  public static void readTag(final BufferedReader r, final String tag) {
-    try {
-      final String s = r.readLine();
-
-      if (!s.equals(tag)) System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   public static String readString(final BufferedReader r) {
     try {
       return r.readLine();
@@ -267,31 +212,4 @@
       return 0;
     }
   }
-
-  public static int readInt(final BufferedReader r) {
-    final String s = readString(r);
-
-    try {
-      return Integer.parseInt(s);
-    }
-    catch (Exception n) {
-      System.err.println("Parsing error: expected integer, but found \"" + s + "\"");
-      return 0;
-    }
-  }
-
-  public static String readStringAttribute(final BufferedReader r, final String tag) {
-    try {
-      final String s = r.readLine();
-
-      if (s.startsWith(tag)) return s.substring(tag.length());
-
-      System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
-
-      return null;
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
 }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
index 3a9fb53..b341eae 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
 import org.jetbrains.asm4.Type;
 
 import java.io.DataInput;
@@ -64,7 +65,7 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(PRIMITIVE_TYPE);
-        out.writeInt(type);
+        DataInputOutputUtil.writeINT(out, type);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -77,7 +78,7 @@
 
     PrimitiveType(final DataInput in) {
       try {
-        type = in.readInt();
+        type = DataInputOutputUtil.readINT(in);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -175,8 +176,8 @@
 
     ClassType(final DependencyContext context, final DataInput in) {
       try {
-        className = in.readInt();
-        final int size = in.readInt();
+        className = DataInputOutputUtil.readINT(in);
+        final int size = DataInputOutputUtil.readINT(in);
         if (size == 0) {
           typeArgs = EMPTY_TYPE_ARRAY;
         }
@@ -217,8 +218,8 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(CLASS_TYPE);
-        out.writeInt(className);
-        out.writeInt(typeArgs.length);
+        DataInputOutputUtil.writeINT(out, className);
+        DataInputOutputUtil.writeINT(out, typeArgs.length);
         for (AbstractType t : typeArgs) {
           t.save(out);
         }
@@ -241,18 +242,6 @@
     return acc;
   }
 
-  public static Collection<AbstractType> createClassType(final DependencyContext context,
-                                                         final Collection<String> args,
-                                                         final Collection<AbstractType> acc) {
-    if (args != null) {
-      for (String a : args) {
-        acc.add(createClassType(context, context.get(a)));
-      }
-    }
-
-    return acc;
-  }
-
   public static ClassType createClassType(final DependencyContext context, final int s) {
     return (ClassType)context.getType(new ClassType(s));
   }
@@ -277,6 +266,7 @@
   }
 
   public static AbstractType[] getType(final DependencyContext context, final Type[] t) {
+    if(t.length == 0) return AbstractType.EMPTY_TYPE_ARRAY;
     final AbstractType[] r = new AbstractType[t.length];
 
     for (int i = 0; i < r.length; i++) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
index abe9df3..f5201a7 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
@@ -16,6 +16,7 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.DataInputOutputUtil;
 import gnu.trove.TIntHashSet;
 import gnu.trove.TIntProcedure;
 import org.jetbrains.asm4.Type;
@@ -77,8 +78,8 @@
 
     private FMUsage(final DataInput in) {
       try {
-        myName = in.readInt();
-        myOwner = in.readInt();
+        myName = DataInputOutputUtil.readINT(in);
+        myOwner = DataInputOutputUtil.readINT(in);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -88,8 +89,8 @@
     protected final void save(final byte tag, final DataOutput out) {
       try {
         out.writeByte(tag);
-        out.writeInt(myName);
-        out.writeInt(myOwner);
+        DataInputOutputUtil.writeINT(out, myName);
+        DataInputOutputUtil.writeINT(out, myOwner);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -215,7 +216,8 @@
       super(in);
       try {
         final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
-        myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[in.readInt()]);
+        int argumentTypes = DataInputOutputUtil.readINT(in);
+        myArgumentTypes = RW.read(externalizer, in, argumentTypes != 0 ? new TypeRepr.AbstractType[argumentTypes]: TypeRepr.AbstractType.EMPTY_TYPE_ARRAY);
         myReturnType = externalizer.read(in);
       }
       catch (IOException e) {
@@ -284,7 +286,7 @@
     public MetaMethodUsage(final DataInput in) {
       super(in);
       try {
-        myArity = in.readInt();
+        myArity = DataInputOutputUtil.readINT(in);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -295,7 +297,7 @@
     public void save(final DataOutput out) {
       save(METAMETHOD_USAGE, out);
       try {
-        out.writeInt(myArity);
+        DataInputOutputUtil.writeINT(out, myArity);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -348,7 +350,7 @@
 
     private ClassUsage(final DataInput in) {
       try {
-        myClassName = in.readInt();
+        myClassName = DataInputOutputUtil.readINT(in);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -359,7 +361,7 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(CLASS_USAGE);
-        out.writeInt(myClassName);
+        DataInputOutputUtil.writeINT(out, myClassName);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -405,7 +407,7 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(CLASS_AS_GENERIC_BOUND_USAGE);
-        out.writeInt(myClassName);
+        DataInputOutputUtil.writeINT(out, myClassName);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -427,7 +429,7 @@
 
     private ClassExtendsUsage(final DataInput in) {
       try {
-        myClassName = in.readInt();
+        myClassName = DataInputOutputUtil.readINT(in);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -438,7 +440,7 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(CLASS_EXTENDS_USAGE);
-        out.writeInt(myClassName);
+        DataInputOutputUtil.writeINT(out, myClassName);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -481,7 +483,7 @@
     public void save(final DataOutput out) {
       try {
         out.writeByte(CLASS_NEW_USAGE);
-        out.writeInt(myClassName);
+        DataInputOutputUtil.writeINT(out, myClassName);
       }
       catch (IOException e) {
         throw new RuntimeException(e);
@@ -503,12 +505,12 @@
     public static final DataExternalizer<ElemType> elementTypeExternalizer = new DataExternalizer<ElemType>() {
       @Override
       public void save(final DataOutput out, final ElemType value) throws IOException {
-        out.writeInt(value.ordinal());
+        DataInputOutputUtil.writeINT(out, value.ordinal());
       }
 
       @Override
       public ElemType read(final DataInput in) throws IOException {
-        final int ordinal = in.readInt();
+        final int ordinal = DataInputOutputUtil.readINT(in);
         for (ElemType value : ElemType.values()) {
           if (value.ordinal() == ordinal) {
             return value;
@@ -682,11 +684,6 @@
     return context.getUsage(new ClassAsGenericBoundUsage(name));
   }
 
-
-  public static Usage createClassExtendsUsage(final DependencyContext context, final int name) {
-    return context.getUsage(new ClassExtendsUsage(name));
-  }
-
   public static Usage createClassNewUsage(final DependencyContext context, final int name) {
     return context.getUsage(new ClassNewUsage(name));
   }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
index 3285a21..63e5380 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
@@ -142,7 +142,7 @@
   }
 
   private static Set<JpsModule> getDependentModulesRecursively(final JpsModule module, final JpsJavaClasspathKind kind) {
-    return JpsJavaExtensionService.dependencies(module).includedIn(kind).recursively().exportedOnly().getModules();
+    return JpsJavaExtensionService.dependencies(module).includedIn(kind).recursivelyExportedOnly().getModules();
   }
 
   public static void processFilesToRecompile(CompileContext context, ModuleChunk chunk, FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor) throws IOException {
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 3c9ac5b..1a0ce3b 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
@@ -41,7 +41,7 @@
  *         Date: 10/7/11
  */
 public class BuildDataManager implements StorageOwner {
-  private static final int VERSION = 19;
+  private static final int VERSION = 20;
   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 MAPPINGS_STORAGE = "mappings";
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java
index 78d6d62..82cec24 100644
--- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java
@@ -16,31 +16,97 @@
 package org.jetbrains.jps.model.java;
 
 import com.intellij.openapi.util.Condition;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.model.module.JpsDependenciesEnumerator;
 import org.jetbrains.jps.model.module.JpsDependencyElement;
 
 /**
+ * Interface for convenient processing dependencies of a java module or a java project. Allows to process {@link org.jetbrains.jps.model.module.JpsDependencyElement}s and collect classes
+  * and source roots.
+ * <p/>
+ * Use {@link org.jetbrains.jps.model.java.JpsJavaExtensionService#dependencies(org.jetbrains.jps.model.module.JpsModule)} to process dependencies of a module
+ * and use {@link org.jetbrains.jps.model.java.JpsJavaExtensionService#dependencies(org.jetbrains.jps.model.JpsProject)} to process dependencies of all modules in a project.<p>
+ *
+ * Note that all configuration methods modify {@link org.jetbrains.jps.model.module.JpsDependenciesEnumerator} instance instead of creating a new one.
+ *
  * @author nik
  */
 public interface JpsJavaDependenciesEnumerator extends JpsDependenciesEnumerator {
+  /**
+   * Skip test dependencies
+   *
+   * @return this instance
+   */
+  @NotNull
   JpsJavaDependenciesEnumerator productionOnly();
+
+  /**
+   * Skip runtime-only dependencies
+   *
+   * @return this instance
+   */
+  @NotNull
   JpsJavaDependenciesEnumerator compileOnly();
+
+  /**
+   * Skip compile-only dependencies
+   *
+   * @return this instance
+   */
+  @NotNull
   JpsJavaDependenciesEnumerator runtimeOnly();
+
+  /**
+   * Skip not exported dependencies. If this method is called after {@link #recursively()} direct non-exported dependencies won't be skipped
+   *
+   * @return this instance
+   */
+  @NotNull
   JpsJavaDependenciesEnumerator exportedOnly();
 
-  JpsJavaDependenciesEnumerator withoutLibraries();
-  JpsJavaDependenciesEnumerator withoutDepModules();
-  JpsJavaDependenciesEnumerator withoutSdk();
-  JpsJavaDependenciesEnumerator withoutModuleSourceEntries();
-
+  @NotNull
   @Override
   JpsJavaDependenciesEnumerator recursively();
 
+  /**
+   * Process all direct dependencies and recursively process transitive dependencies which marked with 'exported'
+   *
+   * @return this instance
+   */
+  @NotNull
+  JpsJavaDependenciesEnumerator recursivelyExportedOnly();
+
+
+  @NotNull
+  JpsJavaDependenciesEnumerator withoutLibraries();
+  @NotNull
+  JpsJavaDependenciesEnumerator withoutDepModules();
+  @NotNull
+  JpsJavaDependenciesEnumerator withoutSdk();
+  @NotNull
+  JpsJavaDependenciesEnumerator withoutModuleSourceEntries();
+
+  @NotNull
   @Override
-  JpsJavaDependenciesEnumerator satisfying(Condition<JpsDependencyElement> condition);
+  JpsJavaDependenciesEnumerator satisfying(@NotNull Condition<JpsDependencyElement> condition);
 
-  JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind);
+  /**
+   * Process only dependencies which should be included in the classpath specified by {@code classpathKind} parameter
+   * @param classpathKind
+   * @return this instance
+   */
+  @NotNull
+  JpsJavaDependenciesEnumerator includedIn(@NotNull JpsJavaClasspathKind classpathKind);
 
+  /**
+   * @return enumerator for processing classes roots of the dependencies
+   */
+  @NotNull
   JpsJavaDependenciesRootsEnumerator classes();
+
+  /**
+   * @return enumerator for processing source roots of the dependencies
+   */
+  @NotNull
   JpsJavaDependenciesRootsEnumerator sources();
 }
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java
index c31ab23..d310247 100644
--- a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java
@@ -17,23 +17,63 @@
 
 import com.intellij.openapi.util.Condition;
 import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.model.library.JpsLibrary;
 
 import java.util.Set;
 
 /**
+ * Interface for convenient processing dependencies of a module or a project
+ * <p/>
+ * Use {@link org.jetbrains.jps.model.java.JpsJavaDependenciesEnumerator JpsJavaDependenciesEnumerator} for java-specific dependencies processing
+ * <p/>
+ * Note that all configuration methods modify {@link org.jetbrains.jps.model.module.JpsDependenciesEnumerator} instance instead of creating a new one.
+ *
  * @author nik
  */
 public interface JpsDependenciesEnumerator {
+  @NotNull
   JpsDependenciesEnumerator withoutLibraries();
+  @NotNull
   JpsDependenciesEnumerator withoutDepModules();
+  @NotNull
   JpsDependenciesEnumerator withoutSdk();
+  @NotNull
   JpsDependenciesEnumerator withoutModuleSourceEntries();
-  JpsDependenciesEnumerator recursively();
-  JpsDependenciesEnumerator satisfying(Condition<JpsDependencyElement> condition);
 
+  /**
+   * Recursively process modules on which the module depends
+   *
+   * @return this instance
+   */
+  @NotNull
+  JpsDependenciesEnumerator recursively();
+
+  /**
+   * Process only dependencies which satisfies the specified condition
+   *
+   * @param condition filtering condition
+   * @return this instance
+   */
+  @NotNull
+  JpsDependenciesEnumerator satisfying(@NotNull Condition<JpsDependencyElement> condition);
+
+  /**
+   * @return all modules processed by enumerator
+   */
+  @NotNull
   Set<JpsModule> getModules();
+
+  /**
+   * @return all libraries processed by enumerator
+   */
+  @NotNull
   Set<JpsLibrary> getLibraries();
 
-  void processModules(Consumer<JpsModule> consumer);
+  /**
+   * Runs <code>consumer.consume()</code> for each module processed by this enumerator
+   *
+   * @param consumer consumer
+   */
+  void processModules(@NotNull Consumer<JpsModule> consumer);
 }
diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java
index 713b18d..87af190 100644
--- a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java
+++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModuleSourceRoot.java
@@ -35,6 +35,9 @@
   <P extends JpsElement> JpsTypedModuleSourceRoot<P> asTyped(@NotNull JpsModuleSourceRootType<P> type);
 
   @NotNull
+  JpsTypedModuleSourceRoot<?> asTyped();
+
+  @NotNull
   JpsElement getProperties();
 
   @NotNull
diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java
index afbaaaf..8e22fe2 100644
--- a/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java
+++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java
@@ -40,6 +40,7 @@
       myMatcher = PatternUtil.fromMask(pattern).matcher("");
     }
 
+    @Override
     public boolean matches(final String filename) {
       synchronized (myMatcher) {
         myMatcher.reset(filename);
@@ -55,6 +56,7 @@
       mySuffix = suffix;
     }
 
+    @Override
     public boolean matches(final String filename) {
       return filename.endsWith(mySuffix);
     }
@@ -67,6 +69,7 @@
       myPrefix = prefix;
     }
 
+    @Override
     public boolean matches(final String filename) {
       return filename.startsWith(myPrefix);
     }
@@ -79,6 +82,7 @@
       myInfix = infix;
     }
 
+    @Override
     public boolean matches(final String filename) {
       return filename.contains(myInfix);
     }
@@ -108,10 +112,12 @@
     return new RegexpMatcher(pattern);
   }
 
+  @Override
   public boolean accept(@NotNull String fileName) {
     return myMatcher.matches(fileName);
   }
 
+  @Override
   @NonNls
   @NotNull
   public String getPresentableString() {
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java
index 17edcce..c3ee736 100644
--- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.jps.model.java.impl;
 
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.model.java.*;
 import org.jetbrains.jps.model.library.JpsOrderRootType;
 import org.jetbrains.jps.model.module.JpsDependencyElement;
@@ -44,24 +45,28 @@
     myHandlers = handlers != null ? handlers : Collections.<JpsJavaDependenciesEnumerationHandler>emptyList();
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesEnumerator productionOnly() {
     myProductionOnly = true;
     return this;
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesEnumerator compileOnly() {
     myCompileOnly = true;
     return this;
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesEnumerator runtimeOnly() {
     myRuntimeOnly = true;
     return this;
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesEnumerator exportedOnly() {
     if (myRecursively) {
@@ -73,17 +78,26 @@
     return this;
   }
 
+  @NotNull
   @Override
-  public JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind) {
+  public JpsJavaDependenciesEnumerator recursivelyExportedOnly() {
+    return recursively().exportedOnly();
+  }
+
+  @NotNull
+  @Override
+  public JpsJavaDependenciesEnumerator includedIn(@NotNull JpsJavaClasspathKind classpathKind) {
     myClasspathKind = classpathKind;
     return this;
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesRootsEnumerator classes() {
     return new JpsJavaDependenciesRootsEnumeratorImpl(this, JpsOrderRootType.COMPILED);
   }
 
+  @NotNull
   @Override
   public JpsJavaDependenciesRootsEnumerator sources() {
     return new JpsJavaDependenciesRootsEnumeratorImpl(this, JpsOrderRootType.SOURCES);
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java
index 86e248e..c6dee7b 100644
--- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java
@@ -20,6 +20,7 @@
 import com.intellij.util.Consumer;
 import com.intellij.util.Processor;
 import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.model.library.JpsLibrary;
 import org.jetbrains.jps.model.module.*;
 
@@ -43,36 +44,42 @@
     myRootModules = rootModules;
   }
 
+  @NotNull
   @Override
   public Self withoutLibraries() {
     myWithoutLibraries = true;
     return self();
   }
 
+  @NotNull
   @Override
   public Self withoutDepModules() {
     myWithoutDepModules = true;
     return self();
   }
 
+  @NotNull
   @Override
   public Self withoutSdk() {
     myWithoutSdk = true;
     return self();
   }
 
+  @NotNull
   @Override
   public Self withoutModuleSourceEntries() {
     myWithoutModuleSourceEntries = true;
     return self();
   }
 
+  @NotNull
   @Override
-  public Self satisfying(Condition<JpsDependencyElement> condition) {
+  public Self satisfying(@NotNull Condition<JpsDependencyElement> condition) {
     myCondition = condition;
     return self();
   }
 
+  @NotNull
   @Override
   public Self recursively() {
     myRecursively = true;
@@ -81,6 +88,7 @@
 
   protected abstract Self self();
 
+  @NotNull
   @Override
   public Set<JpsModule> getModules() {
     Set<JpsModule> result = new HashSet<JpsModule>();
@@ -89,7 +97,7 @@
   }
 
   @Override
-  public void processModules(final Consumer<JpsModule> consumer) {
+  public void processModules(@NotNull final Consumer<JpsModule> consumer) {
     processDependencies(new Processor<JpsDependencyElement>() {
       @Override
       public boolean process(JpsDependencyElement dependencyElement) {
@@ -167,6 +175,7 @@
     return myRootModules.contains(module);
   }
 
+  @NotNull
   @Override
   public Set<JpsLibrary> getLibraries() {
     Set<JpsLibrary> libraries = new HashSet<JpsLibrary>();
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java
index 90369b8..7ba971b 100644
--- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleSourceRootImpl.java
@@ -62,6 +62,12 @@
     return myRootType.equals(type) ? (JpsTypedModuleSourceRoot<P>)this : null;
   }
 
+  @NotNull
+  @Override
+  public JpsTypedModuleSourceRoot<?> asTyped() {
+    return this;
+  }
+
   @Override
   public JpsElementType<?> getType() {
     return myRootType;
diff --git a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java
index 744077a..95f3a63 100644
--- a/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java
+++ b/jps/model-impl/testSrc/org/jetbrains/jps/model/JpsDependenciesEnumeratorTest.java
@@ -177,7 +177,7 @@
 
     assertClassRoots(orderEntries(myModule).withoutSdk(), getAsmJar());
     assertClassRoots(orderEntries(myModule).withoutSdk().recursively(), getAsmJar(), getJDomJar());
-    assertClassRoots(orderEntries(myModule).withoutSdk().recursively().exportedOnly(), getAsmJar());
+    assertClassRoots(orderEntries(myModule).withoutSdk().recursivelyExportedOnly(), getAsmJar());
     assertClassRoots(orderEntries(myModule).withoutSdk().exportedOnly().recursively());
   }
 
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
index e5adc22..62f76ff 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
@@ -178,7 +178,7 @@
       rootModelElement.addContent(contentElement);
       for (JpsModuleSourceRoot root : sourceRoots) {
         if (FileUtil.startsWith(root.getUrl(), url)) {
-          saveSourceRoot(contentElement, (JpsTypedModuleSourceRoot<?>)root);
+          saveSourceRoot(contentElement, root.asTyped().getUrl(), root.asTyped());
         }
       }
       for (String excludedUrl : excludedUrls) {
@@ -241,9 +241,11 @@
     }
   }
 
-  public static <P extends JpsElement> void saveSourceRoot(Element contentElement, JpsTypedModuleSourceRoot<P> root) {
+  public static <P extends JpsElement> void saveSourceRoot(@NotNull Element contentElement,
+                                                           final @NotNull String rootUrl,
+                                                           @NotNull JpsTypedModuleSourceRoot<P> root) {
     Element sourceElement = new Element(SOURCE_FOLDER_TAG);
-    sourceElement.setAttribute(URL_ATTRIBUTE, root.getUrl());
+    sourceElement.setAttribute(URL_ATTRIBUTE, rootUrl);
     JpsModuleSourceRootPropertiesSerializer<P> serializer = getSerializer(root.getRootType());
     if (serializer != null) {
       String typeId = serializer.getTypeId();
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSourceRootPropertiesSerializerImpl.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSourceRootPropertiesSerializerImpl.java
new file mode 100644
index 0000000..706ef83
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleSourceRootPropertiesSerializerImpl.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.jetbrains.jps.model.serialization.module;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+/**
+ * @author nik
+ */
+public class JpsModuleSourceRootPropertiesSerializerImpl extends JpsModuleSourceRootPropertiesSerializer<JpsDummyElement> {
+  public JpsModuleSourceRootPropertiesSerializerImpl(JpsModuleSourceRootType<JpsDummyElement> type, String typeId) {
+    super(type, typeId);
+  }
+
+  @Override
+  public JpsDummyElement loadProperties(@NotNull Element sourceRootTag) {
+    return JpsElementFactory.getInstance().createDummyElement();
+  }
+
+  @Override
+  public void saveProperties(@NotNull JpsDummyElement properties, @NotNull Element sourceRootTag) {
+  }
+}
diff --git a/lib/netty-all.jar b/lib/netty-all.jar
index 847efe5..96f6241 100644
--- a/lib/netty-all.jar
+++ b/lib/netty-all.jar
Binary files differ
diff --git a/lib/src/netty-all-sources.jar b/lib/src/netty-all-sources.jar
index 07ac406..1a8e749 100644
--- a/lib/src/netty-all-sources.jar
+++ b/lib/src/netty-all-sources.jar
Binary files differ
diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java
index 179d0d3..d1dabcb 100644
--- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java
+++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java
@@ -62,7 +62,6 @@
     addAdditionalClassPath(classpath);
     UrlClassLoader newClassLoader = UrlClassLoader.build()
       .urls(filterClassPath(classpath))
-      .nativeLibs("IdeaWin32", "focusKiller", "jumpListBridge")
       .allowLock().useCache().get();
 
     // prepare plugins
diff --git a/platform/core-api/src/com/intellij/lang/injection/InjectedLanguageManager.java b/platform/core-api/src/com/intellij/lang/injection/InjectedLanguageManager.java
index 5a41d24..c1f7618 100644
--- a/platform/core-api/src/com/intellij/lang/injection/InjectedLanguageManager.java
+++ b/platform/core-api/src/com/intellij/lang/injection/InjectedLanguageManager.java
@@ -94,4 +94,5 @@
   public abstract void startRunInjectors(@NotNull Document hostDocument, boolean synchronously);
 
   public abstract void enumerate(@NotNull PsiElement host, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor);
+  public abstract void enumerateEx(@NotNull PsiElement host, @NotNull PsiFile containingFile, boolean probeUp, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor);
 }
diff --git a/platform/core-api/src/com/intellij/psi/ElementManipulators.java b/platform/core-api/src/com/intellij/psi/ElementManipulators.java
index 9f91e0e..098a204 100644
--- a/platform/core-api/src/com/intellij/psi/ElementManipulators.java
+++ b/platform/core-api/src/com/intellij/psi/ElementManipulators.java
@@ -60,6 +60,7 @@
     return manipulator == null ? TextRange.from(0, element.getTextLength()) : manipulator.getRangeInElement(element);
   }
 
+  @NotNull
   public static String getValueText(final PsiElement element) {
     final TextRange valueTextRange = getValueTextRange(element);
     if (valueTextRange.isEmpty()) return "";
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
index e5e0e96..1714e90 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
@@ -17,7 +17,9 @@
 
 import com.intellij.diagnostic.PluginException;
 import com.intellij.ide.plugins.PluginManagerCore;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.extensions.PluginId;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.lang.UrlClassLoader;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -28,37 +30,40 @@
 import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.ListIterator;
 
 /**
  * @author Eugene Zhuravlev
  * @since 6.03.2003
  */
-@SuppressWarnings({"UseOfSystemOutOrSystemErr"})
 public class PluginClassLoader extends UrlClassLoader {
   private final ClassLoader[] myParents;
   private final PluginId myPluginId;
   private final String myPluginVersion;
-  private final File myLibDirectory;
+  private final List<String> myLibDirectories;
 
   public PluginClassLoader(@NotNull List<URL> urls,
                            @NotNull ClassLoader[] parents,
-                           final PluginId pluginId,
-                           final String version,
-                           final File pluginRoot) {
+                           PluginId pluginId,
+                           String version,
+                           File pluginRoot) {
     super(build().urls(urls).allowLock().useCache());
     myParents = parents;
     myPluginId = pluginId;
     myPluginVersion = version;
-
-    //noinspection HardCodedStringLiteral
-    final File file = new File(pluginRoot, "lib");
-    myLibDirectory = file.exists()? file : null;
+    myLibDirectories = ContainerUtil.newSmartList();
+    File libDir = new File(pluginRoot, "lib");
+    if (libDir.exists()) {
+      myLibDirectories.add(libDir.getAbsolutePath());
+    }
   }
 
   // Changed sequence in which classes are searched, this is essential if plugin uses library,
   // a different version of which is used in IDEA.
+  @Override
   public Class loadClass(@NotNull String name, final boolean resolve) throws ClassNotFoundException {
     Class c = loadClassInsideSelf(name);
 
@@ -156,46 +161,50 @@
     return new CompoundEnumeration<URL>(resources);
   }
 
-  @Override
-  protected String findLibrary(String libName) {
-    if (myLibDirectory == null) {
-      return null;
-    }
-    final File libraryFile = new File(myLibDirectory, System.mapLibraryName(libName));
-    return libraryFile.exists()? libraryFile.getAbsolutePath() : null;
+  @SuppressWarnings("UnusedDeclaration")
+  public void addLibDirectories(@NotNull Collection<String> libDirectories) {
+    myLibDirectories.addAll(libDirectories);
   }
 
+  @Override
+  protected String findLibrary(String libName) {
+    if (!myLibDirectories.isEmpty()) {
+      String libFileName = System.mapLibraryName(libName);
+      ListIterator<String> i = myLibDirectories.listIterator(myLibDirectories.size());
+      while (i.hasPrevious()) {
+        File libFile = new File(i.previous(), libFileName);
+        if (libFile.exists()) {
+          return libFile.getAbsolutePath();
+        }
+      }
+    }
+
+    return null;
+  }
 
   private static URL fetchResource(ClassLoader cl, String resourceName) {
-    //protected URL findResource(String s)
     try {
-      //noinspection HardCodedStringLiteral
       final Method findResourceMethod = getFindResourceMethod(cl.getClass(), "findResource");
       return (URL)findResourceMethod.invoke(cl, resourceName);
     }
     catch (Exception e) {
-      e.printStackTrace();
+      Logger.getInstance(PluginClassLoader.class).error(e);
       return null;
     }
   }
 
   private static Enumeration fetchResources(ClassLoader cl, String resourceName) {
-    //protected Enumeration findResources(String s) throws IOException
     try {
-      //noinspection HardCodedStringLiteral
       final Method findResourceMethod = getFindResourceMethod(cl.getClass(), "findResources");
-      if (findResourceMethod == null) {
-        return null;
-      }
-      return (Enumeration)findResourceMethod.invoke(cl, resourceName);
+      return findResourceMethod == null ? null : (Enumeration)findResourceMethod.invoke(cl, resourceName);
     }
     catch (Exception e) {
-      e.printStackTrace();
+      Logger.getInstance(PluginClassLoader.class).error(e);
       return null;
     }
   }
 
-  private static Method getFindResourceMethod(final Class clClass, final String methodName) {
+  private static Method getFindResourceMethod(final Class<?> clClass, final String methodName) {
     try {
       final Method declaredMethod = clClass.getDeclaredMethod(methodName, String.class);
       declaredMethod.setAccessible(true);
@@ -214,6 +223,7 @@
     return myPluginId;
   }
 
+  @Override
   public String toString() {
     return "PluginClassLoader[" + myPluginId + ", " + myPluginVersion + "]";
   }
diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java
index c0529ac..23b42f9 100644
--- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java
@@ -517,7 +517,7 @@
       final String componentKey = config.getInterfaceClass();
       myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, implementationClass, null, true)) {
         @Override
-        public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException {
+        public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException, ProcessCanceledException {
           ProgressIndicator indicator = getProgressIndicator();
           if (indicator != null) {
             indicator.checkCanceled();
diff --git a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java
index 52c6c1b..dc3fff5 100644
--- a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java
+++ b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -513,14 +513,14 @@
     @Override
     public int getStartOffset() {
       final PsiElement resolved = retrieve();
-      if (resolved == null) throw new PsiInvalidElementAccessException(null);
+      if (resolved == null) throw new PsiInvalidElementAccessException(null, "Element type: " + myElementType.toString() + "; " + myVirtualFile);
       return resolved.getTextRange().getStartOffset();
     }
 
     @Override
     public int getEndOffset() {
       final PsiElement resolved = retrieve();
-      if (resolved == null) throw new PsiInvalidElementAccessException(null);
+      if (resolved == null) throw new PsiInvalidElementAccessException(null, "Element type: " + myElementType.toString() + "; " + myVirtualFile);
       return resolved.getTextRange().getEndOffset();
     }
 
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java
index d081d55..8e46a2f 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.extensions.impl;
 
 import com.intellij.openapi.extensions.*;
+import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.util.pico.AssignableToComponentAdapter;
 import com.intellij.util.xmlb.XmlSerializer;
 import org.jdom.Element;
@@ -64,8 +65,12 @@
   }
 
   @Override
-  public Object getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
-    //assert myContainer == container : "Different containers: " + myContainer + " - " + container;
+  public Object getComponentInstance(final PicoContainer container)
+    throws PicoInitializationException,
+           PicoIntrospectionException,
+           AssignabilityRegistrationException,
+           NotConcreteRegistrationException,
+           ProcessCanceledException {
     if (myComponentInstance == null) {
       if (Element.class.equals(getComponentImplementation())) {
         myComponentInstance = myExtensionElement;
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
index 81b1d28..2ddb8fb 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
@@ -169,7 +169,7 @@
     // has content
     if (!extensionElement.getContent().isEmpty()) return true;
     // has custom attributes
-    for (Attribute attribute : (List<Attribute>)extensionElement.getAttributes()) {
+    for (Attribute attribute : extensionElement.getAttributes()) {
       final String name = attribute.getName();
       if (!"implementation".equals(name) && !"id".equals(name) && !"order".equals(name)) {
         return true;
@@ -405,6 +405,7 @@
     return extensionPoint;
   }
 
+  @NotNull
   @Override
   @SuppressWarnings({"unchecked"})
   public <T> ExtensionPoint<T> getExtensionPoint(@NotNull ExtensionPointName<T> extensionPointName) {
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ModuleAwareContentRoot.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ModuleAwareContentRoot.java
index 789203e..8479bfc 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ModuleAwareContentRoot.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/ModuleAwareContentRoot.java
@@ -6,6 +6,8 @@
 import com.intellij.openapi.roots.SourceFolder;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 /**
  * @author Denis Zhdanov
@@ -77,6 +79,14 @@
     return myDelegate.addSourceFolder(file, isTestSource, packagePrefix);
   }
 
+  @NotNull
+  @Override
+  public <P extends JpsElement> SourceFolder addSourceFolder(@NotNull VirtualFile file,
+                                                             @NotNull JpsModuleSourceRootType<P> type,
+                                                             @NotNull P properties) {
+    return myDelegate.addSourceFolder(file, type, properties);
+  }
+
   @Override
   public SourceFolder addSourceFolder(@NotNull String url, boolean isTestSource) {
     return myDelegate.addSourceFolder(url, isTestSource);
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
index de72751..75cf210 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
@@ -20,6 +20,7 @@
 import com.intellij.openapi.extensions.Extensions
 import com.intellij.openapi.externalSystem.ExternalSystemManager
 import com.intellij.openapi.externalSystem.model.DataNode
+import com.intellij.openapi.externalSystem.model.ProjectSystemId
 import com.intellij.openapi.externalSystem.model.project.ProjectData
 import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager
 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalProjectBuilder.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalProjectBuilder.groovy
index f80d50d..b0480ac 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalProjectBuilder.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalProjectBuilder.groovy
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.externalSystem.model.DataNode
 import com.intellij.openapi.externalSystem.model.ProjectKeys
+import com.intellij.openapi.externalSystem.model.ProjectSystemId
 import com.intellij.openapi.externalSystem.model.project.*
 import com.intellij.openapi.externalSystem.model.task.TaskData
 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
@@ -58,14 +59,16 @@
   protected Object createNode(Object name, Map attributes) {
     switch (name) {
       case 'project':
-        ProjectData projectData = new ProjectData(TEST_EXTERNAL_SYSTEM_ID, projectDir.path, projectDir.path)
+        ProjectSystemId projectSystemId = attributes.projectSystemId ?: TEST_EXTERNAL_SYSTEM_ID
+        ProjectData projectData = new ProjectData(projectSystemId, projectDir.path, projectDir.path)
         projectData.name = attributes.name ?: 'project'
         projectNode = new DataNode<ProjectData>(ProjectKeys.PROJECT, projectData, null)
         return projectNode
       case 'module':
+        ProjectSystemId projectSystemId = attributes.projectSystemId ?: TEST_EXTERNAL_SYSTEM_ID
         String moduleFilePath = attributes.moduleFilePath ?: projectDir.path
         String externalConfigPath = attributes.externalConfigPath ?: projectDir.path
-        ModuleData moduleData = new ModuleData(TEST_EXTERNAL_SYSTEM_ID,
+        ModuleData moduleData = new ModuleData(projectSystemId,
                                                ModuleTypeId.JAVA_MODULE,
                                                attributes.name ?: name as String,
                                                moduleFilePath,
@@ -80,7 +83,8 @@
         return parentNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, data)
       case 'task':
         DataNode<ExternalConfigPathAware> parentNode = current as DataNode
-        TaskData data = new TaskData(TEST_EXTERNAL_SYSTEM_ID, attributes.name, parentNode.data.linkedExternalProjectPath, null)
+        ProjectSystemId projectSystemId = attributes.projectSystemId ?: TEST_EXTERNAL_SYSTEM_ID
+        TaskData data = new TaskData(projectSystemId, attributes.name, parentNode.data.linkedExternalProjectPath, null)
         return parentNode.createChild(ProjectKeys.TASK, data)
       case 'contentRoot':
         DataNode<ModuleData> parentNode = current as DataNode
diff --git a/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java b/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java
index 7a22237..75d09a3 100644
--- a/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java
+++ b/platform/indexing-api/src/com/intellij/psi/search/searches/DefinitionsScopedSearch.java
@@ -16,7 +16,9 @@
 
 package com.intellij.psi.search.searches;
 
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.Computable;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.search.PsiSearchHelper;
 import com.intellij.psi.search.SearchScope;
@@ -80,7 +82,12 @@
     }
 
     public SearchScope getScope() {
-      final SearchScope accessScope = PsiSearchHelper.SERVICE.getInstance(myElement.getProject()).getUseScope(myElement);
+      final SearchScope accessScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
+        @Override
+        public SearchScope compute() {
+          return PsiSearchHelper.SERVICE.getInstance(myElement.getProject()).getUseScope(myElement);
+        }
+      });
       return myScope.intersectWith(accessScope);
     }
   }
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
index 9260714..ef1395e 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
@@ -27,6 +27,7 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.util.Consumer;
 import com.intellij.util.Processor;
+import com.intellij.util.SystemProperties;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -150,6 +151,7 @@
     void registerFileTypesUsedForIndexing(@NotNull Consumer<FileType> fileTypeSink);
   }
 
-  // TODO: remove once changes becomes permamnent
-  public static final boolean ourEnableTracingOfKeyHashToVirtualFileMapping = ApplicationManager.getApplication().isInternal();
+  // TODO: remove once changes becomes permanent
+  public static final boolean ourEnableTracingOfKeyHashToVirtualFileMapping =
+    SystemProperties.getBooleanProperty("idea.enable.tracing.keyhash2virtualfile", true);
 }
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java
index 6be87f7..f9e8f09 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -205,6 +205,13 @@
   }
 
   /**
+   * Allow autoPopup to appear after custom symbol
+   */
+  public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar) {
+    return false;
+  }
+
+  /**
    * Invoked in a read action in parallel to the completion process. Used to calculate the replacement offset
    * (see {@link com.intellij.codeInsight.completion.CompletionInitializationContext#setReplacementOffset(int)})
    * if it takes too much time to spend it in {@link #beforeCompletion(CompletionInitializationContext)},
@@ -216,7 +223,7 @@
    */
   public void duringCompletion(@NotNull CompletionInitializationContext context) {
   }
-
+  
   /**
    * @param actionId
    * @return String representation of action shortcut. Useful while advertising something
diff --git a/platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java b/platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java
index 1f05008..74828fa 100644
--- a/platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java
+++ b/platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -37,17 +37,16 @@
   @NonNls public static final String COLUMN_MACROS = "$COLUMN$";
 
   @NonNls private static final String FILE_PATH_REGEXP = "((?:\\p{Alpha}\\:)?[0-9 a-z_A-Z\\-\\\\./]+)";
-  private static final String NUMBER_REGEXP = "([0-9]+)";
+  @NonNls private static final String NUMBER_REGEXP = "([0-9]+)";
+  @NonNls private static final String FILE_STR = "file";
+  @NonNls private static final String LINE_STR = "line";
+  @NonNls private static final String COLUMN_STR = "column";
 
   private final int myFileRegister;
   private final int myLineRegister;
   private final int myColumnRegister;
-
   private final Pattern myPattern;
   private final Project myProject;
-  @NonNls private static final String FILE_STR = "file";
-  @NonNls private static final String LINE_STR = "line";
-  @NonNls private static final String COLUMN_STR = "column";
 
   public RegexpFilter(Project project, @NonNls String expression) {
     myProject = project;
@@ -104,17 +103,17 @@
     myPattern = Pattern.compile(expression, Pattern.MULTILINE);
   }
 
+  @SuppressWarnings("ResultOfMethodCallIgnored")
   public static void validate(String expression) {
     if (expression == null || expression.trim().isEmpty()) {
       throw new InvalidExpressionException("expression == null or empty");
     }
 
-    expression = substituteMacrosesWithRegexps(expression);
-
+    expression = substituteMacrosWithRegexps(expression);
     Pattern.compile(expression, Pattern.MULTILINE);
   }
 
-  private static String substituteMacrosesWithRegexps(String expression) {
+  private static String substituteMacrosWithRegexps(String expression) {
     int filePathIndex = expression.indexOf(FILE_PATH_MACROS);
     int lineIndex = expression.indexOf(LINE_MACROS);
     int columnIndex = expression.indexOf(COLUMN_MACROS);
@@ -136,21 +135,18 @@
   }
 
   @Override
-  public Result applyFilter(final String line, final int entireLength) {
-
-    final Matcher matcher = myPattern.matcher(line);
-    if (matcher.find()) {
-      return createResult(matcher, entireLength - line.length());
+  public Result applyFilter(String line, int entireLength) {
+    Matcher matcher = myPattern.matcher(line);
+    if (!matcher.find()) {
+      return null;
     }
 
-    return null;
-  }
-
-  private Result createResult(final Matcher matcher, final int entireLen) {
-    final String filePath = matcher.group(myFileRegister);
+    String filePath = matcher.group(myFileRegister);
+    if (filePath == null) {
+      return null;
+    }
 
     String lineNumber = "0";
-
     if (myLineRegister != -1) {
       lineNumber = matcher.group(myLineRegister);
     }
@@ -160,32 +156,29 @@
       columnNumber = matcher.group(myColumnRegister);
     }
 
-    int line = 0;
+    int line1 = 0;
     int column = 0;
     try {
-      line = Integer.parseInt(lineNumber);
+      line1 = Integer.parseInt(lineNumber);
       column = Integer.parseInt(columnNumber);
     } catch (NumberFormatException e) {
-      // Do nothing, so that line and column will remain at their initial
-      // zero values.
+      // Do nothing, so that line and column will remain at their initial zero values.
     }
 
-    if (line > 0) line -= 1;
+    if (line1 > 0) line1 -= 1;
     if (column > 0) column -= 1;
     // Calculate the offsets relative to the entire text.
-    final int highlightStartOffset = entireLen + matcher.start(myFileRegister);
+    final int highlightStartOffset = entireLength - line.length() + matcher.start(myFileRegister);
     final int highlightEndOffset = highlightStartOffset + filePath.length();
-
-    final HyperlinkInfo info = createOpenFileHyperlink(filePath, line, column);
+    final HyperlinkInfo info = createOpenFileHyperlink(filePath, line1, column);
     return new Result(highlightStartOffset, highlightEndOffset, info);
   }
 
   @Nullable
   protected HyperlinkInfo createOpenFileHyperlink(String fileName, final int line, final int column) {
     fileName = fileName.replace(File.separatorChar, '/');
-    final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(fileName);
-    if (file == null) return null;
-    return new OpenFileHyperlinkInfo(myProject, file, line, column);
+    VirtualFile file = LocalFileSystem.getInstance().findFileByPath(fileName);
+    return file != null ? new OpenFileHyperlinkInfo(myProject, file, line, column) : null;
   }
 
   public static String[] getMacrosName() {
diff --git a/platform/lang-api/src/com/intellij/lang/annotation/Annotation.java b/platform/lang-api/src/com/intellij/lang/annotation/Annotation.java
index bd20378..3236b16 100644
--- a/platform/lang-api/src/com/intellij/lang/annotation/Annotation.java
+++ b/platform/lang-api/src/com/intellij/lang/annotation/Annotation.java
@@ -62,23 +62,14 @@
 
   public static class QuickFixInfo {
     public final IntentionAction quickFix;
+    @NotNull
     public final TextRange textRange;
-    public final List<IntentionAction> options;
     public final HighlightDisplayKey key;
 
-    @Deprecated
-    public QuickFixInfo(final IntentionAction quickFix, final TextRange textRange, final List<IntentionAction> options, String displayName) {
-      key = null;
-      this.quickFix = quickFix;
-      this.textRange = textRange;
-      this.options = options;
-    }
-
-    public QuickFixInfo(@NotNull IntentionAction fix, final TextRange range, @Nullable final HighlightDisplayKey key) {
+    public QuickFixInfo(@NotNull IntentionAction fix, @NotNull TextRange range, @Nullable final HighlightDisplayKey key) {
       this.key = key;
       quickFix = fix;
       textRange = range;
-      options = null;
     }
 
     @Override
@@ -99,7 +90,7 @@
    * @see AnnotationHolder#createWarningAnnotation
    * @see AnnotationHolder#createInfoAnnotation
    */
-  public Annotation(final int startOffset, final int endOffset, final HighlightSeverity severity, final String message, String tooltip) {
+  public Annotation(final int startOffset, final int endOffset, @NotNull HighlightSeverity severity, final String message, String tooltip) {
     assert startOffset <= endOffset : startOffset + ":" + endOffset;
     assert startOffset >= 0 : "Start offset must not be negative: " +startOffset;
     myStartOffset = startOffset;
@@ -140,24 +131,6 @@
    * @param fix   the quick fix implementation.
    * @param range the text range (relative to the document) where the quick fix is available.
    */
-  @Deprecated
-  public void registerFix(@NotNull IntentionAction fix, TextRange range, List<IntentionAction> options, String displayName) {
-    if (range == null) {
-      range = new TextRange(myStartOffset, myEndOffset);
-    }
-    if (myQuickFixes == null) {
-      myQuickFixes = new ArrayList<QuickFixInfo>();
-    }
-    myQuickFixes.add(new QuickFixInfo(fix, range, options, displayName));
-  }
-
-  /**
-   * Registers a quick fix for the annotation which is only available on a particular range of text
-   * within the annotation.
-   *
-   * @param fix   the quick fix implementation.
-   * @param range the text range (relative to the document) where the quick fix is available.
-   */
   public void registerFix(@NotNull IntentionAction fix, @Nullable TextRange range, @Nullable final HighlightDisplayKey key) {
     if (range == null) {
       range = new TextRange(myStartOffset, myEndOffset);
@@ -242,6 +215,7 @@
    *
    * @return the annotation severity.
    */
+  @NotNull
   public HighlightSeverity getSeverity() {
     return mySeverity;
   }
@@ -263,6 +237,7 @@
    *
    * @return the text attribute key used for highlighting
    */
+  @NotNull
   public TextAttributesKey getTextAttributes() {
     if (myEnforcedAttributesKey != null) return myEnforcedAttributesKey;
 
diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java
index b20f1f7..e5aa799 100644
--- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java
+++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java
@@ -68,7 +68,7 @@
 
   @Override
   @Nullable
-  public String getVersionString(Sdk sdk) {
+  public String getVersionString(@NotNull Sdk sdk) {
     return getVersionString(sdk.getHomePath());
   }
 
@@ -99,15 +99,15 @@
 
   @Override
   @Nullable
-  public SdkAdditionalData loadAdditionalData(Sdk currentSdk, Element additional) {
+  public SdkAdditionalData loadAdditionalData(@NotNull Sdk currentSdk, Element additional) {
     return loadAdditionalData(additional);
   }
 
-
-  public SdkType(@NonNls String name) {
+  public SdkType(@NotNull @NonNls String name) {
     myName = name;
   }
 
+  @NotNull
   @Override
   public String getName() {
     return myName;
diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java
index 41b5876..9db9794 100644
--- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java
+++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java
@@ -20,6 +20,7 @@
 import com.intellij.openapi.projectRoots.impl.SdkVersionUtil;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
 
@@ -55,24 +56,24 @@
   }
 
   @Override
-  public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
+  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
   }
 
   @Override
-  public String getBinPath(Sdk sdk) {
+  public String getBinPath(@NotNull Sdk sdk) {
     return getConvertedHomePath(sdk) + "bin";
   }
 
   @Override
   @NonNls
-  public String getToolsPath(Sdk sdk) {
+  public String getToolsPath(@NotNull Sdk sdk) {
     final String versionString = sdk.getVersionString();
     final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1"));
     return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x? "classes.zip" : "tools.jar");
   }
 
   @Override
-  public String getVMExecutablePath(Sdk sdk) {
+  public String getVMExecutablePath(@NotNull Sdk sdk) {
     return getBinPath(sdk) + File.separator + VM_EXE_NAME;
   }
 
diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/UnknownSdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/UnknownSdkType.java
index 98633e3..2b06e87 100644
--- a/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/UnknownSdkType.java
+++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/UnknownSdkType.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.project.ProjectBundle;
 import com.intellij.openapi.projectRoots.*;
 import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.util.HashMap;
@@ -35,11 +36,12 @@
   /**
    * @param typeName the name of the SDK type that this SDK serves as a plug for
    */
-  private UnknownSdkType(String typeName) {
+  private UnknownSdkType(@NotNull String typeName) {
     super(typeName);
   }
 
-  public static UnknownSdkType getInstance(String typeName) {
+  @NotNull
+  public static UnknownSdkType getInstance(@NotNull String typeName) {
     UnknownSdkType instance = ourTypeNameToInstanceMap.get(typeName);
     if (instance == null) {
       instance = new UnknownSdkType(typeName);
@@ -86,7 +88,7 @@
   }
 
   @Override
-  public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
+  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
   }
 
   @Override
diff --git a/platform/lang-api/src/com/intellij/refactoring/classMembers/AbstractMemberInfoModel.java b/platform/lang-api/src/com/intellij/refactoring/classMembers/AbstractMemberInfoModel.java
new file mode 100644
index 0000000..2869d0d
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/refactoring/classMembers/AbstractMemberInfoModel.java
@@ -0,0 +1,50 @@
+package com.intellij.refactoring.classMembers;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Nikolay.Tropin
+ * 8/23/13
+ */
+public abstract class AbstractMemberInfoModel<T extends PsiElement, M extends MemberInfoBase<T>> implements MemberInfoModel<T, M> {
+
+  @Override
+  public boolean isMemberEnabled(M member) {
+    return true;
+  }
+
+  @Override
+  public boolean isCheckedWhenDisabled(M member) {
+    return false;
+  }
+
+  @Override
+  public boolean isAbstractEnabled(M member) {
+    return false;
+  }
+
+  @Override
+  public boolean isAbstractWhenDisabled(M member) {
+    return false;
+  }
+
+  @Override
+  public Boolean isFixedAbstract(M member) {
+    return null;
+  }
+
+  @Override
+  public int checkForProblems(@NotNull M member) {
+    return OK;
+  }
+
+  @Override
+  public String getTooltipText(M member) {
+    return null;
+  }
+
+  @Override
+  public void memberInfoChanged(MemberInfoChange<T, M> event) {
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java
index f28bc87..51499b6 100644
--- a/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java
@@ -1,3 +1,18 @@
+/*
+ * 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.intellij.application.options;
 
 import com.intellij.openapi.module.Module;
@@ -6,10 +21,12 @@
 import com.intellij.openapi.options.UnnamedConfigurable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.Condition;
 import com.intellij.platform.ModuleAttachProcessor;
 import com.intellij.ui.CollectionListModel;
 import com.intellij.ui.components.JBList;
 import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -49,6 +66,10 @@
     return myHelpTopic;
   }
 
+  protected boolean isSuitableForModule(@NotNull Module module) {
+    return true;
+  }
+
   @Override
   public JComponent createComponent() {
     if (myProject.isDefault()) {
@@ -58,7 +79,12 @@
         return configurable.createComponent();
       }
     }
-    final List<Module> modules = ModuleAttachProcessor.getSortedModules(myProject);
+    final List<Module> modules = ContainerUtil.filter(ModuleAttachProcessor.getSortedModules(myProject), new Condition<Module>() {
+      @Override
+      public boolean value(Module module) {
+        return isSuitableForModule(module);
+      }
+    });
     if (modules.size() == 1) {
       Module module = modules.get(0);
       final T configurable = createModuleConfigurable(module);
@@ -98,6 +124,7 @@
     return null;
   }
 
+  @NotNull
   protected abstract T createModuleConfigurable(Module module);
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java
index a289831..4048ad8 100644
--- a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java
+++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java
@@ -15,7 +15,11 @@
  */
 package com.intellij.codeEditor.printing;
 
+import com.intellij.CommonBundle;
 import com.intellij.ide.highlighter.HighlighterFactory;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
@@ -155,6 +159,10 @@
             LOG.info("Cancelled");
             printerJob.cancel();
           }
+          catch (PrinterException e) {
+            Notifications.Bus.notify(new Notification("Print", CommonBundle.getErrorTitle(), e.getMessage(), NotificationType.ERROR));
+            LOG.warn(e);
+          }
           catch (Exception e) {
             LOG.error(e);
           }
@@ -170,7 +178,7 @@
     if (isRecursive) {
       for (PsiDirectory directory : psiDirectory.getSubdirectories()) {
         if (!Project.DIRECTORY_STORE_FOLDER.equals(directory.getName())) {
-          addToPsiFileList(directory, filesList, isRecursive);
+          addToPsiFileList(directory, filesList, true);
         }
       }
     }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
index c461c9e0..3914ce6 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
@@ -27,7 +27,6 @@
 import com.intellij.psi.PsiDirectory;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.codeStyle.arrangement.Rearranger;
-import com.intellij.util.ui.OptionsDialog;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -202,7 +201,7 @@
         updateState();
       }
     });
-    return OptionsDialog.addDoNotShowCheckBox(southPanel, myDoNotAskMeCheckBox);
+    return DialogWrapper.addDoNotShowCheckBox(southPanel, myDoNotAskMeCheckBox);
   }
 
   @NotNull
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java
index 1062bd4..2b3368f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java
@@ -46,6 +46,7 @@
 import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
 import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.*;
@@ -209,7 +210,7 @@
                                        @NotNull TextEditor textEditor,
                                        @NotNull int[] toIgnore,
                                        boolean canChangeDocument,
-                                       @Nullable Runnable callbackWhileWaiting) {
+                                       @Nullable Runnable callbackWhileWaiting) throws ProcessCanceledException {
     assert myInitialized;
     assert !myDisposed;
     Application application = ApplicationManager.getApplication();
@@ -240,13 +241,7 @@
     try {
       while (progress.isRunning()) {
         try {
-          if (progress.isCanceled() && progress.isRunning()) {
-            // write action sneaked in the AWT. restart
-            waitForTermination();
-            Throwable savedException = PassExecutorService.getSavedException(progress);
-            if (savedException != null) throw savedException;
-            return runPasses(file, document, textEditor, toIgnore, canChangeDocument, callbackWhileWaiting);
-          }
+          progress.checkCanceled();
           if (callbackWhileWaiting != null) {
             callbackWhileWaiting.run();
           }
@@ -292,7 +287,7 @@
     waitForTermination();
   }
 
-  private void waitForTermination() {
+  void waitForTermination() {
     myPassExecutorService.cancelAll(true);
   }
 
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
index f704286..013db8f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
@@ -120,7 +120,7 @@
                                  boolean updateAll) {
     this(project, file, document, startOffset, endOffset, updateAll, new ProperTextRange(0,document.getTextLength()), null);
   }
-  public GeneralHighlightingPass(@NotNull Project project,
+  GeneralHighlightingPass(@NotNull Project project,
                                  @NotNull PsiFile file,
                                  @NotNull Document document,
                                  int startOffset,
@@ -385,9 +385,9 @@
               final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
               addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange, outInfos);
             }
-            holder.clear();
+            int injectedStart = holder.size();
             highlightInjectedSyntax(injectedPsi, holder);
-            for (int i = 0; i < holder.size(); i++) {
+            for (int i = injectedStart; i < holder.size(); i++) {
               HighlightInfo info = holder.get(i);
               final int startOffset = info.startOffset;
               final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
@@ -523,7 +523,7 @@
     }
   }
 
-  private void highlightInjectedSyntax(final PsiFile injectedPsi, HighlightInfoHolder holder) {
+  private void highlightInjectedSyntax(@NotNull PsiFile injectedPsi, @NotNull HighlightInfoHolder holder) {
     List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>> tokens = InjectedLanguageUtil
       .getHighlightTokens(injectedPsi);
     if (tokens == null) return;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
index 1c61666..5ce6e13 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
@@ -17,7 +17,6 @@
 package com.intellij.codeInsight.daemon.impl;
 
 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInsight.intention.IntentionManager;
 import com.intellij.codeInspection.*;
@@ -36,10 +35,7 @@
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
 import com.intellij.codeInsight.daemon.GutterMark;
 import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Segment;
-import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.*;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
 import com.intellij.psi.PsiElement;
@@ -55,6 +51,7 @@
 
 import javax.swing.*;
 import java.awt.*;
+import java.util.Iterator;
 import java.util.List;
 
 public class HighlightInfo implements Segment {
@@ -73,8 +70,8 @@
   public final int startOffset;
   public final int endOffset;
 
-  public int fixStartOffset;
-  public int fixEndOffset;
+  private int fixStartOffset;
+  private int fixEndOffset;
   RangeMarker fixMarker; // null means it the same as highlighter
 
   private final String description;
@@ -84,7 +81,7 @@
 
   final int navigationShift;
 
-  RangeHighlighterEx highlighter;
+  volatile RangeHighlighterEx highlighter; // modified in EDT only
 
   public List<Pair<IntentionActionDescriptor, TextRange>> quickFixActionRanges;
   public List<Pair<IntentionActionDescriptor, RangeMarker>> quickFixActionMarkers;
@@ -100,6 +97,11 @@
   private static final int FILE_LEVEL_ANNOTATION_FLAG = 4;
   private static final int NEEDS_UPDATE_ON_TYPING_FLAG = 5;
 
+  @NotNull
+  ProperTextRange getFixTextRange() {
+    return new ProperTextRange(fixStartOffset, fixEndOffset);
+  }
+
   public void setFromInjection(boolean fromInjection) {
     setFlag(FROM_INJECTION_FLAG, fromInjection);
   }
@@ -652,14 +654,16 @@
     return info;
   }
 
+  public static final String ANNOTATOR_INSPECTION_SHORT_NAME = "Annotator";
+
   private static void appendFixes(@Nullable TextRange fixedRange, @NotNull HighlightInfo info, List<Annotation.QuickFixInfo> fixes) {
     if (fixes != null) {
       for (final Annotation.QuickFixInfo quickFixInfo : fixes) {
         TextRange range = fixedRange != null ? fixedRange : quickFixInfo.textRange;
         HighlightDisplayKey key = quickFixInfo.key != null
                                   ? quickFixInfo.key
-                                  : HighlightDisplayKey.find(DefaultHighlightVisitorBasedInspection.AnnotatorBasedInspection.ANNOTATOR_SHORT_NAME);
-        QuickFixAction.registerQuickFixAction(info, range, quickFixInfo.quickFix, key);
+                                  : HighlightDisplayKey.find(ANNOTATOR_INSPECTION_SHORT_NAME);
+        info.registerFix(quickFixInfo.quickFix, null, HighlightDisplayKey.getDisplayNameByKey(key), range, key);
       }
     }
   }
@@ -821,7 +825,7 @@
           ContainerUtil.addAll(newOptions, ContainerUtil.map(suppressActions, new Function<SuppressQuickFix, IntentionAction>() {
             @Override
             public IntentionAction fun(SuppressQuickFix fix) {
-              return InspectionManagerEx.convertBatchToSuppressIntentionAction(fix);
+              return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction(fix);
             }
           }));
         }
@@ -888,4 +892,32 @@
     if (!highlighter.isValid()) return "";
     return highlighter.getDocument().getText(TextRange.create(highlighter));
   }
+
+  public void registerFix(@Nullable IntentionAction action,
+                          @Nullable List<IntentionAction> options,
+                          @Nullable String displayName,
+                          @Nullable TextRange fixRange,
+                          @Nullable HighlightDisplayKey key) {
+    if (action == null) return;
+    if (fixRange == null) fixRange = new TextRange(startOffset, endOffset);
+    if (quickFixActionRanges == null) {
+      quickFixActionRanges = ContainerUtil.createLockFreeCopyOnWriteList();
+    }
+    IntentionActionDescriptor desc = new IntentionActionDescriptor(action, options, displayName, null, key, getProblemGroup());
+    quickFixActionRanges.add(Pair.create(desc, fixRange));
+    fixStartOffset = Math.min (fixStartOffset, fixRange.getStartOffset());
+    fixEndOffset = Math.max (fixEndOffset, fixRange.getEndOffset());
+    if (action instanceof HintAction) {
+      setHint(true);
+    }
+  }
+
+  public void unregisterQuickFix(@NotNull Condition<IntentionAction> condition) {
+    for (Iterator<Pair<IntentionActionDescriptor, TextRange>> it = quickFixActionRanges.iterator(); it.hasNext();) {
+      Pair<IntentionActionDescriptor, TextRange> pair = it.next();
+      if (condition.value(pair.first.getAction())) {
+        it.remove();
+      }
+    }
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
index 9cc91a3..2470e0d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
@@ -681,7 +681,7 @@
     if (((ProblemDescriptorBase)descriptor).getEnforcedTextAttributes() != null) {
       needEmptyAction = false;
     }
-    if (needEmptyAction && emptyActionRegistered.add(Pair.create(new TextRange(highlightInfo.fixStartOffset, highlightInfo.fixEndOffset), tool.getShortName()))) {
+    if (needEmptyAction && emptyActionRegistered.add(Pair.<TextRange, String>create(highlightInfo.getFixTextRange(), tool.getShortName()))) {
       EmptyIntentionAction emptyIntentionAction = new EmptyIntentionAction(tool.getDisplayName());
       QuickFixAction.registerQuickFixAction(highlightInfo, emptyIntentionAction, key);
     }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java
index e30b8e0..6484893 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java
@@ -18,7 +18,6 @@
 
 import com.intellij.codeHighlighting.TextEditorHighlightingPass;
 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
-import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
 import com.intellij.codeInsight.hint.HintManager;
 import com.intellij.codeInsight.intention.AbstractIntentionAction;
 import com.intellij.codeInsight.intention.IntentionAction;
@@ -40,6 +39,7 @@
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.progress.ProgressIndicator;
@@ -50,6 +50,7 @@
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.PairProcessor;
@@ -74,6 +75,62 @@
   private volatile boolean myShowBulb;
   private volatile boolean myHasToRecreate;
 
+  @NotNull
+  public static List<HighlightInfo.IntentionActionDescriptor> getAvailableActions(@NotNull final Editor editor, @NotNull final PsiFile file, final int passId) {
+    final int offset = editor.getCaretModel().getOffset();
+    final Project project = file.getProject();
+
+    final List<HighlightInfo.IntentionActionDescriptor> result = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
+    DaemonCodeAnalyzerImpl.processHighlightsNearOffset(editor.getDocument(), project, HighlightSeverity.INFORMATION, offset, true, new Processor<HighlightInfo>() {
+      @Override
+      public boolean process(HighlightInfo info) {
+        addAvailableActionsForGroups(info, editor, file, result, passId, offset);
+        return true;
+      }
+    });
+    return result;
+  }
+
+  private static void addAvailableActionsForGroups(@NotNull HighlightInfo info,
+                                                   @NotNull Editor editor,
+                                                   @NotNull PsiFile file,
+                                                   @NotNull List<HighlightInfo.IntentionActionDescriptor> outList,
+                                                   int group,
+                                                   int offset) {
+    if (info.quickFixActionMarkers == null) return;
+    if (group != -1 && group != info.getGroup()) return;
+    Editor injectedEditor = null;
+    PsiFile injectedFile = null;
+    for (Pair<HighlightInfo.IntentionActionDescriptor, RangeMarker> pair : info.quickFixActionMarkers) {
+      HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
+      RangeMarker range = pair.second;
+      if (!range.isValid()) continue;
+      int start = range.getStartOffset();
+      int end = range.getEndOffset();
+      final Project project = file.getProject();
+      if (start > offset || offset > end) {
+        continue;
+      }
+      Editor editorToUse;
+      PsiFile fileToUse;
+      if (info.isFromInjection()) {
+        if (injectedEditor == null) {
+          injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset);
+          injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
+        }
+        editorToUse = injectedEditor;
+        fileToUse = injectedFile;
+      }
+      else {
+        editorToUse = editor;
+        fileToUse = file;
+      }
+      if (actionInGroup.getAction().isAvailable(project, editorToUse, fileToUse)) {
+        outList.add(actionInGroup);
+      }
+    }
+  }
+
   public static class IntentionsInfo {
     public final List<HighlightInfo.IntentionActionDescriptor> intentionsToShow = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
     public final List<HighlightInfo.IntentionActionDescriptor> errorFixesToShow = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
@@ -114,7 +171,7 @@
     myEditor = editor;
 
     PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
-    
+
     myFile = documentManager.getPsiFile(myEditor.getDocument());
     assert myFile != null : FileDocumentManager.getInstance().getFile(myEditor.getDocument());
   }
@@ -202,7 +259,7 @@
     int offset = hostEditor.getCaretModel().getOffset();
     Project project = hostFile.getProject();
 
-    List<HighlightInfo.IntentionActionDescriptor> fixes = QuickFixAction.getAvailableActions(hostEditor, hostFile, passIdToShowIntentionsFor);
+    List<HighlightInfo.IntentionActionDescriptor> fixes = getAvailableActions(hostEditor, hostFile, passIdToShowIntentionsFor);
     final DaemonCodeAnalyzer codeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
     final Document hostDocument = hostEditor.getDocument();
     HighlightInfo infoAtCursor = ((DaemonCodeAnalyzerImpl)codeAnalyzer).findHighlightByOffset(hostDocument, offset, true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java
index 4e41c37..e2d5df0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java
@@ -449,11 +449,11 @@
           }
           info.quickFixActionMarkers = ContainerUtil.createLockFreeCopyOnWriteList(list);
         }
-        if (finalInfoRange.equalsToRange(info.fixStartOffset, info.fixEndOffset)) {
+        ProperTextRange fixRange = info.getFixTextRange();
+        if (finalInfoRange.equals(fixRange)) {
           info.fixMarker = null; // null means it the same as highlighter'
         }
         else {
-          TextRange fixRange = new TextRange(info.fixStartOffset, info.fixEndOffset);
           info.fixMarker = getOrCreate(document, ranges2markersCache, fixRange);
         }
       }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java
index 6525bea..671f58b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java
@@ -17,25 +17,14 @@
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
 import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInspection.HintAction;
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.RangeMarker;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
-import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -54,114 +43,27 @@
     registerQuickFixAction(info, null, action);
   }
 
-  public static void registerQuickFixActions(@Nullable final HighlightInfo info, @NotNull final Collection<? extends IntentionAction> actions) {
-    for (IntentionAction action : actions) {
-      registerQuickFixAction(info, action);
-    }
-  }
-
   /** This is used by TeamCity plugin */
   @Deprecated
-  public static void registerQuickFixAction(@Nullable HighlightInfo info, @Nullable IntentionAction action, @Nullable List<IntentionAction> options, @Nullable String displayName) {
-    doRegister(info, action, options, displayName, null, null);
+  public static void registerQuickFixAction(@Nullable HighlightInfo info,
+                                            @Nullable IntentionAction action,
+                                            @Nullable List<IntentionAction> options,
+                                            @Nullable String displayName) {
+    if (info == null) return;
+    info.registerFix(action, options, displayName, null, null);
   }
 
-  private static void doRegister(@Nullable HighlightInfo info,
-                                 @Nullable IntentionAction action,
-                                 @Nullable List<IntentionAction> options,
-                                 @Nullable String displayName,
-                                 @Nullable TextRange fixRange,
-                                 @Nullable HighlightDisplayKey key) {
-    if (info == null || action == null) return;
-    if (fixRange == null) fixRange = new TextRange(info.startOffset, info.endOffset);
-    if (info.quickFixActionRanges == null) {
-      info.quickFixActionRanges = ContainerUtil.createLockFreeCopyOnWriteList();
-    }
-    HighlightInfo.IntentionActionDescriptor desc = new HighlightInfo.IntentionActionDescriptor(action, options, displayName, null, key, info.getProblemGroup());
-    info.quickFixActionRanges.add(Pair.create(desc, fixRange));
-    info.fixStartOffset = Math.min (info.fixStartOffset, fixRange.getStartOffset());
-    info.fixEndOffset = Math.max (info.fixEndOffset, fixRange.getEndOffset());
-    if (action instanceof HintAction) {
-      info.setHint(true);
-    }
-  }
 
   public static void registerQuickFixAction(@Nullable HighlightInfo info,
                                             @Nullable TextRange fixRange,
                                             @Nullable IntentionAction action,
                                             @Nullable final HighlightDisplayKey key) {
-    doRegister(info, action, null, HighlightDisplayKey.getDisplayNameByKey(key), fixRange, key);
+    if (info == null) return;
+    info.registerFix(action, null, HighlightDisplayKey.getDisplayNameByKey(key), fixRange, key);
   }
 
   public static void registerQuickFixAction(@Nullable HighlightInfo info, @Nullable TextRange fixRange, @Nullable IntentionAction action) {
-    doRegister(info, action, null, null, fixRange, null);
-  }
-
-  public static void unregisterQuickFixAction(@NotNull HighlightInfo info, Condition<IntentionAction> condition) {
-    for (Iterator<Pair<HighlightInfo.IntentionActionDescriptor, TextRange>> it = info.quickFixActionRanges.iterator(); it.hasNext();) {
-      Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair = it.next();
-      if (condition.value(pair.first.getAction())) {
-        it.remove();
-      }
-    }
-  }
-
-  /**
-   * Is invoked inside atomic action.
-   */
-  @NotNull
-  public static List<HighlightInfo.IntentionActionDescriptor> getAvailableActions(@NotNull final Editor editor, @NotNull final PsiFile file, final int passId) {
-    final int offset = editor.getCaretModel().getOffset();
-    final Project project = file.getProject();
-
-    final List<HighlightInfo.IntentionActionDescriptor> result = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
-    DaemonCodeAnalyzerImpl.processHighlightsNearOffset(editor.getDocument(), project, HighlightSeverity.INFORMATION, offset, true, new Processor<HighlightInfo>() {
-      @Override
-      public boolean process(HighlightInfo info) {
-        addAvailableActionsForGroups(info, editor, file, result, passId, offset);
-        return true;
-      }
-    });
-    return result;
-  }
-
-  private static void addAvailableActionsForGroups(@NotNull HighlightInfo info,
-                                                   @NotNull Editor editor,
-                                                   @NotNull PsiFile file,
-                                                   @NotNull List<HighlightInfo.IntentionActionDescriptor> outList,
-                                                   int group,
-                                                   int offset) {
-    if (info.quickFixActionMarkers == null) return;
-    if (group != -1 && group != info.getGroup()) return;
-    Editor injectedEditor = null;
-    PsiFile injectedFile = null;
-    for (Pair<HighlightInfo.IntentionActionDescriptor, RangeMarker> pair : info.quickFixActionMarkers) {
-      HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
-      RangeMarker range = pair.second;
-      if (!range.isValid()) continue;
-      int start = range.getStartOffset();
-      int end = range.getEndOffset();
-      final Project project = file.getProject();
-      if (start > offset || offset > end) {
-        continue;
-      }
-      Editor editorToUse;
-      PsiFile fileToUse;
-      if (info.isFromInjection()) {
-        if (injectedEditor == null) {
-          injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset);
-          injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
-        }
-        editorToUse = injectedEditor;
-        fileToUse = injectedFile;
-      }
-      else {
-        editorToUse = editor;
-        fileToUse = file;
-      }
-      if (actionInGroup.getAction().isAvailable(project, editorToUse, fileToUse)) {
-        outList.add(actionInGroup);
-      }
-    }
+    if (info == null) return;
+    info.registerFix(action, null, null, fixRange, null);
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixActionRegistrarImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixActionRegistrarImpl.java
index 3890dd4..3a44379 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixActionRegistrarImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixActionRegistrarImpl.java
@@ -45,7 +45,7 @@
   @Override
   public void unregister(@NotNull Condition<IntentionAction> condition) {
     if (myInfo != null) {
-      QuickFixAction.unregisterQuickFixAction(myInfo, condition);
+      myInfo.unregisterQuickFix(condition);
     }
   }
 }
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 3892391..80aec67 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
 import com.intellij.codeInsight.AutoPopupController;
 import com.intellij.codeInsight.CodeInsightSettings;
 import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.completion.CompletionContributor;
 import com.intellij.codeInsight.highlighting.BraceMatcher;
 import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
 import com.intellij.codeInsight.highlighting.NontrivialBraceMatcher;
@@ -61,6 +62,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class TypedHandler extends TypedActionHandlerBase {
@@ -173,7 +175,7 @@
     }
 
     if (!handled) {
-      autoPopupCompletion(editor, charTyped, project);
+      autoPopupCompletion(editor, charTyped, project, file);
       autoPopupParameterInfo(editor, charTyped, project, file);
     }
 
@@ -248,12 +250,26 @@
     }
   }
 
-  public static void autoPopupCompletion(Editor editor, char charTyped, Project project) {
-    if (charTyped == '.') {
+  public static void autoPopupCompletion(Editor editor, char charTyped, Project project, PsiFile file) {
+    if (charTyped == '.' || isAutoPopup(editor, file, charTyped)) {
       AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
     }
   }
 
+  private static boolean isAutoPopup(Editor editor, PsiFile file, char charTyped) {
+    final int offset = editor.getCaretModel().getOffset() - 1;
+    if (offset >= 0) {
+      final PsiElement element = file.findElementAt(offset);
+      if (element != null) {
+        final List<CompletionContributor> list = CompletionContributor.forLanguage(element.getLanguage());
+        for (CompletionContributor contributor : list) {
+          if (contributor.invokeAutoPopup(element, charTyped)) return true;
+        }
+      }
+    }
+    return false;
+  }
+
   private static boolean isInsideStringLiteral(final Editor editor, final PsiFile file) {
     int offset = editor.getCaretModel().getOffset();
     PsiElement element = file.findElementAt(offset);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java
index 9d0a8d4..be95eed 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -118,7 +118,7 @@
     }
 
     lookup.hide();
-    TypedHandler.autoPopupCompletion(editor, charTyped, project);
+    TypedHandler.autoPopupCompletion(editor, charTyped, project, file);
     return Result.CONTINUE;
   }
 
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java b/platform/lang-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
new file mode 100644
index 0000000..d90efd7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
@@ -0,0 +1,68 @@
+/*
+ * 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.intellij.codeInspection;
+
+import com.intellij.codeInsight.daemon.impl.actions.AbstractBatchSuppressByNoInspectionCommentFix;
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+public class SuppressIntentionActionFromFix extends SuppressIntentionAction {
+  private final SuppressQuickFix myFix;
+
+  private SuppressIntentionActionFromFix(@NotNull SuppressQuickFix fix) {
+    myFix = fix;
+  }
+
+  @NotNull
+  public static SuppressIntentionAction convertBatchToSuppressIntentionAction(@NotNull final SuppressQuickFix fix) {
+    return new SuppressIntentionActionFromFix(fix);
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+    PsiElement container = myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
+                           ? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
+    boolean caretWasBeforeStatement = editor != null && container != null && editor.getCaretModel().getOffset() == container.getTextRange().getStartOffset();
+    InspectionManager inspectionManager = InspectionManager.getInstance(project);
+    ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(element, element, "", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
+    myFix.applyFix(project, descriptor);
+
+    if (caretWasBeforeStatement) {
+      editor.getCaretModel().moveToOffset(container.getTextRange().getStartOffset());
+    }
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
+    return myFix.isAvailable(project, element);
+  }
+
+  @NotNull
+  @Override
+  public String getText() {
+    return myFix.getName();
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return myFix.getFamilyName();
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java b/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java
index 2610b38..b17e2f0 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java
@@ -28,8 +28,10 @@
 import com.intellij.openapi.project.ModuleAdapter;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
@@ -37,6 +39,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -51,19 +54,23 @@
 public final class ModuleRunConfigurationManager extends ModuleAdapter implements ModuleComponent, PersistentStateComponent<Element> {
   private static final Logger LOG = Logger.getInstance(ModuleRunConfigurationManager.class);
   @NonNls static final String COMPONENT_NAME = "ModuleRunConfigurationManager";
-
-  final Object myRemoverKey;
+  @NotNull
+  private final Condition<RunnerAndConfigurationSettings> myModuleConfigCondition = new Condition<RunnerAndConfigurationSettings>() {
+    @Override
+    public boolean value(@Nullable RunnerAndConfigurationSettings settings) {
+      return settings != null && usesMyModule(settings.getConfiguration());
+    }
+  };
   @NotNull
   private final Module myModule;
   @NotNull
-  final RunManagerImpl myManager;
+  private final RunManagerImpl myManager;
   @Nullable
   private List<Element> myUnloadedElements = null;
 
   public ModuleRunConfigurationManager(@NotNull final Module module, @NotNull final RunManagerImpl runManager) {
     myModule = module;
     myManager = runManager;
-    myRemoverKey = new Object();
   }
 
   @Override
@@ -118,6 +125,11 @@
     }
   }
 
+  @NotNull
+  private Collection<? extends RunnerAndConfigurationSettings> getModuleRunConfigurationSettings() {
+    return ContainerUtil.filter(myManager.getConfigurationSettings(), myModuleConfigCondition);
+  }
+
   private boolean usesMyModule(RunConfiguration config) {
     return config instanceof ModuleBasedConfiguration
            && myModule.equals(((ModuleBasedConfiguration)config).getConfigurationModule().getModule());
@@ -125,7 +137,7 @@
 
   public void writeExternal(@NotNull final Element element) throws WriteExternalException {
     LOG.debug("writeExternal(" + myModule + ")");
-    for (final RunnerAndConfigurationSettings settings : myManager.getExternalSettings(myRemoverKey)) {
+    for (final RunnerAndConfigurationSettings settings : getModuleRunConfigurationSettings()) {
       myManager.addConfigurationElement(element, settings);
     }
     if (myUnloadedElements != null) {
@@ -142,7 +154,7 @@
 
     final List children = element.getChildren();
     for (final Object child : children) {
-      final RunnerAndConfigurationSettings configuration = myManager.loadConfiguration(myRemoverKey, (Element)child, true);
+      final RunnerAndConfigurationSettings configuration = myManager.loadConfiguration((Element)child, true);
       if (configuration == null && Comparing.strEqual(element.getName(), RunManagerImpl.CONFIGURATION)) {
         if (myUnloadedElements == null) myUnloadedElements = new ArrayList<Element>(2);
         myUnloadedElements.add(element);
@@ -168,9 +180,12 @@
   }
 
   @Override
-  public void moduleRemoved(Project project, Module module) {
+  public void beforeModuleRemoved(Project project, Module module) {
     if (myModule.equals(module)) {
-      myManager.removeExternalSettings(myRemoverKey);
+      LOG.debug("time to remove something from project (" + project + ")");
+      for (final RunnerAndConfigurationSettings settings : getModuleRunConfigurationSettings()) {
+        myManager.removeConfiguration(settings);
+      }
     }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
index f645686..2143665 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,6 +23,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector;
 import com.intellij.openapi.util.*;
 import com.intellij.ui.IconDeferrer;
 import com.intellij.util.EventDispatcher;
@@ -49,8 +50,6 @@
     new HashMap<String, RunnerAndConfigurationSettings>();
   private final Map<String, RunnerAndConfigurationSettings> myConfigurations =
     new LinkedHashMap<String, RunnerAndConfigurationSettings>(); // template configurations are not included here
-  final Map<Object, List<RunnerAndConfigurationSettings>> myExternalSettings =
-    new java.util.HashMap<Object, List<RunnerAndConfigurationSettings>>();
   private final Map<String, Boolean> mySharedConfigurations = new TreeMap<String, Boolean>();
   private final Map<RunConfiguration, List<BeforeRunTask>> myConfigurationToBeforeTasksMap = new WeakHashMap<RunConfiguration, List<BeforeRunTask>>();
 
@@ -224,11 +223,6 @@
   }
 
   @NotNull
-  public List<RunnerAndConfigurationSettings> getExternalSettings(@NotNull Object key) {
-    return myExternalSettings.containsKey(key) ? myExternalSettings.get(key) : Collections.<RunnerAndConfigurationSettings>emptyList();
-  }
-
-  @NotNull
   @Override
   public List<RunnerAndConfigurationSettings> getAllSettings() {
     return Collections.unmodifiableList(new ArrayList<RunnerAndConfigurationSettings>(getSortedConfigurations()));
@@ -403,9 +397,6 @@
   @Override
   public void removeConfiguration(@Nullable RunnerAndConfigurationSettings settings) {
     if (settings == null) return;
-    for (Map.Entry<Object, List<RunnerAndConfigurationSettings>> entry : myExternalSettings.entrySet()) {
-      if (entry.getValue().remove(settings)) break;
-    }
 
     for (Iterator<RunnerAndConfigurationSettings> it = getSortedConfigurations().iterator(); it.hasNext(); ) {
       final RunnerAndConfigurationSettings configuration = it.next();
@@ -786,21 +777,8 @@
     fireRunConfigurationsRemoved(configurations);
   }
 
-  public void removeExternalSettings(@NotNull Object removerKey) {
-    List<RunnerAndConfigurationSettings> settingsList = getExternalSettings(removerKey);
-    for (RunnerAndConfigurationSettings each : settingsList) {
-      removeConfiguration(each);
-    }
-    myExternalSettings.remove(removerKey);
-  }
-
   @Nullable
   public RunnerAndConfigurationSettings loadConfiguration(final Element element, boolean isShared) throws InvalidDataException {
-    return loadConfiguration(null, element, isShared);
-  }
-
-  @Nullable
-  public RunnerAndConfigurationSettings loadConfiguration(@Nullable final Object removerKey, final Element element, boolean isShared) throws InvalidDataException {
     final RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this);
     settings.readExternal(element);
     ConfigurationFactory factory = settings.getFactory();
@@ -808,13 +786,6 @@
       return null;
     }
 
-    if (removerKey !=null) {
-      if (!myExternalSettings.containsKey(removerKey)) {
-        myExternalSettings.put(removerKey, new ArrayList<RunnerAndConfigurationSettings>());
-      }
-      myExternalSettings.get(removerKey).add(settings);
-    }
-
     final Element methodsElement = element.getChild(METHOD);
     final List<BeforeRunTask> tasks = readStepsBeforeRun(methodsElement, settings);
     if (settings.isTemplate()) {
@@ -857,7 +828,15 @@
 
   @Nullable
   public ConfigurationFactory getFactory(final String typeName, String factoryName) {
+    return getFactory(typeName, factoryName, false);
+  }
+
+  @Nullable
+  public ConfigurationFactory getFactory(final String typeName, String factoryName, boolean checkUnknown) {
     final ConfigurationType type = myTypesByName.get(typeName);
+    if (type == null && checkUnknown && typeName != null) {
+      UnknownFeaturesCollector.getInstance(myProject).registerUnknownRunConfiguration(typeName);
+    }
     if (factoryName == null) {
       factoryName = type != null ? type.getConfigurationFactories()[0].getName() : null;
     }
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
index f0d6aa1e..55bdd85 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -188,7 +188,7 @@
   private ConfigurationFactory getFactory(final Element element) {
     final String typeName = element.getAttributeValue(CONFIGURATION_TYPE_ATTRIBUTE);
     String factoryName = element.getAttributeValue(FACTORY_NAME_ATTRIBUTE);
-    return myManager.getFactory(typeName, factoryName);
+    return myManager.getFactory(typeName, factoryName, !myIsTemplate);
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/find/actions/CompositeActiveComponent.java b/platform/lang-impl/src/com/intellij/find/actions/CompositeActiveComponent.java
index 8697eb0..a06fb74 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/CompositeActiveComponent.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/CompositeActiveComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -28,7 +28,8 @@
   public CompositeActiveComponent(@NotNull ActiveComponent... components) {
     myComponents = components;
 
-    myComponent = new JPanel(new FlowLayout());
+    myComponent = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 0));
+    myComponent.setBorder(null);
     myComponent.setOpaque(false);
     for (ActiveComponent component : components) {
       myComponent.add(component.getComponent());
diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
index 02e99eb..1572fd3 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -636,31 +636,14 @@
         return processIcon;
       }
     };
-    builder.setCommandButton(new CompositeActiveComponent(spinningProgress, settingsButton));
+    final DefaultActionGroup pinGroup = new DefaultActionGroup();
+    final ActiveComponent pin = createPinButton(descriptor, usageView, options, popup, pinGroup);
+    builder.setCommandButton(new CompositeActiveComponent(spinningProgress, settingsButton, pin));
 
     DefaultActionGroup toolbar = new DefaultActionGroup();
     usageView.addFilteringActions(toolbar);
 
-    toolbar.add(UsageGroupingRuleProviderImpl.createGroupByFileStructureAction(usageView));
-    toolbar.add(new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", AllIcons.Toolwindows.ToolWindowFind) {
-      {
-        AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_FIND_USAGES);
-        setShortcutSet(action.getShortcutSet());
-      }
-      @Override
-      public void actionPerformed(AnActionEvent e) {
-        hideHints();
-        popup[0].cancel();
-        FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager();
-        FindUsagesManager.SearchData data = new FindUsagesManager.SearchData();
-        data.myOptions = options;
-        List<SmartPsiElementPointer<PsiElement>> plist = descriptor.getAllElementPointers();
-
-        data.myElements = plist.toArray(new SmartPsiElementPointer[plist.size()]);
-        findUsagesManager.rerunAndRecallFromHistory(data);
-      }
-    });
-
+    toolbar.add(UsageGroupingRuleProviderImpl.createGroupByFileStructureAction(usageView)); 
     ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.USAGE_VIEW_TOOLBAR, toolbar, true);
     actionToolbar.setReservePlaceAutoPopupIcon(false);
     final JComponent toolBar = actionToolbar.getComponent();
@@ -679,9 +662,56 @@
       action.registerCustomShortcutSet(action.getShortcutSet(), content);
     }
 
+    for (AnAction action : pinGroup.getChildren(null)) {
+      action.unregisterCustomShortcutSet(usageView.getComponent());
+      action.registerCustomShortcutSet(action.getShortcutSet(), content);
+    }
+
     return popup[0];
   }
 
+  private ActiveComponent createPinButton(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
+                                          final UsageViewImpl usageView,
+                                          final FindUsagesOptions options, final JBPopup[] popup, DefaultActionGroup pinGroup) {
+    final AnAction pinAction =
+      new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", AllIcons.General.AutohideOff) {
+        {
+          AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_FIND_USAGES);
+          setShortcutSet(action.getShortcutSet());
+        }
+
+        @Override
+        public void actionPerformed(AnActionEvent e) {
+          hideHints();
+          popup[0].cancel();
+          FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager();
+          FindUsagesManager.SearchData data = new FindUsagesManager.SearchData();
+          data.myOptions = options;
+          List<SmartPsiElementPointer<PsiElement>> plist = descriptor.getAllElementPointers();
+
+          data.myElements = plist.toArray(new SmartPsiElementPointer[plist.size()]);
+          findUsagesManager.rerunAndRecallFromHistory(data);
+        }
+      };
+    pinGroup.add(pinAction);
+    final ActionToolbar pinToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.USAGE_VIEW_TOOLBAR, pinGroup, true);
+    pinToolbar.setReservePlaceAutoPopupIcon(false);
+    final JComponent pinToolBar = pinToolbar.getComponent();
+    pinToolBar.setBorder(null);
+    pinToolBar.setOpaque(false);
+
+    return new ActiveComponent() {
+      @Override
+      public void setActive(boolean active) {
+      }
+
+      @Override
+      public JComponent getComponent() {
+        return pinToolBar;
+      }
+    };
+  }
+
   @NotNull
   private static String getFullTitle(@NotNull List<Usage> usages,
                                      @NotNull String title,
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 7febef7..4847d13 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -24,6 +24,7 @@
 import com.intellij.find.*;
 import com.intellij.find.findUsages.FindUsagesManager;
 import com.intellij.find.impl.livePreview.SearchResults;
+import com.intellij.ide.highlighter.custom.CustomFileHighlighter;
 import com.intellij.lang.Language;
 import com.intellij.lang.LanguageParserDefinitions;
 import com.intellij.lang.ParserDefinition;
@@ -48,6 +49,7 @@
 import com.intellij.openapi.fileTypes.LanguageFileType;
 import com.intellij.openapi.fileTypes.SyntaxHighlighter;
 import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.openapi.fileTypes.impl.AbstractFileType;
 import com.intellij.openapi.keymap.KeymapUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ProjectManager;
@@ -437,53 +439,65 @@
       lang = ((LanguageFileType)ftype).getLanguage();
     }
 
-    if(lang == null) return NOT_FOUND_RESULT;
-
     CommentsLiteralsSearchData data = model.getUserData(ourCommentsLiteralsSearchDataKey);
     if (data == null || !Comparing.equal(data.lastFile, file)) {
-      SyntaxHighlighter lexer = getHighlighter(file, lang);
+      SyntaxHighlighter lexer;
 
       TokenSet tokensOfInterest = TokenSet.EMPTY;
-      final Language finalLang = lang;
-      Set<Language> relevantLanguages = ApplicationManager.getApplication().runReadAction(new Computable<Set<Language>>() {
-        @Override
-        public Set<Language> compute() {
-          THashSet<Language> result = new THashSet<Language>();
+      Set<Language> relevantLanguages = null;
+      if (lang != null) {
+        lexer = getHighlighter(file, lang);
+        final Language finalLang = lang;
+        relevantLanguages = ApplicationManager.getApplication().runReadAction(new Computable<Set<Language>>() {
+          @Override
+          public Set<Language> compute() {
+            THashSet<Language> result = new THashSet<Language>();
 
-          for(Project project:ProjectManager.getInstance().getOpenProjects()) {
-            FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
-            if (viewProvider != null) {
-              result.addAll(viewProvider.getLanguages());
-              break;
+            for(Project project: ProjectManager.getInstance().getOpenProjects()) {
+              FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
+              if (viewProvider != null) {
+                result.addAll(viewProvider.getLanguages());
+                break;
+              }
             }
+
+            if (result.isEmpty()) {
+              result.add(finalLang);
+            }
+            return result;
+          }
+        });
+
+        for (Language relevantLanguage:relevantLanguages) {
+          tokensOfInterest = addTokenTypesForLanguage(model, relevantLanguage, tokensOfInterest);
+        }
+
+        if(model.isInStringLiteralsOnly()) {
+          // TODO: xml does not have string literals defined so we add XmlAttributeValue element type as convenience
+          final Lexer xmlLexer = getHighlighter(null, Language.findLanguageByID("XML")).getHighlightingLexer();
+          final String marker = "xxx";
+          xmlLexer.start("<a href=\"" + marker+ "\" />");
+
+          while (!marker.equals(xmlLexer.getTokenText())) {
+            xmlLexer.advance();
+            if (xmlLexer.getTokenType() == null) break;
           }
 
-          if (result.isEmpty()) {
-            result.add(finalLang);
+          IElementType convenienceXmlAttrType = xmlLexer.getTokenType();
+          if (convenienceXmlAttrType != null) {
+            tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(convenienceXmlAttrType));
           }
-          return result;
         }
-      });
-
-      for (Language relevantLanguage:relevantLanguages) {
-        tokensOfInterest = addTokenTypesForLanguage(model, relevantLanguage, tokensOfInterest);
-      }
-
-      if(model.isInStringLiteralsOnly()) {
-        // TODO: xml does not have string literals defined so we add XmlAttributeValue element type as convenience
-        final Lexer xmlLexer = getHighlighter(null, Language.findLanguageByID("XML")).getHighlightingLexer();
-        final String marker = "xxx";
-        xmlLexer.start("<a href=\"" + marker+ "\" />");
-
-        while (!marker.equals(xmlLexer.getTokenText())) {
-          xmlLexer.advance();
-          if (xmlLexer.getTokenType() == null) break;
+      } else if (ftype instanceof AbstractFileType) {
+        if (model.isInCommentsOnly()) {
+          tokensOfInterest = TokenSet.create(CustomHighlighterTokenType.LINE_COMMENT, CustomHighlighterTokenType.MULTI_LINE_COMMENT);
         }
-
-        IElementType convenienceXmlAttrType = xmlLexer.getTokenType();
-        if (convenienceXmlAttrType != null) {
-          tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(convenienceXmlAttrType));
+        if (model.isInStringLiteralsOnly()) {
+          tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(CustomHighlighterTokenType.STRING, CustomHighlighterTokenType.SINGLE_QUOTED_STRING));
         }
+        lexer = new CustomFileHighlighter(((AbstractFileType)ftype).getSyntaxTable());
+      } else {
+        return NOT_FOUND_RESULT;
       }
 
       Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null;
@@ -493,7 +507,7 @@
     }
 
     final Lexer lexer = data.highlighter.getHighlightingLexer();
-    lexer.start(text, data.startOffset, text.length(), 0);
+    lexer.start(text, model.isForward() && data.startOffset < offset ? data.startOffset : 0, text.length(), 0);
 
     IElementType tokenType;
     TokenSet tokens = data.tokensOfInterest;
@@ -506,21 +520,40 @@
       if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart();
 
       final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType);
-      if (tokens.contains(tokenType) || (model.isInStringLiteralsOnly() && isHighlightedAsString(keys))) {
+
+      if (tokens.contains(tokenType) ||
+          (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) ||
+          (model.isInCommentsOnly() && isHighlightedAsDocComment(keys))
+        ) {
 
         int start = lexer.getTokenStart();
 
-        if (start >= offset || !scanningForward) {
+        while(true) {
           FindResultImpl findResult = null;
 
           if (data.searcher != null) {
             int i = data.searcher.scan(text, textArray, start, lexer.getTokenEnd());
-            if (i != -1) findResult = new FindResultImpl(i, i + model.getStringToFind().length());
+
+            if (i != -1 && i >= start) {
+              final int matchEnd = i + model.getStringToFind().length();
+              if (start >= offset || !scanningForward)
+                findResult = new FindResultImpl(i, matchEnd);
+              else {
+                start = matchEnd;
+                continue;
+              }
+            }
           } else {
             data.matcher.reset(text.subSequence(start, lexer.getTokenEnd()));
             if (data.matcher.find()) {
-              int matchStart = data.matcher.start();
-              findResult = new FindResultImpl(start + matchStart, start + data.matcher.end());
+              final int matchEnd = start + data.matcher.end();
+              if (start >= offset || !scanningForward) {
+                findResult = new FindResultImpl(start + data.matcher.start(), matchEnd);
+              }
+              else {
+                start = matchEnd;
+                continue;
+              }
             }
           }
 
@@ -529,10 +562,14 @@
               data.startOffset = lastGoodOffset;
               return findResult;
             } else {
-              if (start >= offset) return prevFindResult;
+
+              if (findResult.getStartOffset() >= offset) return prevFindResult;
               prevFindResult = findResult;
+              start = findResult.getEndOffset();
+              continue;
             }
           }
+          break;
         }
       } else {
         Language tokenLang = tokenType.getLanguage();
@@ -549,6 +586,19 @@
     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) {
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 a02e77f..cbdb43e 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -24,6 +24,7 @@
 import com.intellij.ide.ui.search.BooleanOptionDescription;
 import com.intellij.ide.ui.search.OptionDescription;
 import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
+import com.intellij.ide.util.DefaultPsiElementCellRenderer;
 import com.intellij.ide.util.gotoByName.*;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
@@ -33,6 +34,7 @@
 import com.intellij.openapi.application.AccessToken;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
 import com.intellij.openapi.keymap.KeymapUtil;
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.options.SearchableConfigurable;
@@ -42,9 +44,9 @@
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.util.ProgressIndicatorBase;
 import com.intellij.openapi.project.Project;
+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.PopupChooserBuilder;
 import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
@@ -55,11 +57,13 @@
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.codeStyle.MinusculeMatcher;
 import com.intellij.psi.codeStyle.NameUtil;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.ui.*;
 import com.intellij.ui.border.CustomLineBorder;
+import com.intellij.ui.components.JBList;
 import com.intellij.ui.components.JBScrollPane;
 import com.intellij.ui.components.OnOffButton;
 import com.intellij.util.Alarm;
@@ -80,6 +84,7 @@
 import java.awt.event.FocusEvent;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
+import java.lang.reflect.Field;
 import java.util.*;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -98,14 +103,30 @@
   private String[] myActions;
   private Component myFocusComponent;
   private JBPopup myPopup;
+  private int myLeftWidth;
+  private SearchListModel myListModel = new SearchListModel();
+  private TitleIndexes myTitleIndexes;
   private Map<String, String> myConfigurables = new HashMap<String, String>();
 
   private Alarm myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, ApplicationManager.getApplication());
-  private JList myList = new JList(); //don't use JBList here!!! todo[kb]
+  private JBList myList = new JBList(myListModel) {
+    {
+      setOpaque(false);
+    }
+    @Override
+    protected void paintComponent(Graphics g) {
+      g.setColor(getTitlePanelBackground());
+      g.fillRect(0, 0, myLeftWidth - 1, getHeight());
+      g.setColor(getSeparatorColor());
+      g.drawLine(myLeftWidth-1, 0, myLeftWidth-1, getHeight());
+      super.paintComponent(g);
+    }
+  };
   private AnActionEvent myActionEvent;
   private Component myContextComponent;
   private CalcThread myCalcThread;
   private static AtomicBoolean ourShiftCanBeUsed = new AtomicBoolean(false);
+  private ArrayList<VirtualFile> myAlreadyAddedFiles = new ArrayList<VirtualFile>();
 
   static {
     IdeEventQueue.getInstance().addPostprocessor(new IdeEventQueue.EventDispatcher() {
@@ -117,10 +138,11 @@
         return false;
       }
     }, null);
-
   }
 
   private int myTopHitsCount;
+  private int myInitialWidth;
+  private int myInitialHeight;
 
   public SearchEverywhereAction() {
     createSearchField();
@@ -155,25 +177,16 @@
       @Override
       protected void textChanged(DocumentEvent e) {
         final String pattern = editor.getText();
+        final int len = pattern.trim().length();
         myAlarm.cancelAllRequests();
         myAlarm.addRequest(new Runnable() {
           @Override
           public void run() {
-            if (StringUtil.isEmpty(pattern.trim())) {
-              //noinspection SSBasedInspection
-              SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                  if (myPopup != null && myPopup.isVisible()) {
-                    myPopup.cancel();
-                  }
-                }
-              });
-              return;
+            if (field != null && field.getTextEditor().hasFocus()) {
+              rebuildList(pattern);
             }
-            rebuildList(pattern);
           }
-        }, Registry.intValue("ide.goto.rebuild.delay"));
+        }, /*Registry.intValue("ide.goto.rebuild.delay")*/ len == 1 ? 400 : len == 2 ? 300 : len == 3 ? 250 : 30);
       }
     });
     editor.addFocusListener(new FocusAdapter() {
@@ -181,7 +194,7 @@
       public void focusGained(FocusEvent e) {
         field.setText("");
         field.getTextEditor().setForeground(UIUtil.getLabelForeground());
-
+        myTitleIndexes = new TitleIndexes();
         editor.setColumns(25);
         myFocusComponent = e.getOppositeComponent();
         //noinspection SSBasedInspection
@@ -193,6 +206,11 @@
             parent.repaint();
           }
         });
+        if (myPopup != null && myPopup.isVisible()) {
+          myPopup.cancel();
+          myPopup = null;
+        }
+        rebuildList("");
       }
 
       @Override
@@ -205,7 +223,10 @@
       @Override
       public void keyPressed(KeyEvent e) {
         int keyCode = e.getKeyCode();
-        if (keyCode == KeyEvent.VK_ESCAPE && (myPopup == null || !myPopup.isVisible())) {
+        if (keyCode == KeyEvent.VK_ESCAPE) {
+          if (myPopup != null && myPopup.isVisible()) {
+            myPopup.cancel();
+          }
           IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(editor);
           focusManager.requestDefaultFocus(true);
         }
@@ -225,13 +246,7 @@
       myCalcThread = null;
     }
     myAlarm.cancelAllRequests();
-    myList.setModel(new DefaultListModel());
-    myClassModel = null;
-    myFileModel = null;
-    myActionModel = null;
-    myClasses = null;
-    myFiles = null;
-    myActions = null;
+    myListModel.clear();
 
     //noinspection SSBasedInspection
     SwingUtilities.invokeLater(new Runnable() {
@@ -254,31 +269,35 @@
     }
     AccessToken token = ApplicationManager.getApplication().acquireReadActionLock();
     try {
-    if (value instanceof PsiElement) {
-      NavigationUtil.activateFileWithPsiElement((PsiElement)value, true);
-      return;
-    } else if (isVirtualFile(value)) {
-      OpenFileDescriptor navigatable = new OpenFileDescriptor(project, (VirtualFile)value);
-      if (navigatable.canNavigate()) {
-        navigatable.navigate(true);
+      if (value instanceof PsiElement) {
+        NavigationUtil.activateFileWithPsiElement((PsiElement)value, true);
         return;
       }
-    } else {
-      focusManager.requestDefaultFocus(true);
-      IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
-        @Override
-        public void run() {
-          if (value instanceof BooleanOptionDescription) {
-            final BooleanOptionDescription option = (BooleanOptionDescription)value;
-            option.setOptionState(!option.isOptionEnabled());
-          } else {
-            GotoActionAction.openOptionOrPerformAction(value, pattern, project, myContextComponent ,myActionEvent);
-          }
+      else if (isVirtualFile(value)) {
+        OpenFileDescriptor navigatable = new OpenFileDescriptor(project, (VirtualFile)value);
+        if (navigatable.canNavigate()) {
+          navigatable.navigate(true);
+          return;
         }
-      });
-      return;
+      }
+      else {
+        focusManager.requestDefaultFocus(true);
+        IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
+          @Override
+          public void run() {
+            if (value instanceof BooleanOptionDescription) {
+              final BooleanOptionDescription option = (BooleanOptionDescription)value;
+              option.setOptionState(!option.isOptionEnabled());
+            }
+            else {
+              GotoActionAction.openOptionOrPerformAction(value, pattern, project, myContextComponent, myActionEvent);
+            }
+          }
+        });
+        return;
+      }
     }
-    } finally {
+    finally {
       token.finish();
     }
     focusManager.requestDefaultFocus(true);
@@ -291,6 +310,7 @@
     final Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(field.getTextEditor()));
 
     assert project != null;
+    myRenderer.myProject = project;
     myCalcThread = new CalcThread(project, pattern);
     myCalcThread.start();
   }
@@ -339,7 +359,9 @@
       }
     };
     private String myLocationString;
+    private DefaultPsiElementCellRenderer myPsiRenderer = new DefaultPsiElementCellRenderer();
     private Icon myLocationIcon;
+    private Project myProject;
     private JPanel myMainPanel = new JPanel(new BorderLayout());
     private JLabel myTitle = new JLabel();
     private JPanel myLeftPanel = new JPanel(new BorderLayout()) {
@@ -353,11 +375,6 @@
         return new Dimension(myLeftWidth, super.getPreferredSize().height);
       }
     };
-    private int myLeftWidth;
-
-    public void setLeftWidth(int width) {
-      myLeftWidth = width;
-    }
 
     @Override
     public void clear() {
@@ -377,7 +394,16 @@
 
     @Override
     public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-      Component cmp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+      Component cmp;
+      PsiFile file;
+      myLocationString = null;
+      if (value instanceof VirtualFile && myProject != null && (file = PsiManager.getInstance(myProject).findFile((VirtualFile)value)) != null) {
+          cmp = new GotoFileCellRenderer(list.getWidth()).getListCellRendererComponent(list, file, index, isSelected, cellHasFocus);
+      } else if (value instanceof PsiElement) {
+        cmp = myPsiRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+      } else {
+        cmp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+      }
       if (myLocationString != null || value instanceof BooleanOptionDescription) {
         final JPanel panel = new JPanel(new BorderLayout());
         panel.add(cmp, BorderLayout.CENTER);
@@ -386,7 +412,8 @@
           final OnOffButton button = new OnOffButton();
           button.setSelected(((BooleanOptionDescription)value).isOptionEnabled());
           rightComponent = button;
-        } else {
+        }
+        else {
           rightComponent = myLocation.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
         }
         panel.add(rightComponent, BorderLayout.EAST);
@@ -394,55 +421,15 @@
       }
 
       cmp.setBackground(isSelected ? UIUtil.getListSelectionBackground() : getRightBackground());
-      String title = getTitle(index, value, index == 0 ? null : list.getModel().getElementAt(index -1));
+      String title = myTitleIndexes.getTitle(index);
       myTitle.setText(title == null ? "" : title);
       myLeftPanel.removeAll();
-      myLeftPanel.setBackground(new JBColor(Gray._242, JBColor.background()));
+      myLeftPanel.setBackground(getTitlePanelBackground());
       myMainPanel.removeAll();
       myLeftPanel.add(myTitle, BorderLayout.EAST);
       myMainPanel.add(myLeftPanel, BorderLayout.WEST);
       myMainPanel.add(cmp, BorderLayout.CENTER);
       return myMainPanel;
-      }
-
-    private Color getRightBackground() {
-      return UIUtil.isUnderAquaLookAndFeel() ? Gray._236 : UIUtil.getListBackground();
-    }
-
-
-    private String getTitle(int index, Object value, Object prevValue) {
-      if (index == 0 && myTopHitsCount > 0) {
-        return myTopHitsCount == 1 ? "Top Hit" : "Top Hits";
-      }
-      if (index < myTopHitsCount) {
-        return null;
-      }
-      if (index == myTopHitsCount) {
-        prevValue = null;
-      }
-      String gotoClass = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoClass"));
-      gotoClass = StringUtil.isEmpty(gotoClass) ? "Classes" : "Classes (" + gotoClass + ")";
-      String gotoFile = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoFile"));
-      gotoFile = StringUtil.isEmpty(gotoFile) ? "Files" : "Files (" + gotoFile + ")";
-      String gotoAction = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoAction"));
-      gotoAction = StringUtil.isEmpty(gotoAction) ? "Actions" : "Actions (" + gotoAction + ")";
-      String gotoSettings = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ShowSettings"));
-      gotoSettings = StringUtil.isEmpty(gotoAction) ? "Preferences" : "Preferences (" + gotoSettings + ")";
-      String toolWindows = "Tool Windows";
-      if (prevValue == null) { // firstElement
-        if (value instanceof PsiElement)return gotoClass;
-        if (isVirtualFile(value))return gotoFile;
-        if (isToolWindowAction(value)) return toolWindows;
-        if (isSetting(value)) return gotoSettings;
-        if (isActionValue(value))return gotoAction;
-        return gotoSettings;
-      } else {
-        if (!isVirtualFile(prevValue) && isVirtualFile(value)) return gotoFile;
-        if (!isSetting(prevValue) && isSetting(value)) return gotoSettings;
-        if (!isToolWindowAction(prevValue) && isToolWindowAction(value)) return toolWindows;
-        if ((!isActionValue(prevValue) || isToolWindowAction(prevValue)) && isActionValue(value)) return gotoAction;
-      }
-      return null;
     }
 
     @Override
@@ -457,7 +444,8 @@
         }
         else if (isVirtualFile(value)) {
           append(((VirtualFile)value).getName());
-        } else if (isActionValue(value)) {
+        }
+        else if (isActionValue(value)) {
           final Map.Entry actionWithParentGroup = value instanceof Map.Entry ? (Map.Entry)value : null;
           final AnAction anAction = actionWithParentGroup == null ? (AnAction)value : (AnAction)actionWithParentGroup.getKey();
           final Presentation templatePresentation = anAction.getTemplatePresentation();
@@ -514,7 +502,7 @@
       while (index < model.getSize()) {
         Object el = model.getElementAt(index);
         Object prev = index == 0 ? null : model.getElementAt(index - 1);
-        String title = getTitle(index, el, prev);
+        String title = myTitleIndexes.getTitle(index);
         if (title != null) {
           myTitle.setText(title);
           myLeftWidth = Math.max(myLeftWidth, myTitle.getPreferredSize().width);
@@ -522,10 +510,10 @@
         index++;
       }
 
-      myLeftWidth += 10;
+      //myLeftWidth += 10;
       myTitle.setForeground(Gray._122);
       myTitle.setAlignmentY(BOTTOM_ALIGNMENT);
-      myLeftPanel.setBorder(new CompoundBorder(new CustomLineBorder(new JBColor(Gray._206, Gray._75), 0,0,0,1), new EmptyBorder(0,0,0,5)));
+      myLeftPanel.setBorder(new CompoundBorder(new CustomLineBorder(getSeparatorColor(), 0, 0, 0, 1), new EmptyBorder(0, 0, 0, 5)));
     }
 
     private Font getTitleFont() {
@@ -533,6 +521,18 @@
     }
   }
 
+  private static JBColor getTitlePanelBackground() {
+    return new JBColor(Gray._242, JBColor.background());
+  }
+
+  private static Color getRightBackground() {
+    return UIUtil.isUnderAquaLookAndFeel() ? Gray._236 : UIUtil.getListBackground();
+  }
+
+  private static JBColor getSeparatorColor() {
+    return new JBColor(Gray._206, Gray._75);
+  }
+
   private static boolean isActionValue(Object o) {
     return o instanceof Map.Entry || o instanceof AnAction;
   }
@@ -545,6 +545,7 @@
     return o instanceof VirtualFile;
   }
 
+  @SuppressWarnings("SSBasedInspection")
   private class CalcThread implements Runnable {
     private final Project project;
     private final String pattern;
@@ -557,84 +558,243 @@
 
     @Override
     public void run() {
+      //noinspection SSBasedInspection
+      UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+        @Override
+        public void run() {
+          myTitleIndexes.clear();
+          myListModel.clear();
+          myAlreadyAddedFiles.clear();
+        }
+      });
       if (pattern.trim().length() == 0) {
+        buildModelFromRecentFiles();
+        updatePopup();
         return;
       }
 
+      checkModelsUpToDate();
+      buildTopHit(pattern);
+      buildRecentFiles(pattern);
+      updatePopup();
+      AccessToken readLock = ApplicationManager.getApplication().acquireReadActionLock();
+      try {
+        buildClasses(pattern);
+      } finally {readLock.finish();}
+      updatePopup();
+      readLock = ApplicationManager.getApplication().acquireReadActionLock();
+      try {
+        buildFiles(pattern);
+      } finally {readLock.finish();}
+      buildActionsAndSettings(pattern);
+      updatePopup();
+    }
+
+    private void buildActionsAndSettings(String pattern) {
+      final Set<AnAction> actions = new HashSet<AnAction>();
+      final Set<Object> settings = new HashSet<Object>();
+      final HashSet<AnAction> toolWindows = new HashSet<AnAction>();
+
+      List<MatchResult> matches = collectResults(pattern, myActions, myActionModel);
+
+      for (MatchResult o : matches) {
+        //if (actionsCount > 15) break;
+        myProgressIndicator.checkCanceled();
+        Object[] objects = myActionModel.getElementsByName(o.elementName, true, pattern);
+        for (Object object : objects) {
+          myProgressIndicator.checkCanceled();
+          if (isSetting(object)) {
+            settings.add(object);
+          }
+          else if (isToolWindowAction(object)) {
+            toolWindows.add((AnAction)((Map.Entry)object).getKey());
+          }
+          else if (isActionValue(object)) {
+            actions.add((AnAction)((Map.Entry)object).getKey());
+          }
+          if (actions.size() + settings.size() + toolWindows.size() > 15) break;
+        }
+      }
+
+      myProgressIndicator.checkCanceled();
+
+      UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+        @Override
+        public void run() {
+          if (myProgressIndicator.isCanceled()) return;
+          if (toolWindows.size() > 0) {
+            myTitleIndexes.toolWindows = myListModel.size();
+            for (Object toolWindow : toolWindows) {
+              myListModel.addElement(toolWindow);
+            }
+          }
+          if (actions.size() > 0) {
+            myTitleIndexes.actions = myListModel.size();
+            for (Object action : actions) {
+              myListModel.addElement(action);
+            }
+          }
+          if (settings.size() > 0) {
+            myTitleIndexes.settings = myListModel.size();
+            for (Object setting : settings) {
+              myListModel.addElement(setting);
+            }
+          }
+        }
+      });
+    }
+
+    private void buildFiles(String pattern) {
+      int filesCounter = 0;
+      List<MatchResult> matches = collectResults(pattern, myFiles, myFileModel);
+      final List<VirtualFile> files = new ArrayList<VirtualFile>();
+
+      for (MatchResult o : matches) {
+        if (filesCounter > 15) break;
+        Object[] objects = myFileModel.getElementsByName(o.elementName, false, pattern, myProgressIndicator);
+        for (Object object : objects) {
+          if (!myListModel.contains(object)) {
+            if (object instanceof PsiFile) {
+              object = ((PsiFile)object).getVirtualFile();
+            }
+            if (object instanceof VirtualFile &&
+                !myAlreadyAddedFiles.contains((VirtualFile)object) &&
+                !((VirtualFile)object).isDirectory()) {
+              files.add((VirtualFile)object);
+              filesCounter++;
+            }
+          }
+          if (filesCounter > 15) break;
+        }
+      }
+
+      myProgressIndicator.checkCanceled();
+
+      if (files.size() > 0) {
+        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+          @Override
+          public void run() {
+            if (!myProgressIndicator.isCanceled()) {
+              myTitleIndexes.files = myListModel.size();
+              for (Object file : files) {
+                myListModel.addElement(file);
+              }
+            }
+          }
+        });
+      }
+    }
+
+    private void buildClasses(String pattern) {
+      int clsCounter = 0;
+      List<MatchResult> matches = collectResults(pattern, myClasses, myClassModel);
+      final List<Object> classes = new ArrayList<Object>();
+      for (MatchResult matchResult : matches) {
+        if (clsCounter > 15) break;
+
+        Object[] objects = myClassModel.getElementsByName(matchResult.elementName, false, pattern, myProgressIndicator);
+        for (Object object : objects) {
+          if (!myListModel.contains(object)) {
+            if (object instanceof PsiElement) {
+              VirtualFile file = PsiUtilCore.getVirtualFile((PsiElement)object);
+              if (file != null) {
+                if (myAlreadyAddedFiles.contains(file)) {
+                  continue;
+                }
+                else {
+                  myAlreadyAddedFiles.add(file);
+                }
+              }
+            }
+            classes.add(object);
+            clsCounter++;
+
+            if (clsCounter > 15) break;
+          }
+        }
+      }
+
+      myProgressIndicator.checkCanceled();
+
+      if (classes.size() > 0) {
+        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+          @Override
+          public void run() {
+            if (!myProgressIndicator.isCanceled()) {
+              myTitleIndexes.classes = myListModel.size();
+              for (Object cls : classes) {
+                myListModel.addElement(cls);
+              }
+            }
+          }
+        });
+      }
+    }
+
+    private void buildRecentFiles(String pattern) {
+      final MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
+      final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
+      for (VirtualFile file : ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles())) {
+        if (StringUtil.isEmptyOrSpaces(pattern) || matcher.matches(file.getName())) {
+          if (!files.contains(file)) {
+            files.add(file);
+          }
+        }
+        if (files.size() > 15) break;
+      }
+
+      if (files.size() > 0) {
+        myAlreadyAddedFiles.addAll(files);
+
+        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+          @Override
+          public void run() {
+            if (!myProgressIndicator.isCanceled()) {
+              myTitleIndexes.recentFiles = myListModel.size();
+              for (Object file : files) {
+                myListModel.addElement(file);
+              }
+            }
+          }
+        });
+      }
+    }
+
+    private void buildTopHit(String pattern) {
+      final List<Object> elements = new ArrayList<Object>();
+      final Consumer<Object> consumer = new Consumer<Object>() {
+        @Override
+        public void consume(Object o) {
+          if (isSetting(o) || isVirtualFile(o) || isActionValue(o) || o instanceof PsiElement) {
+            elements.add(o);
+          }
+        }
+      };
+
+      for (SearchTopHitProvider provider : SearchTopHitProvider.EP_NAME.getExtensions()) {
+        myProgressIndicator.checkCanceled();
+        provider.consumeTopHits(pattern, consumer);
+      }
+      if (elements.size() > 0) {
+        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+          @Override
+          public void run() {
+            if (!myProgressIndicator.isCanceled()) {
+              myTitleIndexes.topHit = myListModel.size();
+              for (Object element : elements) {
+                myListModel.addElement(element);
+              }
+            }
+          }
+        });
+      }
+    }
+
+    private void checkModelsUpToDate() {
       if (myClassModel == null) {
         myClassModel = new GotoClassModel2(project);
         myFileModel = new GotoFileModel(project);
-        myActionModel = new GotoActionModel(project, myFocusComponent) {
-          @Override
-          public boolean matches(@NotNull String name, @NotNull String pattern) {
-            final AnAction anAction = ActionManager.getInstance().getAction(name);
-            if (anAction == null) return true;
-            return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE).matches(
-              anAction.getTemplatePresentation().getText());
-          }
-
-          @NotNull
-          @Override
-          public Object[] getElementsByName(String id, boolean checkBoxState, String pattern) {
-            final HashMap<AnAction, String> map = new HashMap<AnAction, String>();
-            final AnAction act = myActionManager.getAction(id);
-            if (act != null) {
-              map.put(act, myActionsMap.get(act));
-              if (checkBoxState) {
-                final Set<String> ids = ((ActionManagerImpl)myActionManager).getActionIds();
-                for (AnAction action : map.keySet()) { //do not add already included actions
-                  ids.remove(getActionId(action));
-                }
-                if (ids.contains(id)) {
-                  final AnAction anAction = myActionManager.getAction(id);
-                  map.put(anAction, null);
-                }
-              }
-            }
-            Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
-            if (Comparing.strEqual(id, SETTINGS_KEY)) {
-              final Set<String> words = myIndex.getProcessedWords(pattern);
-              Set<OptionDescription> optionDescriptions = null;
-              final String actionManagerName = myActionManager.getComponentName();
-              for (String word : words) {
-                final Set<OptionDescription> descriptions = ((SearchableOptionsRegistrarImpl)myIndex).getAcceptableDescriptions(word);
-                if (descriptions != null) {
-                  for (Iterator<OptionDescription> iterator = descriptions.iterator(); iterator.hasNext(); ) {
-                    OptionDescription description = iterator.next();
-                    if (actionManagerName.equals(description.getPath())) {
-                      iterator.remove();
-                    }
-                  }
-                  if (!descriptions.isEmpty()) {
-                    if (optionDescriptions == null) {
-                      optionDescriptions = descriptions;
-                    }
-                    else {
-                      optionDescriptions.retainAll(descriptions);
-                    }
-                  }
-                } else {
-                  optionDescriptions = null;
-                  break;
-                }
-              }
-              if (optionDescriptions != null && !optionDescriptions.isEmpty()) {
-                Set<String> currentHits = new HashSet<String>();
-                for (Iterator<OptionDescription> iterator = optionDescriptions.iterator(); iterator.hasNext(); ) {
-                  OptionDescription description = iterator.next();
-                  final String hit = description.getHit();
-                  if (hit == null || !currentHits.add(hit.trim())) {
-                    iterator.remove();
-                  }
-                }
-                final Object[] descriptions = optionDescriptions.toArray();
-                Arrays.sort(descriptions);
-                objects = ArrayUtil.mergeArrays(objects, descriptions);
-              }
-            }
-            return objects;
-          }
-        };
+        myActionModel = createActionModel();
         myClasses = myClassModel.getNames(false);
         myFiles = myFileModel.getNames(false);
         myActions = myActionModel.getNames(true);
@@ -642,153 +802,106 @@
         fillConfigurablesIds(null, new IdeConfigurablesGroup().getConfigurables());
         fillConfigurablesIds(null, new ProjectConfigurablesGroup(project).getConfigurables());
       }
-      int clsCounter = 0;
-      int filesCounter = 0;
-      int actionsCount = 0;
-      final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock();
-      try {
-        List<MatchResult> classes = collectResults(pattern, myClasses, myClassModel);
-        List<MatchResult> files = collectResults(pattern, myFiles, myFileModel);
-        List<MatchResult> actions = collectResults(pattern, myActions, myActionModel);
-        DefaultListModel listModel = new DefaultListModel();
-        Set<VirtualFile> alreadyAddedFiles = new HashSet<VirtualFile>();
+    }
 
-        for (MatchResult o : classes) {
-          if (clsCounter > 15) break;
+    private void buildModelFromRecentFiles() {
+      buildRecentFiles("");
+    }
 
-          Object[] objects = myClassModel.getElementsByName(o.elementName, false, pattern, myProgressIndicator);
-          for (Object object : objects) {
-            if (!listModel.contains(object)) {
-              listModel.addElement(object);
-              clsCounter++;
-              if (object instanceof PsiElement) {
-                VirtualFile file = PsiUtilCore.getVirtualFile((PsiElement)object);
-                if (file != null) {
-                  alreadyAddedFiles.add(file);
+    private GotoActionModel createActionModel() {
+      return new GotoActionModel(project, myFocusComponent) {
+        @Override
+        public boolean matches(@NotNull String name, @NotNull String pattern) {
+          final AnAction anAction = ActionManager.getInstance().getAction(name);
+          if (anAction == null) return true;
+          return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE).matches(
+            anAction.getTemplatePresentation().getText());
+        }
+
+        @NotNull
+        @Override
+        public Object[] getElementsByName(String id, boolean checkBoxState, String pattern) {
+          final HashMap<AnAction, String> map = new HashMap<AnAction, String>();
+          final AnAction act = myActionManager.getAction(id);
+          if (act != null) {
+            map.put(act, myActionsMap.get(act));
+            if (checkBoxState) {
+              final Set<String> ids = ((ActionManagerImpl)myActionManager).getActionIds();
+              for (AnAction action : map.keySet()) { //do not add already included actions
+                ids.remove(getActionId(action));
+              }
+              if (ids.contains(id)) {
+                final AnAction anAction = myActionManager.getAction(id);
+                map.put(anAction, null);
+              }
+            }
+          }
+          Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
+          if (Comparing.strEqual(id, SETTINGS_KEY)) {
+            final Set<String> words = myIndex.getProcessedWords(pattern);
+            Set<OptionDescription> optionDescriptions = null;
+            final String actionManagerName = myActionManager.getComponentName();
+            for (String word : words) {
+              final Set<OptionDescription> descriptions = ((SearchableOptionsRegistrarImpl)myIndex).getAcceptableDescriptions(word);
+              if (descriptions != null) {
+                for (Iterator<OptionDescription> iterator = descriptions.iterator(); iterator.hasNext(); ) {
+                  OptionDescription description = iterator.next();
+                  if (actionManagerName.equals(description.getPath())) {
+                    iterator.remove();
+                  }
+                }
+                if (!descriptions.isEmpty()) {
+                  if (optionDescriptions == null) {
+                    optionDescriptions = descriptions;
+                  }
+                  else {
+                    optionDescriptions.retainAll(descriptions);
+                  }
                 }
               }
-              if (clsCounter > 15) break;
-            }
-          }
-        }
-        for (MatchResult o : files) {
-          if (filesCounter > 15) break;
-          Object[] objects = myFileModel.getElementsByName(o.elementName, false, pattern, myProgressIndicator);
-          for (Object object : objects) {
-            if (!listModel.contains(object)) {
-              if (object instanceof PsiFile) {
-                object = ((PsiFile)object).getVirtualFile();
-              }
-              if (object instanceof VirtualFile && !alreadyAddedFiles.contains((VirtualFile)object) && !((VirtualFile)object).isDirectory()) {
-                listModel.addElement(object);
-                filesCounter++;
+              else {
+                optionDescriptions = null;
+                break;
               }
             }
-            if (filesCounter > 15) break;
-          }
-        }
-
-        final Set<AnAction> addedActions = new HashSet<AnAction>();
-        final List<Object> actionsAndSettings = new ArrayList<Object>();
-        for (MatchResult o : actions) {
-          //if (actionsCount > 15) break;
-          myProgressIndicator.checkCanceled();
-          Object[] objects = myActionModel.getElementsByName(o.elementName, true, pattern);
-          for (Object object : objects) {
-            myProgressIndicator.checkCanceled();
-            if (isActionValue(object)) {
-              final AnAction action = (AnAction)((Map.Entry)object).getKey();
-              if (!addedActions.add(action)) continue;
+            if (optionDescriptions != null && !optionDescriptions.isEmpty()) {
+              Set<String> currentHits = new HashSet<String>();
+              for (Iterator<OptionDescription> iterator = optionDescriptions.iterator(); iterator.hasNext(); ) {
+                OptionDescription description = iterator.next();
+                final String hit = description.getHit();
+                if (hit == null || !currentHits.add(hit.trim())) {
+                  iterator.remove();
+                }
+              }
+              final Object[] descriptions = optionDescriptions.toArray();
+              Arrays.sort(descriptions);
+              objects = ArrayUtil.mergeArrays(objects, descriptions);
             }
-            actionsAndSettings.add(object);
-            actionsCount++;
-            //if (actionsCount > 15) break;
           }
+          return objects;
         }
-
-        Collections.sort(actionsAndSettings, new Comparator<Object>() {
-          @Override
-          public int compare(Object o1, Object o2) {
-            final boolean b1 = isSetting(o1);
-            final boolean b2 = isSetting(o2);
-            final boolean t1 = isToolWindowAction(o1);
-            final boolean t2 = isToolWindowAction(o2);
-            return t1 == t2 ? b1 == b2  ? 0 : b1 ? 1 : -1 : t1 ? -1 : 1;
-          }
-        });
-
-        for (Object actionOrSetting : actionsAndSettings) {
-          listModel.addElement(actionOrSetting);
-        }
-
-        updateModel(listModel);
-      }
-      finally {
-        token.finish();
-      }
+      };
     }
 
     @SuppressWarnings("SSBasedInspection")
-    private void updateModel(final DefaultListModel listModel) {
+    private void updatePopup() {
+      myProgressIndicator.checkCanceled();
       SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
           myProgressIndicator.checkCanceled();
-          final DataContext dataContext = DataManager.getInstance().getDataContext(myContextComponent);
-          int settings = 0;
-          int actions = 0;
-          final DefaultListModel model = new DefaultListModel();
+          myListModel.update();
+          myList.revalidate();
+          myList.repaint();
 
-          final String pattern = field.getText();
-          final Consumer<Object> consumer = new Consumer<Object>() {
-            @Override
-            public void consume(Object o) {
-              if (isSetting(o) || isVirtualFile(o) || isActionValue(o) || o instanceof PsiElement) {
-                model.addElement(o);
-              }
-            }
-          };
-
-          for (SearchTopHitProvider provider : SearchTopHitProvider.EP_NAME.getExtensions()) {
-            provider.consumeTopHits(pattern, consumer);
-          }
-
-          myTopHitsCount = model.size();
-
-          for (Object o : listModel.toArray()) {
-            if (model.contains(o)) {
-              continue;
-            }
-
-            if (isSetting(o)) {
-              if (settings < 15) {
-                settings++;
-                model.addElement(o);
-              }
-            } else if (isActionValue(o)) {
-              if (actions < 15) {
-                final AnAction action = (AnAction)((Map.Entry)o).getKey();
-
-                if (model.contains(action)) {
-                  continue;
-                }
-
-                final AnActionEvent event = GotoActionModel.updateActionBeforeShow(action, dataContext);
-                if (event.getPresentation().isEnabledAndVisible()) {
-                  actions++;
-                  model.addElement(action);
-                }
-              }
-            } else {
-              model.addElement(o);
-            }
-          }
-          myList.setModel(model);
           myRenderer.recalculateWidth();
           if (myPopup == null || !myPopup.isVisible()) {
             final ActionCallback callback = ListDelegationUtil.installKeyboardDelegation(field.getTextEditor(), myList);
-            final PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(myList);
-            myPopup = builder.setRequestFocus(false).createPopup();
+            final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(new JBScrollPane(myList), null);
+            myInitialWidth = myInitialHeight = 0;
+            myPopup = builder.setRequestFocus(false)
+              .setCancelKeyEnabled(false)
+              .createPopup();
             Disposer.register(myPopup, new Disposable() {
               @Override
               public void dispose() {
@@ -802,21 +915,24 @@
                 myPopup.cancel();
               }
             }, myPopup);
-          } else {
+          }
+          else {
             myList.revalidate();
             myList.repaint();
           }
           ListScrollingUtil.ensureSelectionExists(myList);
           if (myList.getModel().getSize() == 0) {
-            myPopup.cancel();
-          } else {
+            //rebuildList("");
+          }
+          else {
             final Dimension size = myList.getPreferredSize();
             Dimension sz = new Dimension(Math.max(field.getWidth(), size.width), size.height);
             if (sz.width > 800 || sz.height > 800) {
               final int extra = new JBScrollPane().getVerticalScrollBar().getWidth();
               sz = new Dimension(Math.min(800, Math.max(field.getWidth(), size.width + extra)), Math.min(800, size.height + extra));
               sz.width += 16;
-            } else {
+            }
+            else {
               sz.height++;
               sz.height++;
               sz.width++;
@@ -909,4 +1025,83 @@
       }
     }
   }
+
+  static class TitleIndexes {
+    int topHit;
+    int recentFiles;
+    int classes;
+    int files;
+    int actions;
+    int settings;
+    int toolWindows;
+
+    final String gotoClassTitle;
+    final String gotoFileTitle;
+    final String gotoActionTitle;
+    final String gotoSettingsTitle;
+    final String gotoRecentFilesTitle;
+    static final String toolWindowsTitle = "Tool Windows";
+
+    TitleIndexes() {
+      String gotoClass = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoClass"));
+      gotoClassTitle = StringUtil.isEmpty(gotoClass) ? "Classes" : "Classes (" + gotoClass + ")";
+      String gotoFile = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoFile"));
+      gotoFileTitle = StringUtil.isEmpty(gotoFile) ? "Files" : "Files (" + gotoFile + ")";
+      String gotoAction = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoAction"));
+      gotoActionTitle = StringUtil.isEmpty(gotoAction) ? "Actions" : "Actions (" + gotoAction + ")";
+      String gotoSettings = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ShowSettings"));
+      gotoSettingsTitle = StringUtil.isEmpty(gotoAction) ? "Preferences" : "Preferences (" + gotoSettings + ")";
+      String gotoRecentFiles = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("RecentFiles"));
+      gotoRecentFilesTitle = StringUtil.isEmpty(gotoRecentFiles) ? "Recent Files" : "Recent Files (" + gotoRecentFiles + ")";
+    }
+
+    String getTitle(int index) {
+      if (index == topHit) return index == 0 ? "Top Hit" : "Top Hits";
+      if (index == recentFiles) return gotoRecentFilesTitle;
+      if (index == classes) return gotoClassTitle;
+      if (index == files) return gotoFileTitle;
+      if (index == toolWindows) return toolWindowsTitle;
+      if (index == actions) return gotoActionTitle;
+      if (index == settings) return gotoSettingsTitle;
+      return null;
+    }
+
+    public void clear() {
+      topHit = -1;
+      recentFiles = -1;
+      classes = -1;
+      files = -1;
+      actions = -1;
+      settings = -1;
+      toolWindows = -1;
+    }
+  }
+
+  private static class SearchListModel extends DefaultListModel {
+    Vector myDelegate;
+
+    private SearchListModel() {
+      super();
+      try {
+        final Field field = DefaultListModel.class.getDeclaredField("delegate");
+        field.setAccessible(true);
+        myDelegate = (Vector)field.get(this);
+      }
+      catch (NoSuchFieldException e) {
+
+      }
+      catch (IllegalAccessException e) {
+        e.printStackTrace();
+      }
+    }
+
+    @Override
+    public void addElement(Object obj) {
+      myDelegate.add(obj);
+    }
+
+    public void update() {
+      fireContentsChanged(this, 0, getSize() - 1);
+    }
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
index 1096a06..e00fd3b 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
@@ -17,24 +17,23 @@
 
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.roots.ContentEntry;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author yole
  */
-public class MarkExcludeRootAction extends MarkRootAction {
-  public MarkExcludeRootAction() {
-    super(false, true);
-  }
-
+public class MarkExcludeRootAction extends MarkRootActionBase {
   @Override
   public void actionPerformed(AnActionEvent e) {
-    VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
-    String message = vFiles.length == 1 ? FileUtil.toSystemDependentName(vFiles [0].getPath()) : vFiles.length + " selected files";
-    final int rc = Messages
-      .showOkCancelDialog(e.getData(PlatformDataKeys.PROJECT), getPromptText(message), "Mark as Excluded", Messages.getQuestionIcon());
+    VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
+
+    String message = files.length == 1 ? FileUtil.toSystemDependentName(files[0].getPath()) : files.length + " selected files";
+    final int rc = Messages.showOkCancelDialog(e.getData(PlatformDataKeys.PROJECT), getPromptText(message), "Mark as Excluded",
+                                               Messages.getQuestionIcon());
     if (rc != 0) {
       return;
     }
@@ -45,4 +44,13 @@
     return "Are you sure you would like to exclude " + message +
            " from the project?\nYou can restore excluded directories later using the Project Structure dialog.";
   }
+
+  protected void modifyRoots(VirtualFile vFile, ContentEntry entry) {
+    entry.addExcludeFolder(vFile);
+  }
+
+  @Override
+  protected boolean isEnabled(@NotNull RootsSelection selection) {
+    return true;
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkJavaSourceRootAction.java
similarity index 64%
copy from plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
copy to platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkJavaSourceRootAction.java
index 6830246..5e7c25a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkJavaSourceRootAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn.properties;
+package com.intellij.ide.projectView.actions;
+
+import org.jetbrains.jps.model.java.JavaSourceRootType;
 
 /**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/12/12
- * Time: 8:40 PM
- */
-public class SvnPropDetailsProvider {
+* @author nik
+*/
+public class MarkJavaSourceRootAction extends MarkSourceRootAction {
+  public MarkJavaSourceRootAction() {
+    super(JavaSourceRootType.SOURCE);
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java
deleted file mode 100644
index bfdf291..0000000
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java
+++ /dev/null
@@ -1,149 +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.ide.projectView.actions;
-
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.openapi.roots.*;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.vfs.VfsUtilCore;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author yole
- */
-public class MarkRootAction extends DumbAwareAction {
-  private final boolean myMarkAsTestSources;
-  private final boolean myMarkAsExcluded;
-  private final boolean myUnmark;
-
-  public MarkRootAction() {
-    myMarkAsTestSources = false;
-    myMarkAsExcluded = false;
-    myUnmark = false;
-  }
-
-  protected MarkRootAction(boolean markAsTestSources, boolean markAsExcluded) {
-    myMarkAsTestSources = markAsTestSources;
-    myMarkAsExcluded = markAsExcluded;
-    myUnmark = false;
-  }
-
-  protected MarkRootAction(boolean unmark) {
-    myMarkAsTestSources = false;
-    myMarkAsExcluded = false;
-    myUnmark = true;
-  }
-
-  @Override
-  public void actionPerformed(AnActionEvent e) {
-    Module module = e.getData(LangDataKeys.MODULE);
-    VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
-    if (module == null || vFiles == null) {
-      return;
-    }
-    final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
-    for (VirtualFile vFile : vFiles) {
-      ContentEntry entry = findContentEntry(model, vFile);
-      if (entry != null) {
-        final SourceFolder[] sourceFolders = entry.getSourceFolders();
-        for (SourceFolder sourceFolder : sourceFolders) {
-          if (Comparing.equal(sourceFolder.getFile(), vFile)) {
-            entry.removeSourceFolder(sourceFolder);
-            break;
-          }
-        }
-        if (!myUnmark) {
-          if (myMarkAsExcluded) {
-            entry.addExcludeFolder(vFile);
-          }
-          else {
-            entry.addSourceFolder(vFile, myMarkAsTestSources);
-          }
-        }
-      }
-    }
-    ApplicationManager.getApplication().runWriteAction(new Runnable() {
-      @Override
-      public void run() {
-        model.commit();
-      }
-    });
-  }
-
-  @Nullable
-  public static ContentEntry findContentEntry(@NotNull ModuleRootModel model, @NotNull VirtualFile vFile) {
-    final ContentEntry[] contentEntries = model.getContentEntries();
-    for (ContentEntry contentEntry : contentEntries) {
-      final VirtualFile contentEntryFile = contentEntry.getFile();
-      if (contentEntryFile != null && VfsUtilCore.isAncestor(contentEntryFile, vFile, false)) {
-        return contentEntry;
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public void update(AnActionEvent e) {
-    boolean enabled = canMark(e, myMarkAsTestSources || myMarkAsExcluded || myUnmark, !myMarkAsTestSources || myMarkAsExcluded || myUnmark,
-                              myMarkAsExcluded, null);
-    e.getPresentation().setVisible(enabled);
-    e.getPresentation().setEnabled(enabled);
-  }
-
-  public static boolean canMark(AnActionEvent e,
-                                boolean acceptSourceRoot,
-                                boolean acceptTestSourceRoot,
-                                boolean acceptInSourceContent,
-                                @Nullable Ref<Boolean> rootType) {
-    Module module = e.getData(LangDataKeys.MODULE);
-    VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
-    if (module == null || vFiles == null) {
-      return false;
-    }
-    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
-    for (VirtualFile vFile : vFiles) {
-      if (!vFile.isDirectory()) {
-        return false;
-      }
-      if (!fileIndex.isInContent(vFile)) {
-        return false;
-      }
-      if (Comparing.equal(fileIndex.getSourceRootForFile(vFile), vFile)) {
-        boolean isTestSourceRoot = fileIndex.isInTestSourceContent(vFile);
-        if (acceptSourceRoot && !isTestSourceRoot) {
-          if (rootType != null) rootType.set(true);
-          return true;
-        }
-        if (acceptTestSourceRoot && isTestSourceRoot) {
-          if (rootType != null) rootType.set(false);
-          return true;
-        }
-      }
-      if (fileIndex.isInSourceContent(vFile) && !acceptInSourceContent) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootActionBase.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootActionBase.java
new file mode 100644
index 0000000..91dfe92
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootActionBase.java
@@ -0,0 +1,129 @@
+/*
+ * 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.ide.projectView.actions;
+
+import com.intellij.ide.projectView.impl.ProjectRootsUtil;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yole
+ */
+public abstract class MarkRootActionBase extends DumbAwareAction {
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    Module module = e.getData(LangDataKeys.MODULE);
+    VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
+    if (module == null || vFiles == null) {
+      return;
+    }
+    final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
+    for (VirtualFile vFile : vFiles) {
+      ContentEntry entry = findContentEntry(model, vFile);
+      if (entry != null) {
+        final SourceFolder[] sourceFolders = entry.getSourceFolders();
+        for (SourceFolder sourceFolder : sourceFolders) {
+          if (Comparing.equal(sourceFolder.getFile(), vFile)) {
+            entry.removeSourceFolder(sourceFolder);
+            break;
+          }
+        }
+        modifyRoots(vFile, entry);
+      }
+    }
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        model.commit();
+      }
+    });
+  }
+
+  protected abstract void modifyRoots(VirtualFile vFile, ContentEntry entry);
+
+  @Nullable
+  public static ContentEntry findContentEntry(@NotNull ModuleRootModel model, @NotNull VirtualFile vFile) {
+    final ContentEntry[] contentEntries = model.getContentEntries();
+    for (ContentEntry contentEntry : contentEntries) {
+      final VirtualFile contentEntryFile = contentEntry.getFile();
+      if (contentEntryFile != null && VfsUtilCore.isAncestor(contentEntryFile, vFile, false)) {
+        return contentEntry;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    RootsSelection selection = getSelection(e);
+    boolean enabled = (!selection.mySelectedRoots.isEmpty() || !selection.mySelectedFiles.isEmpty()) && isEnabled(selection);
+    e.getPresentation().setVisible(enabled);
+    e.getPresentation().setEnabled(enabled);
+  }
+
+  protected abstract boolean isEnabled(@NotNull RootsSelection selection);
+
+  protected static RootsSelection getSelection(AnActionEvent e) {
+    Module module = e.getData(LangDataKeys.MODULE);
+    VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
+    if (module == null || files == null) {
+      return RootsSelection.EMPTY;
+    }
+
+    RootsSelection selection = new RootsSelection();
+    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
+    for (VirtualFile file : files) {
+      if (!file.isDirectory()) {
+        return RootsSelection.EMPTY;
+      }
+      if (!fileIndex.isInContent(file)) {
+        return RootsSelection.EMPTY;
+      }
+      SourceFolder folder;
+      if (Comparing.equal(fileIndex.getSourceRootForFile(file), file) && ((folder = ProjectRootsUtil.findSourceFolder(module, file)) != null)) {
+        selection.mySelectedRoots.add(folder);
+      }
+      else {
+        selection.mySelectedFiles.add(file);
+        if (fileIndex.isInSourceContent(file)) {
+          selection.myHaveSelectedFilesUnderSourceRoots = true;
+        }
+      }
+    }
+    return selection;
+  }
+
+  protected static class RootsSelection {
+    public static final RootsSelection EMPTY = new RootsSelection();
+
+    public List<SourceFolder> mySelectedRoots = new ArrayList<SourceFolder>();
+    public List<VirtualFile> mySelectedFiles = new ArrayList<VirtualFile>();
+    public boolean myHaveSelectedFilesUnderSourceRoots;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkSourceRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkSourceRootAction.java
new file mode 100644
index 0000000..0d8e37b
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkSourceRootAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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.intellij.ide.projectView.actions;
+
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+/**
+ * @author nik
+ */
+public class MarkSourceRootAction extends MarkRootActionBase {
+  private final JpsModuleSourceRootType<?> myRootType;
+
+  public MarkSourceRootAction(@NotNull JpsModuleSourceRootType<?> type) {
+    myRootType = type;
+  }
+
+  protected void modifyRoots(VirtualFile vFile, ContentEntry entry) {
+    addSourceFolder(vFile, entry, myRootType);
+  }
+
+  @Override
+  protected boolean isEnabled(@NotNull RootsSelection selection) {
+    if (selection.myHaveSelectedFilesUnderSourceRoots) {
+      return false;
+    }
+
+    if (!selection.mySelectedFiles.isEmpty()) {
+      return true;
+    }
+
+    for (SourceFolder root : selection.mySelectedRoots) {
+      if (!myRootType.equals(root.getRootType())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static <P extends JpsElement> void addSourceFolder(VirtualFile vFile, ContentEntry entry,
+                                                             JpsModuleSourceRootType<P> markAsRootType) {
+    entry.addSourceFolder(vFile, markAsRootType, ((JpsElementTypeWithDefaultProperties<P>)markAsRootType).createDefaultProperties());
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkTestSourceRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkTestSourceRootAction.java
index b308ed2..ea0c20b8 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkTestSourceRootAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkTestSourceRootAction.java
@@ -15,11 +15,13 @@
  */
 package com.intellij.ide.projectView.actions;
 
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+
 /**
  * @author yole
  */
-public class MarkTestSourceRootAction extends MarkRootAction {
+public class MarkTestSourceRootAction extends MarkSourceRootAction {
   public MarkTestSourceRootAction() {
-    super(true, false);
+    super(JavaSourceRootType.TEST_SOURCE);
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/UnmarkRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/UnmarkRootAction.java
index ca122bc..d16f91a 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/UnmarkRootAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/UnmarkRootAction.java
@@ -16,30 +16,53 @@
 package com.intellij.ide.projectView.actions;
 
 import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.roots.ui.configuration.ModuleSourceRootEditHandler;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+import java.util.Set;
 
 /**
  * @author yole
  */
-public class UnmarkRootAction extends MarkRootAction {
-  public UnmarkRootAction() {
-    super(true);
-  }
+public class UnmarkRootAction extends MarkRootActionBase {
+  private static final Logger LOG = Logger.getInstance(UnmarkRootAction.class);
 
   @Override
   public void update(AnActionEvent e) {
-    Ref<Boolean> rootType = new Ref<Boolean>();
-    boolean enabled = canMark(e, true, true, false, rootType);
-    if (rootType.get() == null) {
-      enabled = false;
+    super.update(e);
+    RootsSelection selection = getSelection(e);
+    Set<JpsModuleSourceRootType<?>> selectedRootTypes = new HashSet<JpsModuleSourceRootType<?>>();
+    for (SourceFolder root : selection.mySelectedRoots) {
+      selectedRootTypes.add(root.getRootType());
     }
-    else if (rootType.get()) {
-      e.getPresentation().setText("Unmark as Source Root");
+
+    if (!selectedRootTypes.isEmpty()) {
+      String text;
+      if (selectedRootTypes.size() == 1) {
+        JpsModuleSourceRootType<?> type = selectedRootTypes.iterator().next();
+        ModuleSourceRootEditHandler<?> handler = ModuleSourceRootEditHandler.findEditHandler(type);
+        LOG.assertTrue(handler != null, type);
+        text = "Unmark as " + handler.getRootTypeName() + " " + StringUtil.pluralize("Root", selection.mySelectedRoots.size());
+      }
+      else {
+        text = "Unmark Roots";
+      }
+      e.getPresentation().setText(text);
     }
-    else {
-      e.getPresentation().setText("Unmark as Test Source Root");
-    }
-    e.getPresentation().setVisible(enabled);
-    e.getPresentation().setEnabled(enabled);
+  }
+
+  @Override
+  protected boolean isEnabled(@NotNull RootsSelection selection) {
+    return selection.mySelectedFiles.isEmpty() && !selection.mySelectedRoots.isEmpty();
+  }
+
+  protected void modifyRoots(VirtualFile vFile, ContentEntry entry) {
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiTreeAnchorizer.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiTreeAnchorizer.java
index aa34383..809c41c 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiTreeAnchorizer.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiTreeAnchorizer.java
@@ -58,9 +58,14 @@
   }
   @Override
   @Nullable
-  public Object retrieveElement(Object pointer) {
+  public Object retrieveElement(final Object pointer) {
     if (pointer instanceof SmartPointerWrapper) {
-      return ((SmartPointerWrapper)pointer).myPointer.getElement();
+      return ApplicationManager.getApplication().runReadAction(new Computable<Object>() {
+        @Override
+        public Object compute() {
+          return ((SmartPointerWrapper)pointer).myPointer.getElement();
+        }
+      });
     }
 
     return super.retrieveElement(pointer);
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 4d02873..0fe520a 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -20,8 +20,11 @@
 import com.intellij.ide.DefaultTreeExpander;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.TreeExpander;
+import com.intellij.ide.structureView.StructureView;
+import com.intellij.ide.structureView.StructureViewBuilder;
 import com.intellij.ide.structureView.StructureViewModel;
 import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.StructureViewComposite;
 import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
 import com.intellij.ide.structureView.newStructureView.StructureViewComponent;
 import com.intellij.ide.structureView.newStructureView.TreeModelWrapper;
@@ -37,6 +40,9 @@
 import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
 import com.intellij.openapi.keymap.KeymapUtil;
 import com.intellij.openapi.project.Project;
@@ -45,10 +51,12 @@
 import com.intellij.openapi.util.*;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
 import com.intellij.ui.*;
 import com.intellij.ui.popup.AbstractPopup;
 import com.intellij.ui.popup.PopupUpdateProcessor;
@@ -93,6 +101,7 @@
   private final StructureViewModel myTreeModel;
   private final StructureViewModel myBaseTreeModel;
   private final TreeStructureActionsOwner myTreeActionsOwner;
+  private PsiFile myPsiFile;
   private JBPopup myPopup;
 
   @NonNls private static final String narrowDownPropertyKey = "FileStructurePopup.narrowDown";
@@ -112,6 +121,7 @@
   private boolean myInitialNodeIsLeaf;
   private final List<Pair<String, JCheckBox>> myTriggeredCheckboxes = new ArrayList<Pair<String, JCheckBox>>();
   private final TreeExpander myTreeExpander;
+  private StructureView myStructureView;
 
 
   public FileStructurePopup(StructureViewModel structureViewModel,
@@ -124,13 +134,32 @@
 
     //Stop code analyzer to speedup EDT
     DaemonCodeAnalyzer.getInstance(myProject).disableUpdateByTimer(this);
-
     IdeFocusManager.getInstance(myProject).typeAheadUntil(myTreeHasBuilt);
-    myBaseTreeModel = structureViewModel;
+
+    //long l = System.currentTimeMillis();
+    if (editor instanceof EditorImpl) {
+      VirtualFile file = ((EditorImpl)editor).getVirtualFile();
+      FileEditor fileEditor = FileEditorManager.getInstance(myProject).getSelectedEditor(file);
+      if (fileEditor != null) {
+        StructureViewBuilder builder = fileEditor.getStructureViewBuilder();
+        myPsiFile = PsiManager.getInstance(project).findFile(file);
+        if (builder != null && myPsiFile != null) {
+          myStructureView = builder.createStructureView(fileEditor, project);
+          Disposer.register(this, myStructureView);
+        }
+      }
+    }
+    //System.out.println(System.currentTimeMillis() - l);
+    if (myStructureView instanceof StructureViewComposite) {
+      StructureViewComposite.StructureViewDescriptor[] views = ((StructureViewComposite)myStructureView).getStructureViews();
+      myBaseTreeModel = new StructureViewCompositeModel(myPsiFile, views);
+    } else {
+      myBaseTreeModel = structureViewModel;
+    }
     Disposer.register(this, auxDisposable);
     if (applySortAndFilter) {
       myTreeActionsOwner = new TreeStructureActionsOwner(myBaseTreeModel);
-      myTreeModel = new TreeModelWrapper(structureViewModel, myTreeActionsOwner);
+      myTreeModel = new TreeModelWrapper(myBaseTreeModel, myTreeActionsOwner);
     }
     else {
       myTreeActionsOwner = null;
@@ -274,7 +303,7 @@
     });
     myTree.getEmptyText().setText("Loading...");
     final Point location = DimensionService.getInstance().getLocation(getDimensionServiceKey(), myProject);
-    if (location != null) {
+    if (location != null && myEditor != null) {
       myPopup.showInScreenCoordinates(myEditor.getContentComponent(), location);
     } else {
       myPopup.showCenteredInCurrentWindow(myProject);
@@ -306,6 +335,7 @@
           }
         });
 
+        //noinspection SSBasedInspection
         SwingUtilities.invokeLater(new Runnable() {
           @Override
           public void run() {
@@ -350,6 +380,7 @@
           myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() {
             @Override
             public void run() {
+              //noinspection SSBasedInspection
               SwingUtilities.invokeLater(new Runnable() {
                 @Override
                 public void run() {
@@ -401,6 +432,28 @@
     Set<PsiElement> parents = getAllParents(element);
 
     FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)myAbstractTreeBuilder.getRootElement();
+    if (node != null && myStructureView instanceof StructureViewComposite) {
+      parents.remove(element.getContainingFile());
+      final List<FilteringTreeStructure.FilteringNode> fileNodes = node.children();
+
+      for (FilteringTreeStructure.FilteringNode fileNode : fileNodes) {
+        final FilteringTreeStructure.FilteringNode found = findNode(parents, fileNode);
+        if (found != null && found != fileNode) {
+          return found;
+        }
+      }
+    } else {
+      final FilteringTreeStructure.FilteringNode found = findNode(parents, node);
+      if (found == null) {
+        TreeUtil.selectFirstNode(myTree);
+      }
+      return found;
+    }
+    TreeUtil.selectFirstNode(myTree);
+    return null;
+  }
+
+  private FilteringTreeStructure.FilteringNode findNode(Set<PsiElement> parents, FilteringTreeStructure.FilteringNode node) {
     while (node != null) {
       boolean changed = false;
       for (FilteringTreeStructure.FilteringNode n : node.children()) {
@@ -420,7 +473,6 @@
         return node;
       }
     }
-    TreeUtil.selectFirstNode(myTree);
     return null;
   }
 
@@ -457,6 +509,7 @@
 
   @Override
   public void dispose() {
+
   }
 
   @NonNls
@@ -475,6 +528,10 @@
       return (PsiElement)elementAtCursor;
     }
 
+    if (myEditor != null) {
+      return psiFile.getViewProvider().findElementAt(myEditor.getCaretModel().getOffset());
+    }
+
     return null;
   }
 
diff --git a/platform/lang-impl/src/com/intellij/ide/util/StructureViewCompositeModel.java b/platform/lang-impl/src/com/intellij/ide/util/StructureViewCompositeModel.java
new file mode 100644
index 0000000..565ba5f
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/util/StructureViewCompositeModel.java
@@ -0,0 +1,126 @@
+/*
+ * 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.intellij.ide.util;
+
+import com.intellij.ide.structureView.StructureViewModelBase;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.StructureViewComposite;
+import com.intellij.ide.util.treeView.smartTree.TreeElement;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class StructureViewCompositeModel extends StructureViewModelBase {
+  public StructureViewCompositeModel(PsiFile file, StructureViewComposite.StructureViewDescriptor[] views) {
+    super(file, createRootNode(file, views));
+  }
+
+  private static StructureViewTreeElement createRootNode(final PsiFile file, final StructureViewComposite.StructureViewDescriptor[] views) {
+    return new StructureViewTreeElement() {
+      @Override
+      public Object getValue() {
+        return file;
+      }
+
+      @Override
+      public void navigate(boolean requestFocus) {
+        file.navigate(requestFocus);
+      }
+
+      @Override
+      public boolean canNavigate() {
+        return file.canNavigate();
+      }
+
+      @Override
+      public boolean canNavigateToSource() {
+        return file.canNavigateToSource();
+      }
+
+      @Override
+      public ItemPresentation getPresentation() {
+        return file.getPresentation();
+      }
+
+      @Override
+      public TreeElement[] getChildren() {
+        ArrayList<TreeElement> elements = new ArrayList<TreeElement>();
+        for (StructureViewComposite.StructureViewDescriptor view : views) {
+          elements.add(createTreeElementFromView(file, view));
+        }
+        return elements.toArray(new TreeElement[elements.size()]);
+      }
+    };
+  }
+
+  private static TreeElement createTreeElementFromView(final PsiFile file, final StructureViewComposite.StructureViewDescriptor view) {
+    return new StructureViewTreeElement() {
+      @Override
+      public Object getValue() {
+        return view;
+      }
+
+      @Override
+      public void navigate(boolean requestFocus) {
+        file.navigate(requestFocus);
+      }
+
+      @Override
+      public boolean canNavigate() {
+        return file.canNavigate();
+      }
+
+      @Override
+      public boolean canNavigateToSource() {
+        return file.canNavigateToSource();
+      }
+
+      @Override
+      public ItemPresentation getPresentation() {
+        return new ItemPresentation() {
+          @Nullable
+          @Override
+          public String getPresentableText() {
+            return view.title;
+          }
+
+          @Nullable
+          @Override
+          public String getLocationString() {
+            return null;
+          }
+
+          @Nullable
+          @Override
+          public Icon getIcon(boolean unused) {
+            return view.icon;
+          }
+        };
+      }
+
+      @Override
+      public TreeElement[] getChildren() {
+        return view.structureView.getTreeModel().getRoot().getChildren();
+      }
+    };
+  }
+}
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 9903fbd..a9395e7 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
@@ -155,6 +155,7 @@
   private ShortcutSet myCheckBoxShortcut;
   protected boolean myInitIsDone;
   static final boolean ourLoadNamesEachTime = FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
+  private boolean myFixLostTyping = true;
 
   public boolean checkDisposed() {
     if (myDisposedFlag && myPostponedOkAction != null && !myPostponedOkAction.isProcessed()) {
@@ -436,12 +437,12 @@
     final JComponent toolbarComponent = actionToolbar.getComponent();
     toolbarComponent.setBorder(null);
 
-    hBox.add(toolbarComponent);
-
     if (myToolArea == null) {
       myToolArea = new JLabel(EmptyIcon.create(1, 24));
     }
     hBox.add(myToolArea);
+    hBox.add(toolbarComponent);
+
     myTextFieldPanel.add(caption2Tools);
 
     final ActionMap actionMap = new ActionMap();
@@ -544,7 +545,7 @@
     myTextField.getDocument().addDocumentListener(new DocumentAdapter() {
       @Override
       protected void textChanged(DocumentEvent e) {
-        clearPosponedOkAction(false);
+        clearPostponedOkAction(false);
         rebuildList(false);
       }
     });
@@ -751,7 +752,7 @@
       cancelListUpdater();
       close(ok);
 
-      clearPosponedOkAction(ok);
+      clearPostponedOkAction(ok);
     }
     finally {
       myListModel.clear();
@@ -777,8 +778,12 @@
     return false;
   }
 
-  protected static boolean isToFixLostTyping() {
-    return Registry.is("actionSystem.fixLostTyping");
+  public void setFixLostTyping(boolean fixLostTyping) {
+    myFixLostTyping = fixLostTyping;
+  }
+
+  protected boolean isToFixLostTyping() {
+    return myFixLostTyping && Registry.is("actionSystem.fixLostTyping");
   }
 
   private synchronized void ensureNamesLoaded(boolean checkboxState) {
@@ -1017,7 +1022,7 @@
       myTextField.setForeground(JBColor.red);
       myListUpdater.cancelAll();
       hideList();
-      clearPosponedOkAction(false);
+      clearPostponedOkAction(false);
       return;
     }
 
@@ -1163,12 +1168,12 @@
         if (getChosenElement() != null) {
           doClose(true);
         }
-        clearPosponedOkAction(checkDisposed());
+        clearPostponedOkAction(checkDisposed());
       }
     }
   }
 
-  private void clearPosponedOkAction(boolean success) {
+  private void clearPostponedOkAction(boolean success) {
     if (myPostponedOkAction != null) {
       if (success) {
         myPostponedOkAction.setDone();
@@ -1194,10 +1199,12 @@
   }
 
   protected List<Object> getChosenElements() {
-    if (myListIsUpToDate) {
-      List<Object> values = new ArrayList<Object>(Arrays.asList(myList.getSelectedValues()));
-      values.remove(EXTRA_ELEM);
-      values.remove(NON_PREFIX_SEPARATOR);
+
+    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;
     }
 
@@ -1516,13 +1523,12 @@
             return;
           }
 
-          final String cardToShow;
           if (elements.isEmpty() && !myCheckboxState) {
             myScopeExpanded = true;
             myCheckboxState = true;
             calculation.run();
           }
-          cardToShow = elements.isEmpty() ? NOT_FOUND_CARD : myScopeExpanded ? NOT_FOUND_IN_PROJECT_CARD : CHECK_BOX_CARD;
+          final String cardToShow = elements.isEmpty() ? NOT_FOUND_CARD : myScopeExpanded ? NOT_FOUND_IN_PROJECT_CARD : CHECK_BOX_CARD;
           showCard(cardToShow, 0);
 
           final Set<Object> filtered = filter(elements);
@@ -1562,8 +1568,8 @@
           }
         }
       );
-      long end = System.currentTimeMillis();
       if (ContributorsBasedGotoByModel.LOG.isDebugEnabled()) {
+        long end = System.currentTimeMillis();
         ContributorsBasedGotoByModel.LOG.debug("addElementsByPattern("+pattern+"): "+(end-start)+"ms; "+elements.size()+" elements");
       }
     }
@@ -1629,7 +1635,7 @@
 
   private abstract class ShowFindUsagesAction extends AnAction {
     public ShowFindUsagesAction() {
-      super(ACTION_NAME, ACTION_NAME, AllIcons.Actions.Find);
+      super(ACTION_NAME, ACTION_NAME, AllIcons.General.AutohideOff);
     }
 
     @Override
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
index c993b85..a2ec3ae4 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
@@ -299,6 +299,16 @@
   }
 
   @Override
+  public JComponent getPermanentHeaderComponent() {
+    return myDelegate.getPermanentHeaderComponent();
+  }
+
+  @Override
+  public void setPermanentHeaderComponent(JComponent component) {
+    myDelegate.setPermanentHeaderComponent(component);
+  }
+
+  @Override
   @NotNull
   public JComponent getContentComponent() {
     return myDelegate.getContentComponent();
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java
index a65052d..fd1b91d 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java
@@ -26,6 +26,6 @@
     if (!WebModuleTypeBase.isWebModule(module)) {
       return ModuleConfigurationEditor.EMPTY;
     }
-    return new ModuleConfigurationEditor[]{new CommonContentEntriesEditor(module.getName(), state, false, false)};
+    return new ModuleConfigurationEditor[]{new CommonContentEntriesEditor(module.getName(), state)};
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java
index c828e23..3a5c3ec 100644
--- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java
@@ -209,15 +209,15 @@
 
   @Override
   public SdkTypeId getDefaultSdkType() {
-    return UnknownSdkType.getInstance(null);
+    return UnknownSdkType.getInstance("");
   }
 
   @Override
-  public SdkTypeId getSdkTypeByName(String sdkTypeName) {
+  public SdkTypeId getSdkTypeByName(@NotNull String sdkTypeName) {
     return findSdkTypeByName(sdkTypeName);
   }
 
-  public static SdkTypeId findSdkTypeByName(String sdkTypeName) {
+  public static SdkTypeId findSdkTypeByName(@NotNull String sdkTypeName) {
     final SdkType[] allSdkTypes = SdkType.getAllTypes();
     for (final SdkType type : allSdkTypes) {
       if (type.getName().equals(sdkTypeName)) {
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 af1c338..76ebc10 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
@@ -43,9 +43,11 @@
 import com.intellij.ui.ScrollPaneFactory;
 import com.intellij.ui.roots.ToolbarPanel;
 import com.intellij.util.Consumer;
+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.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
 import javax.swing.border.Border;
@@ -77,16 +79,16 @@
   private final String myModuleName;
   private final ModulesProvider myModulesProvider;
   private final ModuleConfigurationState myState;
-  private final boolean myCanMarkSources;
-  private final boolean myCanMarkTestSources;
+  private final List<ModuleSourceRootEditHandler<?>> myEditHandlers = new ArrayList<ModuleSourceRootEditHandler<?>>();
 
-  public CommonContentEntriesEditor(String moduleName, final ModuleConfigurationState state, boolean canMarkSources, boolean canMarkTestSources) {
+  public CommonContentEntriesEditor(String moduleName, final ModuleConfigurationState state, JpsModuleSourceRootType<?>... rootTypes) {
     super(state);
     myState = state;
     myModuleName = moduleName;
-    myCanMarkSources = canMarkSources;
-    myCanMarkTestSources = canMarkTestSources;
     myModulesProvider = state.getModulesProvider();
+    for (JpsModuleSourceRootType<?> type : rootTypes) {
+      ContainerUtil.addIfNotNull(myEditHandlers, ModuleSourceRootEditHandler.findEditHandler(type));
+    }
     final VirtualFileManagerAdapter fileManagerListener = new VirtualFileManagerAdapter() {
       @Override
       public void afterRefreshFinish(boolean asynchronous) {
@@ -125,6 +127,10 @@
     return NAME;
   }
 
+  protected final List<ModuleSourceRootEditHandler<?>> getEditHandlers() {
+    return myEditHandlers;
+  }
+
   @Override
   public void disposeUIResources() {
     if (myRootTreeEditor != null) {
@@ -197,7 +203,7 @@
   }
 
   protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) {
-    return new ContentEntryTreeEditor(project, myCanMarkSources, myCanMarkTestSources);
+    return new ContentEntryTreeEditor(project, myEditHandlers);
   }
 
   protected void addAdditionalSettingsToPanel(final JPanel mainPanel) {
@@ -229,7 +235,7 @@
   }
 
   protected ContentEntryEditor createContentEntryEditor(String contentEntryUrl) {
-    return new ContentEntryEditor(contentEntryUrl, myCanMarkSources, myCanMarkTestSources) {
+    return new ContentEntryEditor(contentEntryUrl, myEditHandlers) {
       @Override
       protected ModifiableRootModel getModel() {
         return CommonContentEntriesEditor.this.getModel();
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
index f6adae4..705df24 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
@@ -25,12 +25,18 @@
 import com.intellij.util.EventDispatcher;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.util.EventListener;
+import java.util.*;
+import java.util.List;
 
 /**
  * @author Eugene Zhuravlev
@@ -43,24 +49,27 @@
   private JPanel myMainPanel;
   protected EventDispatcher<ContentEntryEditorListener> myEventDispatcher;
   private final String myContentEntryUrl;
-  protected final boolean myCanMarkSources;
-  protected final boolean myCanMarkTestSources;
+  private final List<ModuleSourceRootEditHandler<?>> myEditHandlers;
 
   public interface ContentEntryEditorListener extends EventListener{
+
     void editingStarted(@NotNull ContentEntryEditor editor);
     void beforeEntryDeleted(@NotNull ContentEntryEditor editor);
     void sourceFolderAdded(@NotNull ContentEntryEditor editor, SourceFolder folder);
-    void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file, boolean isTestSource);
+    void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file);
     void folderExcluded(@NotNull ContentEntryEditor editor, VirtualFile file);
     void folderIncluded(@NotNull ContentEntryEditor editor, VirtualFile file);
     void navigationRequested(@NotNull ContentEntryEditor editor, VirtualFile file);
-    void packagePrefixSet(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder);
+    void sourceRootPropertiesChanged(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder);
   }
 
-  public ContentEntryEditor(final String contentEntryUrl, boolean canMarkSources, boolean canMarkTestSources) {
-    myContentEntryUrl = contentEntryUrl;
-    myCanMarkSources = canMarkSources;
-    myCanMarkTestSources = canMarkTestSources;
+  public ContentEntryEditor(String url, List<ModuleSourceRootEditHandler<?>> editHandlers) {
+    myContentEntryUrl = url;
+    myEditHandlers = editHandlers;
+  }
+
+  protected final List<ModuleSourceRootEditHandler<?>> getEditHandlers() {
+    return myEditHandlers;
   }
 
   public String getContentEntryUrl() {
@@ -145,10 +154,9 @@
   }
 
   @Override
-  public void setPackagePrefix(@NotNull SourceFolder folder, @NotNull String prefix) {
-    folder.setPackagePrefix(prefix);
+  public void onSourceRootPropertiesChanged(@NotNull SourceFolder folder) {
     update();
-    myEventDispatcher.getMulticaster().packagePrefixSet(this, folder);
+    myEventDispatcher.getMulticaster().sourceRootPropertiesChanged(this, folder);
   }
 
   public void addContentEntryEditorListener(ContentEntryEditorListener listener) {
@@ -188,7 +196,7 @@
   }
 
   protected ContentRootPanel createContentRootPane() {
-    return new ContentRootPanel(this, myCanMarkSources, myCanMarkTestSources) {
+    return new ContentRootPanel(this, myEditHandlers) {
       @Override
       protected ContentEntry getContentEntry() {
         return ContentEntryEditor.this.getContentEntry();
@@ -198,16 +206,19 @@
 
   @Nullable
   public SourceFolder addSourceFolder(@NotNull final VirtualFile file, boolean isTestSource, String packagePrefix) {
+    return addSourceFolder(file, isTestSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE,
+                           JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties(packagePrefix)));
+  }
+
+  @Nullable
+  public <P extends JpsElement> SourceFolder addSourceFolder(@NotNull final VirtualFile file, final JpsModuleSourceRootType<P> rootType,
+                                                             final P properties) {
     final ContentEntry contentEntry = getContentEntry();
     if (contentEntry != null) {
-      final SourceFolder sourceFolder = contentEntry.addSourceFolder(file, isTestSource, packagePrefix);
-      try {
-        return sourceFolder;
-      }
-      finally {
-        myEventDispatcher.getMulticaster().sourceFolderAdded(this, sourceFolder);
-        update();
-      }
+      final SourceFolder sourceFolder = contentEntry.addSourceFolder(file, rootType, properties);
+      myEventDispatcher.getMulticaster().sourceFolderAdded(this, sourceFolder);
+      update();
+      return sourceFolder;
     }
 
     return null;
@@ -224,7 +235,7 @@
       doRemoveSourceFolder(sourceFolder);
     }
     finally {
-      myEventDispatcher.getMulticaster().sourceFolderRemoved(this, sourceFolder.getFile(), sourceFolder.isTestSource());
+      myEventDispatcher.getMulticaster().sourceFolderRemoved(this, sourceFolder.getFile());
       update();
     }
   }
@@ -268,14 +279,10 @@
     }
   }
 
-  public boolean isSource(@NotNull final VirtualFile file) {
-    final SourceFolder sourceFolder = getSourceFolder(file);
-    return sourceFolder != null && !sourceFolder.isTestSource();
-  }
-
-  public boolean isTestSource(@NotNull final VirtualFile file) {
-    final SourceFolder sourceFolder = getSourceFolder(file);
-    return sourceFolder != null && sourceFolder.isTestSource();
+  @Nullable
+  public JpsModuleSourceRootType<?> getRootType(@NotNull VirtualFile file) {
+    SourceFolder folder = getSourceFolder(file);
+    return folder != null ? folder.getRootType() : null;
   }
 
   public boolean isExcluded(@NotNull final VirtualFile file) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditorListenerAdapter.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditorListenerAdapter.java
index e21475f..2b4b9b9 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditorListenerAdapter.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditorListenerAdapter.java
@@ -39,7 +39,7 @@
   }
 
   @Override
-  public void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file, boolean isTestSource) {
+  public void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file) {
   }
 
   @Override
@@ -55,6 +55,6 @@
   }
 
   @Override
-  public void packagePrefixSet(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder) {
+  public void sourceRootPropertiesChanged(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder) {
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java
index 267755b..44834bb 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java
@@ -28,16 +28,21 @@
 import com.intellij.ui.JBColor;
 import com.intellij.ui.SimpleTextAttributes;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
 import javax.swing.tree.DefaultMutableTreeNode;
 import java.awt.*;
+import java.util.List;
 
 public class ContentEntryTreeCellRenderer extends NodeRenderer {
   protected final ContentEntryTreeEditor myTreeEditor;
+  private final List<ModuleSourceRootEditHandler<?>> myEditHandlers;
 
-  public ContentEntryTreeCellRenderer(@NotNull final ContentEntryTreeEditor treeEditor) {
+  public ContentEntryTreeCellRenderer(@NotNull final ContentEntryTreeEditor treeEditor, List<ModuleSourceRootEditHandler<?>> editHandlers) {
     myTreeEditor = treeEditor;
+    myEditHandlers = editHandlers;
   }
 
   @Override
@@ -86,7 +91,7 @@
     final SourceFolder[] sourceFolders = entry.getSourceFolders();
     for (SourceFolder sourceFolder : sourceFolders) {
       if (file.equals(sourceFolder.getFile())) {
-        return IconSet.getSourceRootIcon(sourceFolder.isTestSource());
+        return IconSet.getSourceRootIcon(sourceFolder.getRootType(), myEditHandlers);
       }
     }
 
@@ -98,10 +103,20 @@
         if (currentRoot != null && VfsUtilCore.isAncestor(sourcePath, currentRoot, false)) {
           continue;
         }
-        icon = IconSet.getSourceFolderIcon(sourceFolder.isTestSource());
+        icon = getSourceFolderIcon(sourceFolder.getRootType());
         currentRoot = sourcePath;
       }
     }
     return icon;
   }
+
+  @Nullable
+  private Icon getSourceFolderIcon(JpsModuleSourceRootType<?> type) {
+    for (ModuleSourceRootEditHandler<?> handler : myEditHandlers) {
+      if (handler.getRootType().equals(type)) {
+        return handler.getFolderUnderRootIcon();
+      }
+    }
+    return null;
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java
index b414046..a3b8356 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java
@@ -41,7 +41,6 @@
 import com.intellij.openapi.roots.ui.configuration.actions.ToggleSourcesStateAction;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.ScrollPaneFactory;
@@ -59,6 +58,7 @@
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.util.Comparator;
+import java.util.List;
 
 /**
  * @author Eugene Zhuravlev
@@ -67,21 +67,19 @@
  */
 public class ContentEntryTreeEditor {
   private final Project myProject;
-  private final boolean myCanMarkSources;
-  private final boolean myCanMarkTestSources;
-  protected Tree myTree;
+  private final List<ModuleSourceRootEditHandler<?>> myEditHandlers;
+  protected final Tree myTree;
   private FileSystemTreeImpl myFileSystemTree;
   private final JPanel myTreePanel;
   private final DefaultMutableTreeNode EMPTY_TREE_ROOT = new DefaultMutableTreeNode(ProjectBundle.message("module.paths.empty.node"));
-  protected DefaultActionGroup myEditingActionsGroup;
+  protected final DefaultActionGroup myEditingActionsGroup;
   private ContentEntryEditor myContentEntryEditor;
   private final MyContentEntryEditorListener myContentEntryEditorListener = new MyContentEntryEditorListener();
   private final FileChooserDescriptor myDescriptor;
 
-  public ContentEntryTreeEditor(Project project, boolean canMarkSources, boolean canMarkTestSources) {
+  public ContentEntryTreeEditor(Project project, List<ModuleSourceRootEditHandler<?>> editHandlers) {
     myProject = project;
-    myCanMarkSources = canMarkSources;
-    myCanMarkTestSources = canMarkTestSources;
+    myEditHandlers = editHandlers;
     myTree = new Tree();
     myTree.setRootVisible(true);
     myTree.setShowsRootHandles(true);
@@ -101,21 +99,24 @@
   }
 
   protected void createEditingActions() {
-    if (myCanMarkSources) {
-      ToggleSourcesStateAction markSourcesAction = new ToggleSourcesStateAction(myTree, this, false);
-      markSourcesAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK)), myTree);
-      myEditingActionsGroup.add(markSourcesAction);
-    }
-
-    if (myCanMarkTestSources) {
-      setupTestsAction();
+    for (ModuleSourceRootEditHandler<?> editor : myEditHandlers) {
+      ToggleSourcesStateAction action = new ToggleSourcesStateAction(myTree, this, editor);
+      CustomShortcutSet shortcutSet = editor.getMarkRootShortcutSet();
+      if (shortcutSet != null) {
+        action.registerCustomShortcutSet(shortcutSet, myTree);
+      }
+      myEditingActionsGroup.add(action);
     }
 
     setupExcludedAction();
   }
 
+  protected List<ModuleSourceRootEditHandler<?>> getEditHandlers() {
+    return myEditHandlers;
+  }
+
   protected TreeCellRenderer getContentEntryCellRenderer() {
-    return new ContentEntryTreeCellRenderer(this);
+    return new ContentEntryTreeCellRenderer(this, myEditHandlers);
   }
 
   /**
@@ -225,7 +226,7 @@
     }
 
     @Override
-    public void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file, boolean isTestSource) {
+    public void sourceFolderRemoved(@NotNull ContentEntryEditor editor, VirtualFile file) {
       update();
     }
 
@@ -240,7 +241,7 @@
     }
 
     @Override
-    public void packagePrefixSet(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder) {
+    public void sourceRootPropertiesChanged(@NotNull ContentEntryEditor editor, @NotNull SourceFolder folder) {
       update();
     }
   }
@@ -289,12 +290,6 @@
     }
   }
 
-  protected void setupTestsAction() {
-    ToggleSourcesStateAction markTestsAction = new ToggleSourcesStateAction(myTree, this, true);
-    markTestsAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK)), myTree);
-    myEditingActionsGroup.add(markTestsAction);
-  }
-
   protected void setupExcludedAction() {
     ToggleExcludedStateAction toggleExcludedAction = new ToggleExcludedStateAction(myTree, this);
     myEditingActionsGroup.add(toggleExcludedAction);
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 be14b1e..b423bec 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
@@ -22,6 +22,7 @@
 import com.intellij.openapi.roots.ContentFolder;
 import com.intellij.openapi.roots.ExcludeFolder;
 import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.roots.impl.SourceFolderImpl;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
@@ -36,28 +37,27 @@
 import com.intellij.ui.roots.ResizingWrapper;
 import com.intellij.uiDesigner.core.GridConstraints;
 import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.util.containers.MultiMap;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 import java.awt.*;
 import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.*;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author Eugene Zhuravlev
  *         Date: Jan 19, 2004
  */
 public abstract class ContentRootPanel extends JPanel {
-  protected static final Color SOURCES_COLOR = new JBColor(new Color(0x0A50A1), DarculaColors.BLUE);
-  protected static final Color TESTS_COLOR = new Color(0x008C2E);
-  protected static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED);
+  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 HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82);
   private static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF);
@@ -65,24 +65,22 @@
   private static final Color UNSELECTED_TEXT_COLOR = Gray._51;
 
   protected final ActionCallback myCallback;
+  private final List<ModuleSourceRootEditHandler<?>> myModuleSourceRootEditHandlers;
   private JComponent myHeader;
   private JComponent myBottom;
   private final Map<JComponent, Color> myComponentToForegroundMap = new HashMap<JComponent, Color>();
-  private final boolean myCanMarkSources;
-  private final boolean myCanMarkTestSources;
 
   public interface ActionCallback {
     void deleteContentEntry();
     void deleteContentFolder(ContentEntry contentEntry, ContentFolder contentFolder);
     void navigateFolder(ContentEntry contentEntry, ContentFolder contentFolder);
-    void setPackagePrefix(@NotNull SourceFolder folder, @NotNull String prefix);
+    void onSourceRootPropertiesChanged(@NotNull SourceFolder folder);
   }
 
-  public ContentRootPanel(ActionCallback callback, boolean canMarkSources, boolean canMarkTestSources) {
+  public ContentRootPanel(ActionCallback callback, List<ModuleSourceRootEditHandler<?>> moduleSourceRootEditHandlers) {
     super(new GridBagLayout());
     myCallback = callback;
-    myCanMarkSources = canMarkSources;
-    myCanMarkTestSources = canMarkTestSources;
+    myModuleSourceRootEditHandlers = moduleSourceRootEditHandlers;
   }
 
   @Nullable
@@ -102,10 +100,9 @@
   }
 
   protected void addFolderGroupComponents() {
-    final List<ContentFolder> sources = new ArrayList<ContentFolder>();
-    final List<ContentFolder> testSources = new ArrayList<ContentFolder>();
     final List<ContentFolder> excluded = new ArrayList<ContentFolder>();
     final SourceFolder[] sourceFolders = getContentEntry().getSourceFolders();
+    MultiMap<JpsModuleSourceRootType<?>, SourceFolder> folderByType = new MultiMap<JpsModuleSourceRootType<?>, SourceFolder>();
     for (SourceFolder folder : sourceFolders) {
       if (folder.isSynthetic()) {
         continue;
@@ -114,12 +111,7 @@
       if (folderFile != null && (isExcluded(folderFile) || isUnderExcludedDirectory(folderFile))) {
         continue;
       }
-      if (folder.isTestSource()) {
-        testSources.add(folder);
-      }
-      else {
-        sources.add(folder);
-      }
+      folderByType.putValue(folder.getRootType(), folder);
     }
 
     final ExcludeFolder[] excludeFolders = getContentEntry().getExcludeFolders();
@@ -129,18 +121,21 @@
       }
     }
 
-    if (!sources.isEmpty() && myCanMarkSources) {
-      final JComponent sourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.sources.group"), sources.toArray(new ContentFolder[sources.size()]),
-                                                                     SOURCES_COLOR);
-      this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
+    Insets insets = new Insets(0, 0, 10, 0);
+    GridBagConstraints constraints = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, insets, 0, 0);
+    for (ModuleSourceRootEditHandler<?> editor : myModuleSourceRootEditHandlers) {
+      Collection<SourceFolder> folders = folderByType.get(editor.getRootType());
+      if (folders.isEmpty()) continue;
+
+      ContentFolder[] foldersArray = folders.toArray(new ContentFolder[folders.size()]);
+      final JComponent sourcesComponent = createFolderGroupComponent(editor.getRootsGroupTitle(), foldersArray, editor.getRootsGroupColor(), editor);
+      add(sourcesComponent, constraints);
     }
-    if (!testSources.isEmpty() && myCanMarkTestSources) {
-      final JComponent testSourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.test.sources.group"), testSources.toArray(new ContentFolder[testSources.size()]), TESTS_COLOR);
-      this.add(testSourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
-    }
+
     if (!excluded.isEmpty()) {
-      final JComponent excludedComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.excluded.group"), excluded.toArray(new ContentFolder[excluded.size()]), EXCLUDED_COLOR);
-      this.add(excludedComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
+      final JComponent excludedComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.excluded.group"), excluded.toArray(new ContentFolder[excluded.size()]), EXCLUDED_COLOR,
+                                                                      null);
+      this.add(excludedComponent, constraints);
     }
   }
 
@@ -167,23 +162,28 @@
     return panel;
   }
 
-  protected JComponent createFolderGroupComponent(String title, ContentFolder[] folders, Color foregroundColor) {
+  protected JComponent createFolderGroupComponent(String title,
+                                                  ContentFolder[] folders,
+                                                  Color foregroundColor,
+                                                  @Nullable ModuleSourceRootEditHandler<?> editor) {
     final JPanel panel = new JPanel(new GridLayoutManager(folders.length, 3, new Insets(1, 17, 0, 2), 0, 1));
     panel.setOpaque(false);
 
     for (int idx = 0; idx < folders.length; idx++) {
       final ContentFolder folder = folders[idx];
       final int verticalPolicy = idx == folders.length - 1? GridConstraints.SIZEPOLICY_CAN_GROW : GridConstraints.SIZEPOLICY_FIXED;
-      panel.add(createFolderComponent(folder, foregroundColor), new GridConstraints(idx, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_CAN_SHRINK, verticalPolicy, null, null, null));
+      panel.add(createFolderComponent(folder, foregroundColor, editor), new GridConstraints(idx, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_CAN_SHRINK, verticalPolicy, null, null, null));
       int column = 1;
       int colspan = 2;
 
-      JComponent additionalComponent = createAdditionalComponent(folder);
-      if (additionalComponent != null) {
-        panel.add(additionalComponent, new GridConstraints(idx, column++, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, verticalPolicy, null, null, null));
-        colspan = 1;                              
+      if (editor != null) {
+        JComponent additionalComponent = createRootPropertiesEditor(editor, (SourceFolder)folder);
+        if (additionalComponent != null) {
+          panel.add(additionalComponent, new GridConstraints(idx, column++, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, verticalPolicy, null, null, null));
+          colspan = 1;
+        }
       }
-      panel.add(createFolderDeleteComponent(folder), new GridConstraints(idx, column, 1, colspan, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, verticalPolicy, null, null, null));
+      panel.add(createFolderDeleteComponent(folder, editor), new GridConstraints(idx, column, 1, colspan, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, verticalPolicy, null, null, null));
     }
 
     final JLabel titleLabel = new JLabel(title);
@@ -202,7 +202,7 @@
   }
 
   @Nullable
-  protected JComponent createAdditionalComponent(ContentFolder folder) {
+  protected JComponent createRootPropertiesEditor(ModuleSourceRootEditHandler<?> editor, SourceFolder folder) {
     return null;
   }
 
@@ -211,16 +211,14 @@
     myComponentToForegroundMap.put(component, foreground);
   }
 
-  private JComponent createFolderComponent(final ContentFolder folder, Color foreground) {
+  private <P extends JpsElement> JComponent createFolderComponent(final ContentFolder folder, Color foreground, ModuleSourceRootEditHandler<P> editor) {
     final VirtualFile folderFile = folder.getFile();
     final VirtualFile contentEntryFile = getContentEntry().getFile();
-    final String packagePrefix = folder instanceof SourceFolder? ((SourceFolder)folder).getPackagePrefix() : "";
+    final String properties = folder instanceof SourceFolderImpl? StringUtil.notNullize(
+      editor.getPropertiesString((P)((SourceFolderImpl)folder).getJpsElement().getProperties())) : "";
     if (folderFile != null && contentEntryFile != null) {
       String path = folderFile.equals(contentEntryFile)? "." : VfsUtilCore.getRelativePath(folderFile, contentEntryFile, File.separatorChar);
-      if (!packagePrefix.isEmpty()) {
-        path = path + " (" + packagePrefix + ")";
-      }
-      HoverHyperlinkLabel hyperlinkLabel = new HoverHyperlinkLabel(path, foreground);
+      HoverHyperlinkLabel hyperlinkLabel = new HoverHyperlinkLabel(path + properties, foreground);
       hyperlinkLabel.setMinimumSize(new Dimension(0, 0));
       hyperlinkLabel.addHyperlinkListener(new HyperlinkListener() {
         @Override
@@ -233,10 +231,7 @@
     }
     else {
       String path = toRelativeDisplayPath(folder.getUrl(), getContentEntry().getUrl());
-      if (!packagePrefix.isEmpty()) {
-        path = path + " (" + packagePrefix + ")";
-      }
-      final JLabel pathLabel = new JLabel(path);
+      final JLabel pathLabel = new JLabel(path + properties);
       pathLabel.setOpaque(false);
       pathLabel.setForeground(Color.RED);
 
@@ -244,13 +239,11 @@
     }
   }
 
-  private JComponent createFolderDeleteComponent(final ContentFolder folder) {
+  private JComponent createFolderDeleteComponent(final ContentFolder folder, @Nullable ModuleSourceRootEditHandler<?> editor) {
     final String tooltipText;
     if (folder.getFile() != null && getContentEntry().getFile() != null) {
-      if (folder instanceof SourceFolder) {
-        tooltipText = ((SourceFolder)folder).isTestSource()
-                      ? ProjectBundle.message("module.paths.unmark.tests.tooltip")
-                      : ProjectBundle.message("module.paths.unmark.source.tooltip");
+      if (editor != null) {
+        tooltipText = editor.getUnmarkRootActionName();
       }
       else if (folder instanceof ExcludeFolder) {
         tooltipText = ProjectBundle.message("module.paths.include.excluded.tooltip");
@@ -313,7 +306,7 @@
 
   protected static String toRelativeDisplayPath(String url, String ancestorUrl) {
     if (!StringUtil.endsWithChar(ancestorUrl, '/')) {
-      ancestorUrl = ancestorUrl + "/";
+      ancestorUrl += "/";
     }
     if (url.startsWith(ancestorUrl)) {
       return url.substring(ancestorUrl.length()).replace('/', File.separatorChar);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/IconSet.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/IconSet.java
index a70f2e0..e4f0c67 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/IconSet.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/IconSet.java
@@ -17,8 +17,11 @@
 package com.intellij.openapi.roots.ui.configuration;
 
 import com.intellij.icons.AllIcons;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
+import java.util.List;
 
 /**
  * @author Eugene Zhuravlev
@@ -31,7 +34,13 @@
     return isTestSource ? AllIcons.Modules.TestRoot : AllIcons.Modules.SourceRoot;
   }
 
-  public static Icon getSourceFolderIcon(boolean isTestSource) {
-    return isTestSource ? AllIcons.Modules.TestSourceFolder : AllIcons.Modules.SourceFolder;
+  @Nullable
+  public static Icon getSourceRootIcon(JpsModuleSourceRootType<?> type, List<ModuleSourceRootEditHandler<?>> handlers) {
+    for (ModuleSourceRootEditHandler<?> handler : handlers) {
+      if (handler.getRootType().equals(type)) {
+        return handler.getRootIcon();
+      }
+    }
+    return null;
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaModuleSourceRootEditHandler.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaModuleSourceRootEditHandler.java
new file mode 100644
index 0000000..305802f
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaModuleSourceRootEditHandler.java
@@ -0,0 +1,82 @@
+/*
+ * 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.intellij.openapi.roots.ui.configuration;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
+import com.intellij.openapi.project.ProjectBundle;
+import com.intellij.ui.DarculaColors;
+import com.intellij.ui.JBColor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+/**
+ * @author nik
+ */
+public class JavaModuleSourceRootEditHandler extends JavaSourceRootEditHandlerBase {
+  private static final Color SOURCES_COLOR = new JBColor(new Color(0x0A50A1), DarculaColors.BLUE);
+
+  public JavaModuleSourceRootEditHandler() {
+    super(JavaSourceRootType.SOURCE);
+  }
+
+  @NotNull
+  @Override
+  public String getRootTypeName() {
+    return ProjectBundle.message("module.toggle.sources.action");
+  }
+
+  @NotNull
+  @Override
+  public String getRootsGroupTitle() {
+    return ProjectBundle.message("module.paths.sources.group");
+  }
+
+  @NotNull
+  @Override
+  public Icon getRootIcon() {
+    return AllIcons.Modules.SourceRoot;
+  }
+
+  @Nullable
+  @Override
+  public Icon getFolderUnderRootIcon() {
+    return AllIcons.Modules.SourceFolder;
+  }
+
+  @Override
+  public CustomShortcutSet getMarkRootShortcutSet() {
+    return new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK));
+  }
+
+  @NotNull
+  @Override
+  public Color getRootsGroupColor() {
+    return SOURCES_COLOR;
+  }
+
+  @NotNull
+  @Override
+  public String getUnmarkRootActionName() {
+    return ProjectBundle.message("module.paths.unmark.source.tooltip");
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootEditHandlerBase.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootEditHandlerBase.java
new file mode 100644
index 0000000..a2aa899
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootEditHandlerBase.java
@@ -0,0 +1,81 @@
+/*
+ * 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.intellij.openapi.roots.ui.configuration;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.project.ProjectBundle;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.ui.roots.IconActionComponent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author nik
+ */
+public abstract class JavaSourceRootEditHandlerBase extends ModuleSourceRootEditHandler<JpsSimpleElement<JavaSourceRootProperties>> {
+  public JavaSourceRootEditHandlerBase(JpsModuleSourceRootType<JpsSimpleElement<JavaSourceRootProperties>> rootType) {
+    super(rootType);
+  }
+
+  @NotNull
+  @Override
+  public JpsSimpleElement<JavaSourceRootProperties> createDefaultProperties() {
+    return JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties());
+  }
+
+  @Nullable
+  @Override
+  public String getPropertiesString(@NotNull JpsSimpleElement<JavaSourceRootProperties> properties) {
+    String packagePrefix = properties.getData().getPackagePrefix();
+    return packagePrefix.isEmpty() ? null : " (" + packagePrefix + ")";
+  }
+
+  @Nullable
+  @Override
+  public JComponent createPropertiesEditor(@NotNull final SourceFolder folder,
+                                           @NotNull final JComponent parentComponent,
+                                           @NotNull final ContentRootPanel.ActionCallback callback) {
+    final IconActionComponent iconComponent = new IconActionComponent(AllIcons.Modules.SetPackagePrefix,
+                                                                      AllIcons.Modules.SetPackagePrefixRollover,
+                                                                      ProjectBundle.message("module.paths.package.prefix.tooltip"), new Runnable() {
+      @Override
+      public void run() {
+        final String message = ProjectBundle.message("module.paths.package.prefix.prompt",
+                                                     ContentRootPanel.toRelativeDisplayPath(folder.getUrl(), folder.getContentEntry().getUrl() + ":"));
+        final String prefix = Messages.showInputDialog(parentComponent, message,
+                                                       ProjectBundle.message("module.paths.package.prefix.title"),
+                                                       Messages.getQuestionIcon(), folder.getPackagePrefix(), null);
+        if (prefix != null) {
+          folder.setPackagePrefix(prefix);
+          callback.onSourceRootPropertiesChanged(folder);
+        }
+      }
+    });
+    final JPanel panel = new JPanel(new BorderLayout());
+    panel.setOpaque(false);
+    panel.add(iconComponent, BorderLayout.CENTER);
+    panel.add(Box.createHorizontalStrut(3), BorderLayout.EAST);
+    return panel;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaTestSourceRootEditHandler.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaTestSourceRootEditHandler.java
new file mode 100644
index 0000000..3ae4fbb
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/JavaTestSourceRootEditHandler.java
@@ -0,0 +1,81 @@
+/*
+ * 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.intellij.openapi.roots.ui.configuration;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
+import com.intellij.openapi.project.ProjectBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+/**
+ * @author nik
+ */
+public class JavaTestSourceRootEditHandler extends JavaSourceRootEditHandlerBase {
+  private static final Color TESTS_COLOR = new Color(0x008C2E);
+
+  public JavaTestSourceRootEditHandler() {
+    super(JavaSourceRootType.TEST_SOURCE);
+  }
+
+
+  @NotNull
+  @Override
+  public String getRootTypeName() {
+    return ProjectBundle.message("module.toggle.test.sources.action");
+  }
+
+  @NotNull
+  @Override
+  public String getRootsGroupTitle() {
+    return ProjectBundle.message("module.paths.test.sources.group");
+  }
+
+  @NotNull
+  @Override
+  public Icon getRootIcon() {
+    return AllIcons.Modules.TestRoot;
+  }
+
+  @Nullable
+  @Override
+  public Icon getFolderUnderRootIcon() {
+    return AllIcons.Modules.TestSourceFolder;
+  }
+
+  @Override
+  public CustomShortcutSet getMarkRootShortcutSet() {
+    return new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK));
+  }
+
+  @NotNull
+  @Override
+  public Color getRootsGroupColor() {
+    return TESTS_COLOR;
+  }
+
+  @NotNull
+  @Override
+  public String getUnmarkRootActionName() {
+    return ProjectBundle.message("module.paths.unmark.tests.tooltip");
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModuleSourceRootEditHandler.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModuleSourceRootEditHandler.java
new file mode 100644
index 0000000..86cb5f9
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModuleSourceRootEditHandler.java
@@ -0,0 +1,89 @@
+/*
+ * 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.intellij.openapi.roots.ui.configuration;
+
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.roots.SourceFolder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author nik
+ */
+public abstract class ModuleSourceRootEditHandler<P extends JpsElement> {
+  public static final ExtensionPointName<ModuleSourceRootEditHandler> EP_NAME = ExtensionPointName.create("com.intellij.projectStructure.sourceRootEditHandler");
+  private final JpsModuleSourceRootType<P> myRootType;
+
+  protected ModuleSourceRootEditHandler(JpsModuleSourceRootType<P> rootType) {
+    myRootType = rootType;
+  }
+
+  @Nullable
+  public static ModuleSourceRootEditHandler<?> findEditHandler(JpsModuleSourceRootType<?> type) {
+    for (ModuleSourceRootEditHandler editor : EP_NAME.getExtensions()) {
+      if (editor.getRootType().equals(type)) {
+        return editor;
+      }
+    }
+    return null;
+  }
+
+  public final JpsModuleSourceRootType<P> getRootType() {
+    return myRootType;
+  }
+
+  @NotNull
+  public abstract String getRootTypeName();
+
+  @NotNull
+  public abstract Icon getRootIcon();
+
+  @Nullable
+  public abstract Icon getFolderUnderRootIcon();
+
+  @Nullable
+  public abstract CustomShortcutSet getMarkRootShortcutSet();
+
+  @NotNull
+  public abstract String getRootsGroupTitle();
+
+  @NotNull
+  public abstract Color getRootsGroupColor();
+
+
+  @NotNull
+  public abstract String getUnmarkRootActionName();
+
+  @NotNull
+  public abstract P createDefaultProperties();
+
+  @Nullable
+  public String getPropertiesString(@NotNull P properties) {
+    return null;
+  }
+
+  @Nullable
+  public JComponent createPropertiesEditor(@NotNull SourceFolder folder, @NotNull JComponent parentComponent,
+                                           @NotNull ContentRootPanel.ActionCallback callback) {
+    return null;
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/PlatformContentEntriesConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/PlatformContentEntriesConfigurable.java
index 998310b..a818b4b 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/PlatformContentEntriesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/PlatformContentEntriesConfigurable.java
@@ -11,6 +11,7 @@
 import com.intellij.openapi.roots.ModuleRootManager;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import javax.swing.*;
 import java.awt.*;
@@ -21,16 +22,14 @@
  */
 public class PlatformContentEntriesConfigurable implements Configurable {
   private final Module myModule;
-  private final boolean myCanMarkSources;
-  private final boolean myCanMarkTestSources;
+  private final JpsModuleSourceRootType<?>[] myRootTypes;
   private final JPanel myTopPanel = new JPanel(new BorderLayout());
   private ModifiableRootModel myModifiableModel;
   private CommonContentEntriesEditor myEditor;
 
-  public PlatformContentEntriesConfigurable(final Module module, boolean canMarkSources, boolean canMarkTestSources) {
+  public PlatformContentEntriesConfigurable(final Module module, JpsModuleSourceRootType<?>... rootTypes) {
     myModule = module;
-    myCanMarkSources = canMarkSources;
-    myCanMarkTestSources = canMarkTestSources;
+    myRootTypes = rootTypes;
   }
 
   @Override
@@ -69,7 +68,7 @@
           return DefaultFacetsProvider.INSTANCE;
         }
       };
-    myEditor = new CommonContentEntriesEditor(myModule.getName(), moduleConfigurationState, myCanMarkSources, myCanMarkTestSources) {
+    myEditor = new CommonContentEntriesEditor(myModule.getName(), moduleConfigurationState, myRootTypes) {
       @Override
       protected List<ContentEntry> addContentEntries(VirtualFile[] files) {
         List<ContentEntry> entries = super.addContentEntries(files);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java
index 6a3daf44..3fae3c6 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java
@@ -16,14 +16,16 @@
 
 package com.intellij.openapi.roots.ui.configuration.actions;
 
-import com.intellij.icons.AllIcons;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.project.ProjectBundle;
 import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.roots.impl.SourceFolderImpl;
 import com.intellij.openapi.roots.ui.configuration.ContentEntryEditor;
 import com.intellij.openapi.roots.ui.configuration.ContentEntryTreeEditor;
+import com.intellij.openapi.roots.ui.configuration.ModuleSourceRootEditHandler;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.jps.model.JpsElement;
 
 import javax.swing.*;
 
@@ -31,25 +33,18 @@
  * @author Eugene Zhuravlev
  * @since Oct 14, 2003
  */
-public class ToggleSourcesStateAction extends ContentEntryEditingAction {
+public class ToggleSourcesStateAction<P extends JpsElement> extends ContentEntryEditingAction {
   private final ContentEntryTreeEditor myEntryTreeEditor;
-  private final boolean myEditTestSources;
+  private final ModuleSourceRootEditHandler<P> myEditHandler;
 
-  public ToggleSourcesStateAction(JTree tree, ContentEntryTreeEditor entryEditor, boolean editTestSources) {
+  public ToggleSourcesStateAction(JTree tree, ContentEntryTreeEditor entryEditor, ModuleSourceRootEditHandler<P> editHandler) {
     super(tree);
     myEntryTreeEditor = entryEditor;
-    myEditTestSources = editTestSources;
+    myEditHandler = editHandler;
     final Presentation templatePresentation = getTemplatePresentation();
-    if (editTestSources) {
-      templatePresentation.setText(ProjectBundle.message("module.toggle.test.sources.action"));
-      templatePresentation.setDescription(ProjectBundle.message("module.toggle.test.sources.action.description"));
-      templatePresentation.setIcon(AllIcons.Modules.TestRoot);
-    }
-    else {
-      templatePresentation.setText(ProjectBundle.message("module.toggle.sources.action"));
-      templatePresentation.setDescription(ProjectBundle.message("module.toggle.sources.action.description"));
-      templatePresentation.setIcon(AllIcons.Modules.SourceRoot);
-    }
+    templatePresentation.setText(editHandler.getRootTypeName());
+    templatePresentation.setDescription(ProjectBundle.message("module.toggle.sources.action.description", editHandler.getRootType()));
+    templatePresentation.setIcon(editHandler.getRootIcon());
   }
 
   @Override
@@ -58,7 +53,7 @@
     if (selectedFiles.length == 0) return false;
 
     final ContentEntryEditor editor = myEntryTreeEditor.getContentEntryEditor();
-    return myEditTestSources ? editor.isTestSource(selectedFiles[0]) : editor.isSource(selectedFiles[0]);
+    return myEditHandler.getRootType().equals(editor.getRootType(selectedFiles[0]));
   }
 
   @Override
@@ -71,20 +66,23 @@
       final SourceFolder sourceFolder = contentEntryEditor.getSourceFolder(selectedFile);
       if (isSelected) {
         if (sourceFolder == null) { // not marked yet
-          contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources, "");
+          P properties = myEditHandler.createDefaultProperties();
+          contentEntryEditor.addSourceFolder(selectedFile, myEditHandler.getRootType(), properties);
         }
-        else {
-          if (myEditTestSources != sourceFolder.isTestSource()) {
-            final String packagePrefix = sourceFolder.getPackagePrefix();
-            contentEntryEditor.removeSourceFolder(sourceFolder);
-            contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources, packagePrefix);
+        else if (!myEditHandler.getRootType().equals(sourceFolder.getRootType())) {
+          P properties;
+          if (myEditHandler.getRootType().getClass().equals(sourceFolder.getRootType().getClass())) {
+            properties = (P)((SourceFolderImpl)sourceFolder).getJpsElement().getProperties().getBulkModificationSupport().createCopy();
           }
+          else {
+            properties = myEditHandler.createDefaultProperties();
+          }
+          contentEntryEditor.removeSourceFolder(sourceFolder);
+          contentEntryEditor.addSourceFolder(selectedFile, myEditHandler.getRootType(), properties);
         }
       }
-      else {
-        if (sourceFolder != null) { // already marked
-          contentEntryEditor.removeSourceFolder(sourceFolder);
-        }
+      else if (sourceFolder != null) { // already marked
+        contentEntryEditor.removeSourceFolder(sourceFolder);
       }
     }
   }
@@ -92,7 +90,6 @@
   @Override
   public void update(final AnActionEvent e) {
     super.update(e);
-    final Presentation presentation = e.getPresentation();
-    presentation.setText(ProjectBundle.message(myEditTestSources ? "module.toggle.test.sources.action" : "module.toggle.sources.action"));
+    e.getPresentation().setText(myEditHandler.getRootTypeName());
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/pom/wrappers/PsiEventWrapperAspect.java b/platform/lang-impl/src/com/intellij/pom/wrappers/PsiEventWrapperAspect.java
index e5d6452..54c461c 100644
--- a/platform/lang-impl/src/com/intellij/pom/wrappers/PsiEventWrapperAspect.java
+++ b/platform/lang-impl/src/com/intellij/pom/wrappers/PsiEventWrapperAspect.java
@@ -32,7 +32,6 @@
 import com.intellij.psi.impl.PsiManagerImpl;
 import com.intellij.psi.impl.PsiTreeChangeEventImpl;
 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
-import com.intellij.psi.impl.source.tree.CompositeElement;
 
 import java.util.Collections;
 
@@ -107,7 +106,6 @@
             psiEvent.setOffset(treeElement.getStartOffset());
             psiEvent.setParent(psiChild);
             psiEvent.setOldLength(changeByChild.getOldLength());
-            psiEvent.setGenericChange(treeElement instanceof CompositeElement);
             manager.childrenChanged(psiEvent);
             break;
           case ChangeInfo.REMOVED:
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java
index 88d3dd2..66f6a65 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java
@@ -403,6 +403,14 @@
     InjectedLanguageUtil.enumerate(host, visitor);
   }
 
+  @Override
+  public void enumerateEx(@NotNull PsiElement host,
+                          @NotNull PsiFile containingFile,
+                          boolean probeUp,
+                          @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
+    InjectedLanguageUtil.enumerate(host, containingFile, probeUp, visitor);
+  }
+
   private final Map<Class,MultiHostInjector[]> myInjectorsClone = new HashMap<Class, MultiHostInjector[]>();
   @TestOnly
   public static void pushInjectors(@NotNull Project project) {
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 c381c79..572a23b 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -388,6 +388,10 @@
       FileUtil.delete(IndexInfrastructure.getIndexRootDir(name));
       IndexInfrastructure.rewriteVersion(versionFile, version);
     }
+
+    initIndexStorage(extension, version, versionFile);
+
+    // save versions at last, they must be saved after initIndexVersion as it also can rewrite version
     Map<FileType, Integer> versionMap = extension.getVersionMap();
     for (Map.Entry<FileType, Integer> entry : versionMap.entrySet()) {
       ID stubId = IndexInfrastructure.getStubId(name, entry.getKey());
@@ -398,7 +402,6 @@
         IndexInfrastructure.rewriteVersion(file, stubVersion);
       }
     }
-    initIndexStorage(extension, version, versionFile);
     return versionChanged;
   }
 
diff --git a/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java b/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java
index 943cbbf..d5906e5 100644
--- a/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java
+++ b/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java
@@ -68,7 +68,6 @@
       createSettings("other-module-run", new MyModuleBasedConfiguration("other-module-run-config", getProject(), getModule())),
       mySettings
     );
-    myManager.myManager.myExternalSettings.put(myManager.myRemoverKey, Collections.singletonList(mySettings));
     myConfigurations = Collections.unmodifiableCollection(configs);
   }
 
@@ -108,13 +107,13 @@
 
   public void testBeforeOtherModuleRemoved() throws Exception {
     myRemovedSettings.clear();
-    myManager.moduleRemoved(getProject(), getModule());
+    myManager.beforeModuleRemoved(getProject(), getModule());
     assertEmpty("No settings should be removed", myRemovedSettings);
   }
 
   public void testBeforeMyModuleRemoved() throws Exception {
     myRemovedSettings.clear();
-    myManager.moduleRemoved(getProject(), myModule);
+    myManager.beforeModuleRemoved(getProject(), myModule);
     assertSameElements("one run config should be removed", myRemovedSettings, Collections.singleton(mySettings));
   }
 
diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
index a24f6c7..d38f86e 100644
--- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
+++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
@@ -272,6 +272,7 @@
     }
 
     Runnable runnable = new Runnable() {
+      @Override
       public void run() {
         Messages.showMessageDialog(message, title, Messages.getErrorIcon());
       }
@@ -320,6 +321,7 @@
       if (!currentTimestamp.equals(previousTimestamp)) {
         final Ref<Boolean> extract = new Ref<Boolean>();
         Runnable r = new Runnable() {
+          @Override
           public void run() {
             final ConfirmExtractDialog dialog = new ConfirmExtractDialog();
             if (dialog.isToBeShown()) {
@@ -336,10 +338,10 @@
         try {
           GuiUtils.runOrInvokeAndWait(r);
         }
-        catch (InvocationTargetException e) {
+        catch (InvocationTargetException ignored) {
           extract.set(false);
         }
-        catch (InterruptedException e) {
+        catch (InterruptedException ignored) {
           extract.set(false);
         }
 
@@ -359,8 +361,10 @@
         }
 
         ApplicationManager.getApplication().invokeLater(new Runnable() {
+          @Override
           public void run() {
             new Task.Backgroundable(null, "Extracting files...", true) {
+              @Override
               public void run(@NotNull final ProgressIndicator indicator) {
                 final int size = zipFile.size();
                 final int[] counter = new int[]{0};
@@ -374,6 +378,7 @@
                     myImportantOnly = importantOnly;
                   }
 
+                  @Override
                   public boolean accept(@NotNull File dir, @NotNull String name) {
                     indicator.checkCanceled();
                     boolean result = myImportantOnly == myImportantDirs.contains(dir);
@@ -426,24 +431,29 @@
       init();
     }
 
+    @Override
     protected boolean isToBeShown() {
       return getGeneralSettingsInstance().isConfirmExtractFiles();
     }
 
+    @Override
     protected void setToBeShown(boolean value, boolean onOk) {
       getGeneralSettingsInstance().setConfirmExtractFiles(value);
     }
 
+    @Override
     protected boolean shouldSaveOptionsOnCancel() {
       return true;
     }
 
+    @Override
     @NotNull
     protected Action[] createActions() {
       setOKButtonText(CommonBundle.getYesButtonText());
       return new Action[]{getOKAction(), getCancelAction()};
     }
 
+    @Override
     protected JComponent createCenterPanel() {
       JPanel panel = new JPanel(new BorderLayout());
       String message = "The files are inside an archive, do you want them to be extracted?";
diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java
index b66cebe..d722c2c 100644
--- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java
+++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -141,7 +141,7 @@
     return myParentDescriptor;
   }
 
-  public T getValue() {
+  public final T getValue() {
     if (myValue == null) {
       return null;
     }
diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
index 392314f..a9e007c 100644
--- a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
+++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
@@ -18,10 +18,12 @@
 
 import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
 import java.util.ArrayList;
 
-public class SimpleColoredText {
+public class SimpleColoredText implements ColoredTextContainer {
   private final ArrayList<String> myTexts;
   private final ArrayList<SimpleTextAttributes> myAttributes;
   private String myCachedToString = null;
@@ -36,12 +38,21 @@
     append(fragment, attributes);
   }
 
+  @Override
   public void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes){
     myTexts.add(fragment);
     myCachedToString = null;
     myAttributes.add(attributes);
   }
 
+  @Override
+  public void setIcon(@Nullable Icon icon) {
+  }
+
+  @Override
+  public void setToolTipText(String text) {
+  }
+
   public void clear() {
     myTexts.clear();
     myCachedToString = null;
diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java
index 56bab6e..05c5a1a 100644
--- a/platform/platform-api/src/com/intellij/util/Alarm.java
+++ b/platform/platform-api/src/com/intellij/util/Alarm.java
@@ -255,17 +255,7 @@
 
     private Request(@NotNull final Runnable task, @Nullable ModalityState modalityState, long delayMillis) {
       synchronized (LOCK) {
-        myTask = new Runnable() {
-          @Override
-          public void run() {
-            try {
-              task.run();
-            }
-            catch (Exception e) {
-              LOG.error("Exception in task " + task, e);
-            }
-          }
-        };
+        myTask = task;
         myModalityState = modalityState;
         myDelay = delayMillis;
       }
@@ -296,10 +286,15 @@
 
             if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
               //noinspection SSBasedInspection
-              SwingUtilities.invokeLater(task);
+              SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                  QueueProcessor.runSafely(task);
+                }
+              });
             }
             else {
-              task.run();
+              QueueProcessor.runSafely(task);
             }
           }
         };
diff --git a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
index 4def957e..5e76ac1 100644
--- a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
+++ b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
@@ -30,13 +30,12 @@
 import java.util.regex.Pattern;
 
 /**
-* Created with IntelliJ IDEA.
-* User: Irina.Chernushina
-* Date: 1/30/13
-* Time: 5:24 PM
+* @author Irina.Chernushina
+* @since 1/30/13
 */
 public class IdeaWideProxySelector extends ProxySelector {
   private final static Logger LOG = Logger.getInstance("#com.intellij.util.net.IdeaWideProxySelector");
+
   private final HttpConfigurable myHttpConfigurable;
   private final AtomicReference<ProxySelector> myPacProxySelector = new AtomicReference<ProxySelector>();
 
@@ -47,53 +46,67 @@
   @Override
   public List<Proxy> select(@NotNull URI uri) {
     LOG.debug("IDEA-wide proxy selector asked for " + uri.toString());
-    final String scheme = uri.getScheme();
-    if (! ("http".equals(scheme) || "https".equals(scheme))) {
-      LOG.debug("IDEA-wide proxy selector returns no proxies: not http/https scheme: " + scheme);
+
+    String scheme = uri.getScheme();
+    if (!("http".equals(scheme) || "https".equals(scheme))) {
+      LOG.debug("No proxy: not http/https scheme: " + scheme);
       return CommonProxy.NO_PROXY_LIST;
     }
+
     if (myHttpConfigurable.USE_HTTP_PROXY) {
       if (isProxyException(uri)) {
-        if (LOG.isDebugEnabled()) {
-          LOG.debug("IDEA-wide proxy selector detected that uri matches proxy exceptions: uri: " + uri.toString() +
-                    ", proxy exceptions string: '" + myHttpConfigurable.PROXY_EXCEPTIONS + "'");
-        }
+        LOG.debug("No proxy: URI '", uri, "' matches proxy exceptions [", myHttpConfigurable.PROXY_EXCEPTIONS, "]");
         return CommonProxy.NO_PROXY_LIST;
       }
-      final Proxy proxy = new Proxy(myHttpConfigurable.PROXY_TYPE_IS_SOCKS ? Proxy.Type.SOCKS : Proxy.Type.HTTP,
-                                    new InetSocketAddress(myHttpConfigurable.PROXY_HOST, myHttpConfigurable.PROXY_PORT));
-      LOG.debug("IDEA-wide proxy selector returns defined proxy: " + proxy);
+
+      if (myHttpConfigurable.PROXY_PORT < 0 || myHttpConfigurable.PROXY_PORT > 65535) {
+        LOG.debug("No proxy: invalid port: " + myHttpConfigurable.PROXY_PORT);
+        return CommonProxy.NO_PROXY_LIST;
+      }
+
+      Proxy.Type type = myHttpConfigurable.PROXY_TYPE_IS_SOCKS ? Proxy.Type.SOCKS : Proxy.Type.HTTP;
+      Proxy proxy = new Proxy(type, new InetSocketAddress(myHttpConfigurable.PROXY_HOST, myHttpConfigurable.PROXY_PORT));
+      LOG.debug("Defined proxy: ", proxy);
       myHttpConfigurable.LAST_ERROR = null;
       return Collections.singletonList(proxy);
-    } else if (myHttpConfigurable.USE_PROXY_PAC) {
+    }
+
+    if (myHttpConfigurable.USE_PROXY_PAC) {
       ProxySelector pacProxySelector = myPacProxySelector.get();
       if (pacProxySelector == null) {
-        final ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();
+        ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();
         proxySearch.setPacCacheSettings(32, 10 * 60 * 1000); // Cache 32 urls for up to 10 min.
         pacProxySelector = proxySearch.getProxySelector();
-
         myPacProxySelector.lazySet(pacProxySelector);
       }
 
       if (pacProxySelector != null) {
-        final List<Proxy> select = pacProxySelector.select(uri);
-        LOG.debug("IDEA-wide proxy selector found autodetected proxies: " + select);
+        List<Proxy> select = pacProxySelector.select(uri);
+        LOG.debug("Autodetected proxies: ", select);
         return select;
       }
-      LOG.debug("IDEA-wide proxy selector found no autodetected proxies");
+      else {
+        LOG.debug("No proxies detected");
+      }
     }
+
     return CommonProxy.NO_PROXY_LIST;
   }
 
   private boolean isProxyException(URI uri) {
     String uriHost = uri.getHost();
-    if (StringUtil.isEmptyOrSpaces(uriHost)) return false;
-    if (StringUtil.isEmptyOrSpaces(myHttpConfigurable.PROXY_EXCEPTIONS)) return false;
-    final List<String> hosts = StringUtil.split(myHttpConfigurable.PROXY_EXCEPTIONS, ",");
-    for (String hostPattern : hosts) {
-      final String regexpPattern = StringUtil.escapeToRegexp(hostPattern.trim()).replace("\\*", ".*");
-      if (Pattern.compile(regexpPattern).matcher(uriHost).matches()) return true;
+    if (StringUtil.isEmptyOrSpaces(uriHost) || StringUtil.isEmptyOrSpaces(myHttpConfigurable.PROXY_EXCEPTIONS)) {
+      return false;
     }
+
+    List<String> hosts = StringUtil.split(myHttpConfigurable.PROXY_EXCEPTIONS, ",");
+    for (String hostPattern : hosts) {
+      String regexpPattern = StringUtil.escapeToRegexp(hostPattern.trim()).replace("\\*", ".*");
+      if (Pattern.compile(regexpPattern).matcher(uriHost).matches()) {
+        return true;
+      }
+    }
+
     return false;
   }
 
@@ -104,6 +117,7 @@
       LOG.debug("generic proxy credentials (if were saved) removed");
       return;
     }
+
     final InetSocketAddress isa = sa instanceof InetSocketAddress ? (InetSocketAddress) sa : null;
     if (myHttpConfigurable.USE_HTTP_PROXY && isa != null && Comparing.equal(myHttpConfigurable.PROXY_HOST, isa.getHostName())) {
       LOG.debug("connection failed message passed to http configurable");
diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
index 6d8b97d..e5b2689 100644
--- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
+++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
@@ -34,6 +34,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.plaf.TreeUI;
 import javax.swing.plaf.basic.BasicTreeUI;
 import javax.swing.tree.*;
 import java.awt.*;
@@ -943,8 +944,16 @@
   }
 
   public static boolean isOverSelection(@NotNull final JTree tree, @NotNull final Point point) {
-    TreePath path = tree.getPathForLocation(point.x, point.y);
-    return path != null && tree.getSelectionModel().isPathSelected(path);
+    TreePath path = tree.getClosestPathForLocation(point.x, point.y);
+    if (path == null || !tree.getSelectionModel().isPathSelected(path)) return false;
+    TreeUI ui = tree.getUI();
+    Rectangle bounds;
+    if (ui instanceof WideSelectionTreeUI) {
+      bounds = ((WideSelectionTreeUI)ui).getWidePathBounds(tree, path);
+    } else {
+      bounds = tree.getPathBounds(path);
+    }
+    return bounds != null && bounds.contains(point);
   }
 
   public static void dropSelectionButUnderPoint(@NotNull JTree tree, @NotNull Point treePoint) {
diff --git a/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java
new file mode 100644
index 0000000..f8e2f4c
--- /dev/null
+++ b/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.jetbrains.ide;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import io.netty.channel.ChannelInboundHandler;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+public abstract class BinaryRequestHandler {
+  public static final ExtensionPointName<BinaryRequestHandler> EP_NAME = ExtensionPointName.create("com.intellij.binaryRequestHandler");
+
+  @NotNull
+  /**
+   * You can use uuidgen on Mac OS X to generate UUID
+   */
+  public abstract UUID getId();
+
+  public abstract ChannelInboundHandler getInboundHandler();
+}
\ No newline at end of file
diff --git a/platform/platform-api/src/org/jetbrains/ide/BuiltInServerManager.java b/platform/platform-api/src/org/jetbrains/ide/BuiltInServerManager.java
index e152dc0..e0689dd 100644
--- a/platform/platform-api/src/org/jetbrains/ide/BuiltInServerManager.java
+++ b/platform/platform-api/src/org/jetbrains/ide/BuiltInServerManager.java
@@ -17,13 +17,9 @@
 
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.extensions.ExtensionPointName;
 import org.jetbrains.annotations.Nullable;
 
 public abstract class BuiltInServerManager {
-  // Your handler will be instantiated on first user request
-  public static final ExtensionPointName<HttpRequestHandler> EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler");
-
   public static BuiltInServerManager getInstance() {
     return ServiceManager.getService(BuiltInServerManager.class);
   }
diff --git a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
index 5368582..f58a7e4e 100644
--- a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
+++ b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.ide;
 
+import com.intellij.openapi.extensions.ExtensionPointName;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.http.FullHttpRequest;
 import io.netty.handler.codec.http.HttpMethod;
@@ -23,6 +24,9 @@
 import java.io.IOException;
 
 public abstract class HttpRequestHandler {
+  // Your handler will be instantiated on first user request
+  public static final ExtensionPointName<HttpRequestHandler> EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler");
+
   public boolean isSupported(FullHttpRequest request) {
     return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD;
   }
diff --git a/platform/platform-impl/platform-impl.iml b/platform/platform-impl/platform-impl.iml
index 6cc1c8a..c88e8c9 100644
--- a/platform/platform-impl/platform-impl.iml
+++ b/platform/platform-impl/platform-impl.iml
@@ -38,6 +38,7 @@
     <orderEntry type="module" module-name="jps-model-impl" />
     <orderEntry type="module" module-name="analysis-impl" />
     <orderEntry type="library" name="jayatana" level="project" />
+    <orderEntry type="library" name="gson" level="project" />
   </component>
 </module>
 
diff --git a/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java b/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
index 0b84ea5..a58aaa1 100644
--- a/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
+++ b/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
@@ -89,9 +89,7 @@
         if (outputTypeFilter.value(outputType)) {
           final String text = event.getText();
           outputBuilder.append(text);
-          if (LOG.isDebugEnabled()) {
-            LOG.debug(text);
-          }
+          LOG.debug(text);
         }
       }
     });
@@ -116,34 +114,19 @@
                                          @Nullable VirtualFile scriptFile,
                                          String[] parameters,
                                          @Nullable Charset charset) throws ExecutionException {
-    ExecutionException ex;
-    try {
-      return doExecute(exePath, workingDirectory, scriptFile, parameters, charset);
-    }
-    catch (ExecutionException e) {
-      ex = e;
-    }
-    boolean rerun = SystemInfo.isMac;
-    if (rerun) {
+    if (SystemInfo.isMac) {
       File exeFile = new File(exePath);
-      rerun = !exeFile.isAbsolute();
-    }
-    if (rerun) {
-      File originalExeFile = PathEnvironmentVariableUtil.findInOriginalPath(exePath);
-      rerun = originalExeFile == null;
-    }
-    if (rerun) {
-      File exeFile = PathEnvironmentVariableUtil.findInPath(exePath);
-      if (exeFile != null) {
-        try {
-          return doExecute(exeFile.getAbsolutePath(), workingDirectory, scriptFile, parameters, charset);
-        } catch (ExecutionException e) {
-          LOG.info("Standby command failed too", e);
-          throw ex;
+      if (!exeFile.isAbsolute() && !exePath.contains(File.separator)) {
+        File originalResolvedExeFile = PathEnvironmentVariableUtil.findInOriginalPath(exePath);
+        if (originalResolvedExeFile == null) {
+          File resolvedExeFile = PathEnvironmentVariableUtil.findInPath(exePath);
+          if (resolvedExeFile != null) {
+            exePath = resolvedExeFile.getAbsolutePath();
+          }
         }
       }
     }
-    throw ex;
+    return doExecute(exePath, workingDirectory, scriptFile, parameters, charset);
   }
 
   @NotNull
@@ -164,8 +147,8 @@
       commandLine.setWorkDirectory(workingDirectory);
     }
 
-    LOG.debug("Command line: " + commandLine.getCommandLineString());
-    LOG.debug("Command line env: " + commandLine.getEnvironment());
+    LOG.debug("Command line: ", commandLine.getCommandLineString());
+    LOG.debug("Command line env: ", commandLine.getEnvironment());
 
     if (charset == null) {
       charset = ObjectUtils.notNull(EncodingManager.getInstance().getDefaultCharset(), CharsetToolkit.UTF8_CHARSET);
@@ -190,8 +173,7 @@
                                                                   @Nullable String workingDirectory,
                                                                   long timeout,
                                                                   Condition<Key> scriptOutputType,
-                                                                  @NonNls String... parameters)
-    throws ExecutionException {
+                                                                  @NonNls String... parameters) throws ExecutionException {
     final OSProcessHandler processHandler = execute(exePathString, workingDirectory, scriptFile, parameters);
 
     ScriptOutput output = new ScriptOutput(scriptOutputType);
@@ -202,19 +184,19 @@
       LOG.warn("Process did not complete in " + timeout / 1000 + "s");
       throw new ExecutionException(ExecutionBundle.message("script.execution.timeout", String.valueOf(timeout / 1000)));
     }
-    LOG.debug("script output: " + output.myFilteredOutput);
+    LOG.debug("script output: ", output.myFilteredOutput);
     return output;
   }
 
   public static class ScriptOutput extends ProcessAdapter {
     private final Condition<Key> myScriptOutputType;
     public final StringBuilder myFilteredOutput;
-    public final StringBuilder myMergedOutput;
+    public final StringBuffer myMergedOutput;
 
     private ScriptOutput(Condition<Key> scriptOutputType) {
       myScriptOutputType = scriptOutputType;
       myFilteredOutput = new StringBuilder();
-      myMergedOutput = new StringBuilder();
+      myMergedOutput = new StringBuffer();
     }
 
     public String getFilteredOutput() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java
index 9b7e754..86a1e73 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -193,7 +193,9 @@
       myLines.add(new AboutBoxLine(""));
 
       final Properties properties = System.getProperties();
-      myLines.add(new AboutBoxLine(IdeBundle.message("aboutbox.jdk", properties.getProperty("java.version", "unknown")), true, null));
+      final String javaVersion = properties.getProperty("java.runtime.version", properties.getProperty("java.version", "unknown"));
+      final String arch = properties.getProperty("os.arch", "");
+      myLines.add(new AboutBoxLine(IdeBundle.message("aboutbox.jdk", javaVersion, arch), true, null));
       appendLast();
       myLines.add(new AboutBoxLine(IdeBundle.message("aboutbox.vm", properties.getProperty("java.vm.name", "unknown"),
                                                      properties.getProperty("java.vendor", "unknown"))));
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java
index 2883afa..b28c831 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,16 +18,9 @@
 import com.intellij.CommonBundle;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.IdeBundle;
-import com.intellij.notification.Notification;
-import com.intellij.notification.NotificationListener;
-import com.intellij.notification.NotificationType;
-import com.intellij.notification.Notifications;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.application.ex.ApplicationEx;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
 import com.intellij.openapi.extensions.PluginId;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.ui.DialogWrapper;
@@ -35,12 +28,8 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.Function;
 import com.intellij.util.net.IOExceptionDialog;
-import com.intellij.xml.util.XmlStringUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.event.HyperlinkEvent;
 import java.io.IOException;
 import java.util.*;
 
@@ -162,7 +151,7 @@
               }
 
               if (needToRestart) {
-                notifyPluginsWereInstalled(list.size() == 1 ? list.get(0).getName() : null);
+                PluginManagerMain.notifyPluginsWereInstalled(list.size() == 1 ? list.get(0).getName() : null);
               }
             }
           }
@@ -268,33 +257,6 @@
     }
   }
 
-  private static void notifyPluginsWereInstalled(@Nullable String pluginName) {
-    final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
-    final boolean restartCapable = app.isRestartCapable();
-    String message =
-      restartCapable ? IdeBundle.message("message.idea.restart.required", ApplicationNamesInfo.getInstance().getFullProductName())
-                     : IdeBundle.message("message.idea.shutdown.required", ApplicationNamesInfo.getInstance().getFullProductName());
-    message += "<br><a href=";
-    message += restartCapable ? "\"restart\">Restart now" : "\"shutdown\">Shutdown";
-    message += "</a>";
-    Notifications.Bus.notify(new Notification("Plugins Lifecycle Group",
-                                              pluginName != null ? "Plugin \'" + pluginName + "\' was successfully installed" : "Plugins were installed",
-                                              XmlStringUtil.wrapInHtml(message), NotificationType.INFORMATION,
-                                              new NotificationListener() {
-                                                @Override
-                                                public void hyperlinkUpdate(@NotNull Notification notification,
-                                                                            @NotNull HyperlinkEvent event) {
-                                                  notification.expire();
-                                                  if (restartCapable) {
-                                                    app.restart(true);
-                                                  }
-                                                  else {
-                                                    app.exit(true);
-                                                  }
-                                                }
-                                              }));
-  }
-
 
   public PluginTable getPluginTable() {
     return host.getPluginTable();
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 9eb33fb..7b93211 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
@@ -21,10 +21,17 @@
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.ui.search.SearchUtil;
 import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationListener;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.ex.ApplicationEx;
+import com.intellij.openapi.application.ex.ApplicationManagerEx;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.*;
 import com.intellij.openapi.project.DumbAwareAction;
@@ -37,6 +44,7 @@
 import com.intellij.util.concurrency.SwingWorker;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.update.UiNotifyConnector;
+import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -294,7 +302,7 @@
   public static boolean downloadPlugins(final List<PluginNode> plugins,
                                         final List<IdeaPluginDescriptor> allPlugins,
                                         final Runnable onSuccess,
-                                        final Runnable cleanup) throws IOException {
+                                        @Nullable final Runnable cleanup) throws IOException {
     final boolean[] result = new boolean[1];
     try {
       ProgressManager.getInstance().run(new Task.Backgroundable(null, IdeBundle.message("progress.download.plugins"), true, PluginManagerUISettings.getInstance()) {
@@ -307,7 +315,7 @@
             }
           }
           finally {
-            cleanup.run();
+            if (cleanup != null) cleanup.run();
           }
         }
       });
@@ -514,6 +522,36 @@
     return false;
   }
 
+
+  public static void notifyPluginsWereInstalled(@Nullable String pluginName) {
+    final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
+    final boolean restartCapable = app.isRestartCapable();
+    String message =
+      restartCapable ? IdeBundle.message("message.idea.restart.required", ApplicationNamesInfo.getInstance().getFullProductName())
+                     : IdeBundle.message("message.idea.shutdown.required", ApplicationNamesInfo.getInstance().getFullProductName());
+    message += "<br><a href=";
+    message += restartCapable ? "\"restart\">Restart now" : "\"shutdown\">Shutdown";
+    message += "</a>";
+    Notifications.Bus.notify(new Notification("Plugins Lifecycle Group",
+                                              pluginName != null
+                                              ? "Plugin \'" + pluginName + "\' was successfully installed"
+                                              : "Plugins were installed",
+                                              XmlStringUtil.wrapInHtml(message), NotificationType.INFORMATION,
+                                              new NotificationListener() {
+                                                @Override
+                                                public void hyperlinkUpdate(@NotNull Notification notification,
+                                                                            @NotNull HyperlinkEvent event) {
+                                                  notification.expire();
+                                                  if (restartCapable) {
+                                                    app.restart(true);
+                                                  }
+                                                  else {
+                                                    app.exit(true);
+                                                  }
+                                                }
+                                              }));
+  }
+
   protected class SortByStatusAction extends ToggleAction {
 
     protected SortByStatusAction(final String title) {
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
index 2417910..33ef82f 100644
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -30,6 +30,7 @@
 import com.intellij.util.Consumer;
 import com.intellij.util.EnvironmentUtil;
 import com.intellij.util.SnappyInitializer;
+import com.intellij.util.lang.UrlClassLoader;
 import com.intellij.util.text.DateFormatUtilRt;
 import com.sun.jna.Native;
 import org.jetbrains.annotations.NonNls;
@@ -246,7 +247,7 @@
 
     if (SystemInfo.isWin2kOrNewer && !Main.isHeadless()) {
       try {
-        System.loadLibrary("focusKiller");
+        UrlClassLoader.loadPlatformLibrary("focusKiller");
         log.info("Using \"FocusKiller\" library to prevent focus stealing.");
       }
       catch (Throwable t) {
@@ -273,7 +274,7 @@
     ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance();
     log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild() + ", " +
                    DateFormatUtilRt.formatBuildDate(appInfo.getBuildDate()) + ")");
-    log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ")");
+    log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ", " + SystemInfo.OS_ARCH + ")");
     log.info("JRE: " + System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")");
     log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")");
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java
index 87c4b7f..81f7870 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java
@@ -57,6 +57,10 @@
 
   EditorHighlighter getHighlighter();
 
+  JComponent getPermanentHeaderComponent();
+
+  void setPermanentHeaderComponent(JComponent component);
+
   void setHighlighter(@NotNull EditorHighlighter highlighter);
 
   void setColorsScheme(@NotNull EditorColorsScheme scheme);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/RangeHighlighterEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/RangeHighlighterEx.java
index 767b5f9..abf776a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/RangeHighlighterEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/RangeHighlighterEx.java
@@ -19,13 +19,14 @@
  * User: max
  * Date: Jun 10, 2002
  * Time: 5:54:59 PM
- * To change template for new interface use 
+ * To change template for new interface use
  * Code Style | Class Templates options (Tools | IDE Options).
  */
 package com.intellij.openapi.editor.ex;
 
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.editor.markup.TextAttributes;
+import org.jetbrains.annotations.NotNull;
 
 public interface RangeHighlighterEx extends RangeHighlighter, RangeMarkerEx {
   boolean isAfterEndOfLine();
@@ -37,5 +38,5 @@
   @Override
   long getId();
 
-  void setTextAttributes(TextAttributes textAttributes);
+  void setTextAttributes(@NotNull TextAttributes textAttributes);
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
index c4bb90b..4c09c61 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
@@ -41,9 +41,9 @@
 import java.util.List;
 
 public class EditorUtil {
-  
+
   private static final Logger LOG = Logger.getInstance("#" + EditorUtil.class.getName());
-  
+
   private EditorUtil() { }
 
   public static int getLastVisualLineColumnNumber(@NotNull Editor editor, final int line) {
@@ -136,14 +136,14 @@
       result += calcColumnNumber(editor, softWrap.getText(), softWrapStartOffset, softWrapEndOffset);
       return result;
     }
-    
+
     CharSequence editorInfo;
     if (editor instanceof EditorImpl) {
       editorInfo = ((EditorImpl)editor).dumpState();
     }
     else {
       editorInfo = "editor's class: " + editor.getClass()
-                   + ", all soft wraps: " + editor.getSoftWrapModel().getSoftWrapsForRange(0, document.getTextLength()) 
+                   + ", all soft wraps: " + editor.getSoftWrapModel().getSoftWrapsForRange(0, document.getTextLength())
                    + ", fold regions: " + Arrays.toString(editor.getFoldingModel().getAllFoldRegions());
     }
     LogMessageEx.error(LOG, "Can't calculate last visual column", String.format(
@@ -151,7 +151,7 @@
       + "the target logical line: %s. Editor info: %s",
       line, resultLogLine, resVisStart, resVisEnd, softWraps, editorInfo
     ));
-    
+
     return resVisEnd.column;
   }
 
@@ -294,36 +294,43 @@
         "Starting calcSoftWrapUnawareOffset(). Target range: [%d; %d), target column number to map: %d, tab size: %d, "
         + "x: %d, current column: %d%n", start, end, columnNumber, tabSize, x, currentColumn[0]));
     }
-    
+
     // The main problem in a calculation is that target text may contain tabulation symbols and every such symbol may take different
     // number of logical columns to represent. E.g. it takes two columns if tab size is four and current column is two; three columns
     // if tab size is four and current column is one etc. So, first of all we check if there are tabulation symbols at the target
     // text fragment.
     boolean useOptimization = true;
-    boolean hasNonTabs = false;
-    boolean hasTabs = false;
-    int scanEndOffset = Math.min(end, start + columnNumber - currentColumn[0] + 1);
-    for (int i = start; i < scanEndOffset; i++) {
-      char c = text.charAt(i);
-      if (debugBuffer != null) {
-        debugBuffer.append(String.format("Found symbol '%c' at the offset %d%n", c, i));
-      }
-      if (c == '\t') {
-        hasTabs = true;
-        if (hasNonTabs) {
-          useOptimization = false;
-          break;
+    boolean hasTabs;
+    if ((editor instanceof EditorImpl) && !((EditorImpl)editor).hasTabs()) {
+      hasTabs = false;
+      useOptimization = true;
+    }
+    else {
+      boolean hasNonTabs = false;
+      hasTabs = false;
+      int scanEndOffset = Math.min(end, start + columnNumber - currentColumn[0] + 1);
+      for (int i = start; i < scanEndOffset; i++) {
+        char c = text.charAt(i);
+        if (debugBuffer != null) {
+          debugBuffer.append(String.format("Found symbol '%c' at the offset %d%n", c, i));
         }
-      }
-      else {
-        hasNonTabs = true;
+        if (c == '\t') {
+          hasTabs = true;
+          if (hasNonTabs) {
+            useOptimization = false;
+            break;
+          }
+        }
+        else {
+          hasNonTabs = true;
+        }
       }
     }
 
     if (debugBuffer != null) {
       debugBuffer.append(String.format("Has tabs: %b, use optimisation: %b%n", hasTabs, useOptimization));
     }
-    
+
     // Perform optimized processing if possible. 'Optimized' here means the processing when we exactly know how many logical
     // columns are occupied by tabulation symbols.
     if (useOptimization) {
@@ -454,16 +461,23 @@
       SoftWrap softWrap = editor.getSoftWrapModel().getSoftWrap(start);
       useOptimization = softWrap == null;
     }
+    boolean hasTabs = true;
     if (useOptimization) {
-      boolean hasNonTabs = false;
-      for (int i = start; i < offset; i++) {
-        if (text.charAt(i) == '\t') {
-          if (hasNonTabs) {
-            useOptimization = false;
-            break;
+      if ((editor instanceof EditorImpl) && !((EditorImpl)editor).hasTabs()) {
+        hasTabs = false;
+      }
+      else {
+        boolean hasNonTabs = false;
+        for (int i = start; i < offset; i++) {
+          if (text.charAt(i) == '\t') {
+            if (hasNonTabs) {
+              useOptimization = false;
+              break;
+            }
           }
-        } else {
-          hasNonTabs = true;
+          else {
+            hasNonTabs = true;
+          }
         }
       }
     }
@@ -471,27 +485,26 @@
     if (editor == null || useOptimization) {
       int shift = 0;
 
-      for (int i = start; i < offset; i++) {
-        char c = text.charAt(i);
-        if (c == '\n' || c == '\r') {
-          String editorInfo = editor instanceof EditorImpl ? ". Editor info: " + ((EditorImpl)editor).dumpState() : "";
-          String documentInfo;
-          if (text instanceof Dumpable) {
-            documentInfo = ((Dumpable)text).dumpState();
-          }
-          else {
-            documentInfo = "Text holder class: " + text.getClass();
-          }
-          LogMessageEx.error(
-            LOG, "detected incorrect offset -> column number calculation",
-            String.format(
-              "Symbol: '%c', its index: %d, given start: %d, given offset: %d, given tab size: %d. %s%s",
-              c, i, start, offset, tabSize, documentInfo, editorInfo
-            )
-          );
+      Document document = editor == null ? null : editor.getDocument();
+      if (document != null && start < offset-1 && document.getLineNumber(start) != document.getLineNumber(offset-1)) {
+        String editorInfo = editor instanceof EditorImpl ? ". Editor info: " + ((EditorImpl)editor).dumpState() : "";
+        String documentInfo;
+        if (text instanceof Dumpable) {
+          documentInfo = ((Dumpable)text).dumpState();
         }
-        if (c == '\t') {
-          shift += getTabLength(i + shift - start, tabSize) - 1;
+        else {
+          documentInfo = "Text holder class: " + text.getClass();
+        }
+        LogMessageEx.error(
+          LOG, "detected incorrect offset -> column number calculation",
+          "start: " + start + ", given offset: " + offset+", given tab size: " + tabSize + ". "+documentInfo+ editorInfo);
+      }
+      if (hasTabs) {
+        for (int i = start; i < offset; i++) {
+          char c = text.charAt(i);
+          if (c == '\t') {
+            shift += getTabLength(i + shift - start, tabSize) - 1;
+          }
         }
       }
       return offset - start + shift;
@@ -580,7 +593,7 @@
       char c = text.charAt(i);
       int prevX = x;
       switch (c) {
-        case '\t': 
+        case '\t':
           x = nextTabStop(x, editor);
           result += columnsNumber(x - prevX, spaceSize);
           break;
@@ -666,10 +679,10 @@
   /**
    * Delegates to the {@link #calcSurroundingRange(Editor, VisualPosition, VisualPosition)} with the
    * {@link CaretModel#getVisualPosition() caret visual position} as an argument.
-   * 
+   *
    * @param editor  target editor
    * @return        surrounding logical positions
-   * @see #calcSurroundingRange(Editor, VisualPosition, VisualPosition) 
+   * @see #calcSurroundingRange(Editor, VisualPosition, VisualPosition)
    */
   public static Pair<LogicalPosition, LogicalPosition> calcCaretLineRange(@NotNull Editor editor) {
     return calcSurroundingRange(editor, editor.getCaretModel().getVisualPosition(), editor.getCaretModel().getVisualPosition());
@@ -719,7 +732,7 @@
       }
       line = foldEndLine;
     }
-    
+
 
     LogicalPosition second = editor.visualToLogicalPosition(new VisualPosition(end.line, 0));
     for (
@@ -739,7 +752,7 @@
       }
       line = foldEndLine;
     }
-    
+
     if (second.line >= document.getLineCount()) {
       second = editor.offsetToLogicalPosition(document.getTextLength());
     }
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 840fbde..fcef9aa 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
@@ -152,6 +152,7 @@
   @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
@@ -518,6 +519,7 @@
         }
       });
     }
+    updateHasTabsFlag(document.getCharsSequence());
   }
 
   public static boolean isPresentationMode(Project project) {
@@ -1693,6 +1695,16 @@
     Point caretLocation = visualPositionToXY(getCaretModel().getVisualPosition());
     int scrollOffset = caretLocation.y - myCaretUpdateVShift;
     getScrollingModel().scrollVertically(scrollOffset);
+    updateHasTabsFlag(e.getNewFragment());
+  }
+
+  private void updateHasTabsFlag(CharSequence newChars) {
+    if (!hasTabs) {
+      hasTabs = StringUtil.contains(newChars, 0, newChars.length(), '\t');
+    }
+  }
+  public boolean hasTabs() {
+    return hasTabs;
   }
 
   public boolean isScrollToCaret() {
@@ -1930,7 +1942,7 @@
   @Override
   public void setHeaderComponent(JComponent header) {
     myHeaderPanel.removeAll();
-    header = header == null ? getUserData(PERMANENT_HEADER) : header;
+    header = header == null ? getPermanentHeaderComponent() : header;
     if (header != null) {
       myHeaderPanel.add(header);
     }
@@ -1940,13 +1952,23 @@
 
   @Override
   public boolean hasHeaderComponent() {
-    return myHeaderPanel.getComponentCount() > 0;
+    JComponent header = getHeaderComponent();
+    return header != null && header != getPermanentHeaderComponent();
+  }
+
+  @Nullable
+  public JComponent getPermanentHeaderComponent() {
+    return getUserData(PERMANENT_HEADER);
+  }
+
+  public void setPermanentHeaderComponent(@Nullable JComponent component) {
+    putUserData(PERMANENT_HEADER, component);
   }
 
   @Override
   @Nullable
   public JComponent getHeaderComponent() {
-    if (hasHeaderComponent()) {
+    if (myHeaderPanel.getComponentCount() > 0) {
       return (JComponent)myHeaderPanel.getComponent(0);
     }
     return null;
@@ -2464,7 +2486,7 @@
     // there then.
     VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition();
     VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition();
-    if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) {
+    if (selectionStartPosition.equals(selectionEndPosition)) {
       return;
     }
 
@@ -2525,7 +2547,7 @@
     // there then.
     VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition();
     VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition();
-    if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) {
+    if (selectionStartPosition.equals(selectionEndPosition)) {
       return;
     }
 
@@ -3968,8 +3990,9 @@
 
     int x = myGutterComponent.convertX(e.getX());
 
-    if (x >= myGutterComponent.getLineNumberAreaOffset() &&
-        x < myGutterComponent.getLineNumberAreaOffset() + myGutterComponent.getLineNumberAreaWidth()) {
+    int lineNumberAreaOffset = EditorGutterComponentImpl.getLineNumberAreaOffset();
+    if (x >= lineNumberAreaOffset &&
+        x < lineNumberAreaOffset + myGutterComponent.getLineNumberAreaWidth()) {
       return EditorMouseEventArea.LINE_NUMBERS_AREA;
     }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
index 051fdbf..25803d9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
@@ -359,7 +359,7 @@
     // currently there are 6 of them and restoration does not happen very often so just iteration is enough
     if (type == PlainTextFileType.INSTANCE && !fileTypeName.equals(type.getName())) {
       for (FileType fileType: getRegisteredFileTypes()) {
-        if (fileType.equals(fileType.getName())) {
+        if (fileTypeName.equals(fileType.getName())) {
           return fileType;
         }
       }
@@ -367,10 +367,6 @@
     return type;
   }
 
-  private static class FileTypeDetectorHolder {
-    private static final FileTypeDetector[] FILE_TYPE_DETECTORS = Extensions.getExtensions(FileTypeDetector.EP_NAME);
-  }
-
   private static final AtomicInteger DETECTED_COUNT = new AtomicInteger();
   private static final int DETECT_BUFFER_SIZE = 8192;
 
@@ -403,8 +399,9 @@
             else {
               text = null;
             }
+
             FileType detected = null;
-            for (FileTypeDetector detector : FileTypeDetectorHolder.FILE_TYPE_DETECTORS) {
+            for (FileTypeDetector detector : Extensions.getExtensions(FileTypeDetector.EP_NAME)) {
               detected = detector.detect(file, byteSequence, text);
               if (detected != null) break;
             }
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 cc6a59b..6cca11c 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
@@ -698,6 +698,7 @@
           JScrollPane scroll = ScrollPaneFactory.createScrollPane(c);
           scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
           scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
+          scroll.getVerticalScrollBar().setUnitIncrement(10);
           scroll.setBorder(null);
           add(scroll, BorderLayout.CENTER);
         }
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java
index 6e7b914..b7be05b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -44,7 +44,7 @@
 
   private static JEditorPane myDescriptionPanel = new JEditorPane();
 
-  protected DetectedPluginsPanel() {
+  public DetectedPluginsPanel() {
     super(PluginDownloader.class);
     final JTable entryTable = getEntryTable();
     entryTable.setTableHeader(null);
@@ -111,20 +111,24 @@
   }
 
   public boolean isChecked(final PluginDownloader downloader) {
-    return !UpdateChecker.getDisabledToUpdatePlugins().contains(downloader.getPluginId());
+    return !getSkippedPlugins().contains(downloader.getPluginId());
   }
 
   public void setChecked(final PluginDownloader downloader, final boolean checked) {
     if (checked) {
-      UpdateChecker.getDisabledToUpdatePlugins().remove(downloader.getPluginId());
+      getSkippedPlugins().remove(downloader.getPluginId());
     } else {
-      UpdateChecker.getDisabledToUpdatePlugins().add(downloader.getPluginId());
+      getSkippedPlugins().add(downloader.getPluginId());
     }
     for (Listener listener : myListeners) {
       listener.stateChanged();
     }
   }
 
+  protected Set<String> getSkippedPlugins() {
+    return UpdateChecker.getDisabledToUpdatePlugins();
+  }
+
   public void addStateListener(Listener l) {
     myListeners.add(l);
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
new file mode 100644
index 0000000..24615ca
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
@@ -0,0 +1,161 @@
+/*
+ * 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.intellij.openapi.updateSettings.impl.pluginsAdvertisement;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.intellij.ide.plugins.*;
+import com.intellij.notification.*;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationInfo;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.PluginId;
+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.startup.StartupActivity;
+import com.intellij.openapi.updateSettings.impl.PluginDownloader;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.net.HttpConfigurable;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class PluginsAdvertiser implements StartupActivity {
+  private static final Logger LOG = Logger.getInstance("#" + PluginsAdvertiser.class.getName());
+
+  public static List<PluginId> retrieve(UnknownFeature unknownFeature) {
+    final String featureType = unknownFeature.getFeatureType();
+    final String implementationName = unknownFeature.getImplementationName();
+    final String buildNumber = ApplicationInfo.getInstance().getBuild().asString();
+    final String pluginRepositoryUrl = "http://plugins.jetbrains.com/feature/getImplementations?" +
+                                       "featureType=" + featureType +
+                                       "&implementationName=" + implementationName +
+                                       "&build=" + buildNumber;
+    try {
+      HttpURLConnection connection = HttpConfigurable.getInstance().openHttpConnection(pluginRepositoryUrl);
+      connection.connect();
+      final InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
+      try {
+        final JsonElement jsonRootElement = new JsonParser().parse(streamReader);
+        final List<PluginId> result = new ArrayList<PluginId>();
+        for (JsonElement jsonElement : jsonRootElement.getAsJsonArray()) {
+          final JsonObject jsonObject = jsonElement.getAsJsonObject();
+          final JsonElement pluginId = jsonObject.get("pluginId");
+          result.add(PluginId.getId(StringUtil.unquoteString(pluginId.toString())));
+        }
+        return result;
+      }
+      finally {
+        streamReader.close();
+      }
+    }
+    catch (IOException e) {
+      LOG.info(e);
+      return null;
+    }
+  }
+
+  @Override
+  public void runActivity(@NotNull final Project project) {
+    final UnknownFeaturesCollector collectorSuggester = UnknownFeaturesCollector.getInstance(project);
+    final Set<UnknownFeature> unknownFeatures = collectorSuggester.getUnknownFeatures();
+    if (unknownFeatures.isEmpty()) return;
+    final Runnable runnable = new Runnable() {
+      public void run() {
+        final Application application = ApplicationManager.getApplication();
+        if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return;
+        ProgressManager.getInstance().run(new Task.Backgroundable(project, "Search for non-bundled plugins in plugin repository...") {
+          private final Set<PluginDownloader> myPlugins = new HashSet<PluginDownloader>();
+          private List<IdeaPluginDescriptor> myAllPlugins;
+
+          @Override
+          public void run(@NotNull ProgressIndicator indicator) {
+            int idx = 0;
+            final Set<PluginId> ids = new HashSet<PluginId>();
+            for (UnknownFeature feature : unknownFeatures) {
+              indicator.setText("Searching for: " + feature.getFeatureType());
+              final List<PluginId> pluginId = retrieve(feature);
+              if (pluginId != null) {
+                //do not suggest to download disabled plugins
+                final List<String> disabledPlugins = PluginManagerCore.getDisabledPlugins();
+                for (PluginId id : pluginId) {
+                  if (!disabledPlugins.contains(id.getIdString())) {
+                    ids.add(id);
+                  }
+                }
+              }
+              indicator.setFraction(idx++ / unknownFeatures.size());
+            }
+
+            try {
+              myAllPlugins = RepositoryHelper.loadPluginsFromRepository(indicator);
+              for (IdeaPluginDescriptor loadedPlugin : myAllPlugins) {
+                if (ids.contains(loadedPlugin.getPluginId())) {
+                  myPlugins.add(PluginDownloader.createDownloader(loadedPlugin));
+                }
+              }
+            }
+            catch (Exception ignore) {
+              //no notification to show
+            }
+          }
+
+          @Override
+          public void onSuccess() {
+            if (!myPlugins.isEmpty()) {
+              final String displayId = "Plugins Suggestion";
+              new NotificationGroup(displayId, NotificationDisplayType.STICKY_BALLOON, true)
+                .createNotification(displayId, "Features covered by non-bundled plugins are detected.<br>" +
+                                               "<a href=\"configure\">Configure plugins...</a><br>" +
+                                               "<a href=\"ignore\">Ignore All</a>", NotificationType.INFORMATION, new NotificationListener() {
+                @Override
+                public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
+                  if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+                    final String description = event.getDescription();
+                    if ("ignore".equals(description)) {
+                      for (UnknownFeature feature : unknownFeatures) {
+                        collectorSuggester.ignoreFeature(feature);
+                      }
+                    } else if ("configure".equals(description)) {
+                      LOG.assertTrue(myAllPlugins != null);
+                      new PluginsAdvertiserDialog(myProject, myPlugins.toArray(new PluginDownloader[myPlugins.size()]), myAllPlugins).show();
+                    }
+                    notification.expire();
+                  }
+                }
+              }).notify(project);
+            }
+          }
+        });
+      }
+    };
+
+    SwingUtilities.invokeLater(runnable);
+  }
+}
+
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiserDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiserDialog.java
new file mode 100644
index 0000000..a092d2a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiserDialog.java
@@ -0,0 +1,95 @@
+/*
+ * 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.intellij.openapi.updateSettings.impl.pluginsAdvertisement;
+
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManagerMain;
+import com.intellij.ide.plugins.PluginNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.updateSettings.impl.DetectedPluginsPanel;
+import com.intellij.openapi.updateSettings.impl.PluginDownloader;
+import com.intellij.ui.TableUtil;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+* User: anna
+*/
+public class PluginsAdvertiserDialog extends DialogWrapper {
+  private static final Logger LOG = Logger.getInstance("#" + PluginsAdvertiserDialog.class.getName());
+
+  private final PluginDownloader[] myUploadedPlugins;
+  private final List<IdeaPluginDescriptor> myAllPlugins;
+  private final HashSet<String> mySkippedPlugins = new HashSet<String>();
+
+  PluginsAdvertiserDialog(@Nullable Project project, PluginDownloader[] plugins, List<IdeaPluginDescriptor> allPlugins) {
+    super(project);
+    myUploadedPlugins = plugins;
+    myAllPlugins = allPlugins;
+    setTitle("Choose Plugins to Install");
+    init();
+  }
+
+  @Nullable
+  @Override
+  protected JComponent createCenterPanel() {
+    final DetectedPluginsPanel foundPluginsPanel = new DetectedPluginsPanel() {
+      @Override
+      protected Set<String> getSkippedPlugins() {
+        return mySkippedPlugins;
+      }
+    };
+
+    for (PluginDownloader uploadedPlugin : myUploadedPlugins) {
+      foundPluginsPanel.add(uploadedPlugin);
+    }
+    TableUtil.ensureSelectionExists(foundPluginsPanel.getEntryTable());
+    return foundPluginsPanel;
+  }
+
+  @Override
+  protected void doOKAction() {
+    final List<PluginNode> nodes = new ArrayList<PluginNode>();
+    for (PluginDownloader downloader : myUploadedPlugins) {
+      if (!mySkippedPlugins.contains(downloader.getPluginId())) {
+        final PluginNode pluginNode = PluginDownloader.createPluginNode(null, downloader);
+        if (pluginNode != null) {
+          nodes.add(pluginNode);
+        }
+      }
+    }
+    try {
+      PluginManagerMain.downloadPlugins(nodes, myAllPlugins, new Runnable() {
+        @Override
+        public void run() {
+          PluginManagerMain.notifyPluginsWereInstalled(null);
+        }
+      }, null);
+    }
+    catch (IOException e) {
+      LOG.error(e);
+    }
+    super.doOKAction();
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeature.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeature.java
new file mode 100644
index 0000000..13640ef
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeature.java
@@ -0,0 +1,57 @@
+/*
+ * 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.intellij.openapi.updateSettings.impl.pluginsAdvertisement;
+
+/**
+ * User: anna
+ */
+public class UnknownFeature {
+  private final String myFeatureType;
+  private final String myImplementationName;
+
+  public UnknownFeature(String featureType, String implementationName) {
+    myFeatureType = featureType;
+    myImplementationName = implementationName;
+  }
+
+  public String getFeatureType() {
+    return myFeatureType;
+  }
+
+  public String getImplementationName() {
+    return myImplementationName;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    UnknownFeature feature = (UnknownFeature)o;
+
+    if (!myFeatureType.equals(feature.myFeatureType)) return false;
+    if (!myImplementationName.equals(feature.myImplementationName)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myFeatureType.hashCode();
+    result = 31 * result + myImplementationName.hashCode();
+    return result;
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeaturesCollector.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeaturesCollector.java
new file mode 100644
index 0000000..0bd1410
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/UnknownFeaturesCollector.java
@@ -0,0 +1,90 @@
+/*
+ * 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.intellij.openapi.updateSettings.impl.pluginsAdvertisement;
+
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.project.Project;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * User: anna
+ */
+@State(
+  name = "UnknownFeatures",
+  storages = {
+    @Storage(
+      file = StoragePathMacros.WORKSPACE_FILE
+    )}
+)
+public class UnknownFeaturesCollector implements PersistentStateComponent<Element> {
+  @NonNls private static final String FEATURE_ID = "featureType";
+  @NonNls private static final String IMPLEMENTATION_NAME = "implementationName";
+
+  private final Set<UnknownFeature> myUnknownFeatures = new HashSet<UnknownFeature>();
+  private final Set<UnknownFeature> myIgnoredUnknownFeatures = new HashSet<UnknownFeature>();
+
+  public static UnknownFeaturesCollector getInstance(Project project) {
+    return ServiceManager.getService(project, UnknownFeaturesCollector.class);
+  }
+
+  public void registerUnknownRunConfiguration(String configurationName) {
+    registerUnknownFeature("com.intellij.configurationType", configurationName);
+  }
+  
+  public void registerUnknownFeature(String featureType, String implementationName) {
+    final UnknownFeature feature = new UnknownFeature(featureType, implementationName);
+    if (!myIgnoredUnknownFeatures.contains(feature)) {
+      myUnknownFeatures.add(feature);
+    }
+  }
+  
+  public void ignoreFeature(UnknownFeature feature) {
+    myIgnoredUnknownFeatures.add(feature);
+  }
+
+  public Set<UnknownFeature> getUnknownFeatures() {
+    return myUnknownFeatures;
+  }
+
+  @Nullable
+  @Override
+  public Element getState() {
+    if (myIgnoredUnknownFeatures.isEmpty()) return null;
+
+    final Element ignored = new Element("ignored");
+    for (UnknownFeature feature : myIgnoredUnknownFeatures) {
+      final Element option = new Element("option");
+      option.setAttribute(FEATURE_ID, feature.getFeatureType());
+      option.setAttribute(IMPLEMENTATION_NAME, feature.getImplementationName());
+      ignored.addContent(option);
+    }
+    return ignored;
+  }
+
+  @Override
+  public void loadState(Element state) {
+    myIgnoredUnknownFeatures.clear();
+    for (Element element : state.getChildren()) {
+      myIgnoredUnknownFeatures.add(
+        new UnknownFeature(element.getAttributeValue(FEATURE_ID), element.getAttributeValue(IMPLEMENTATION_NAME)));
+    }
+  }
+}
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 eb46fc8..7f0b5e8 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -13,10 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
- * @author max
- */
 package com.intellij.openapi.vfs.impl.jar;
 
 import com.intellij.notification.NotificationGroup;
@@ -48,6 +44,9 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
+/**
+ * @author max
+ */
 public class JarHandler extends JarHandlerBase {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.jar.JarHandler");
 
@@ -111,6 +110,8 @@
   private File getMirrorWithContentHash(File originalFile,
                                         FileAttributes originalAttributes) {
     File mirrorFile = null;
+    String jarDir = getJarsDir();
+
     try {
       String path = originalFile.getPath();
       CacheLibraryInfo info = CacheLibraryInfo.ourCachedLibraryInfo.get(path);
@@ -120,7 +121,7 @@
         if (originalAttributes.length == info.myFileLength &&
             Math.abs(originalAttributes.lastModified - info.myModificationTime) <= FS_TIME_RESOLUTION
            ) {
-          mirrorFile = new File(new File(getJarsDir()), info.mySnapshotPath);
+          mirrorFile = new File(new File(jarDir), info.mySnapshotPath);
           mirrorFileAttributes = FileSystemUtil.getAttributes(mirrorFile);
           if (mirrorFileAttributes != null &&
               mirrorFileAttributes.length == originalAttributes.length &&
@@ -139,7 +140,7 @@
       File tempJarFile = null;
 
       try {
-        tempJarFile = FileUtil.createTempFile(new File(getJarsDir()), originalFile.getName(), "", true, false);
+        tempJarFile = FileUtil.createTempFile(new File(jarDir), originalFile.getName(), "", true, false);
         os = new DataOutputStream(new FileOutputStream(tempJarFile));
         is = new FileInputStream(originalFile);
         byte[] buffer = new byte[20 * 1024];
@@ -154,10 +155,13 @@
           sha1.update(buffer, 0, read);
           os.write(buffer, 0, read);
         }
-      } catch (IOException ex) {
-        reportIOErrorWithJars(originalFile, mirrorFile  != null ? mirrorFile:tempJarFile, ex);
+      }
+      catch (IOException ex) {
+        File target = mirrorFile != null ? mirrorFile : tempJarFile != null ? tempJarFile : new File(jarDir);
+        reportIOErrorWithJars(originalFile, target, ex);
         return originalFile;
-      } catch (NoSuchAlgorithmException ex) {
+      }
+      catch (NoSuchAlgorithmException ex) {
         assert false;
         return originalFile; // should never happen for sha1
       }
@@ -167,7 +171,7 @@
       }
 
       byte[] digest = sha1.digest();
-      mirrorFile = new File(new File(getJarsDir()), getSnapshotName(originalFile.getName(), digest));
+      mirrorFile = new File(new File(jarDir), getSnapshotName(originalFile.getName(), digest));
       mirrorFileAttributes = FileSystemUtil.getAttributes(mirrorFile);
 
       if (mirrorFileAttributes == null ||
@@ -193,7 +197,7 @@
       CacheLibraryInfo.ourCachedLibraryInfo.force();
       return mirrorFile;
     } catch (IOException ex) {
-      reportIOErrorWithJars(originalFile, mirrorFile != null ? mirrorFile: new File(getJarsDir(), originalFile.getName()), ex);
+      reportIOErrorWithJars(originalFile, mirrorFile != null ? mirrorFile: new File(jarDir, originalFile.getName()), ex);
       return originalFile;
     }
   }
@@ -314,13 +318,13 @@
     }
   };
 
-  private void reportIOErrorWithJars(File original, File mirror, IOException e) {
+  private void reportIOErrorWithJars(File original, File target, IOException e) {
     LOG.warn(e);
-    final String path = original.getPath();
-    final String message = VfsBundle.message("jar.copy.error.message", path, mirror.getPath(), e.getMessage());
 
-    ERROR_COPY_NOTIFICATION.getValue().createNotification(message, NotificationType.ERROR).notify(null);
-
+    String path = original.getPath();
     myFileSystem.setNoCopyJarForPath(path);
+
+    String message = VfsBundle.message("jar.copy.error.message", path, target.getPath(), e.getMessage());
+    ERROR_COPY_NOTIFICATION.getValue().createNotification(message, NotificationType.ERROR).notify(null);
   }
 }
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 19af1b1..09de7d3 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
@@ -139,6 +139,8 @@
       final boolean pureMouse1Event = (me.getModifiersEx() | button1) == button1;
       if (pureMouse1Event && me.getClickCount() <= 1 && !me.isPopupTrigger()) {
         final Point point = SwingUtilities.convertPoint(meComponent, me.getPoint(), myRootPane.getContentPane());
+        JMenuBar menuBar = myRootPane.getJMenuBar();
+        point.y += menuBar != null ? menuBar.getHeight() : 0;
 
         final Component target =
           SwingUtilities.getDeepestComponentAt(myRootPane.getContentPane().getParent(), point.x, point.y);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenUrlPsiReference.java b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
similarity index 71%
rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenUrlPsiReference.java
rename to platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
index 12fd29d..9a52a56 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenUrlPsiReference.java
+++ b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
@@ -13,33 +13,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.maven.dom.references;
+package com.intellij.psi.impl;
 
 import com.intellij.ide.BrowserUtil;
-import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.impl.FakePsiElement;
+import com.intellij.psi.PsiReferenceBase;
 import org.jetbrains.annotations.NotNull;
 
-public class MavenUrlPsiReference extends MavenPsiReference {
-  public MavenUrlPsiReference(PsiElement element, String text, TextRange range) {
-    super(element, text, range);
+public class UrlPsiReference extends PsiReferenceBase<PsiElement> {
+  public UrlPsiReference(PsiElement element) {
+    super(element);
   }
 
   public PsiElement resolve() {
     return new FakePsiElement() {
       public PsiElement getParent() {
-        return myElement;
+        return getElement();
       }
 
       @Override
       public String getName() {
-        return myText;
+        return getValue();
       }
 
       @Override
       public void navigate(boolean requestFocus) {
-        BrowserUtil.launchBrowser(myText);
+        BrowserUtil.launchBrowser(getValue());
       }
     };
   }
@@ -48,4 +47,9 @@
   public Object[] getVariants() {
     return EMPTY_ARRAY;
   }
+
+  @Override
+  public boolean isSoft() {
+    return true;
+  }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java
new file mode 100644
index 0000000..9561c77
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java
@@ -0,0 +1,39 @@
+/*
+ * 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.intellij.ui.win;
+
+import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.openapi.diff.ApplicationStarterBase;
+
+
+/**
+ * @author Denis Fokin
+ */
+public class RecentProjectApplication extends ApplicationStarterBase {
+  public RecentProjectApplication() {
+    super("reopen", 1);
+  }
+
+  @Override
+  public String getUsageMessage() {
+    return String.format("This command is used for internal purpose only.");
+  }
+
+  @Override
+  protected void processCommand(String[] args) throws Exception {
+    ProjectUtil.openProject(args[1], null, false);
+  }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java
index 12ad39f..3ba433a 100644
--- a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java
+++ b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java
@@ -16,6 +16,7 @@
 package com.intellij.ui.win;
 
 import com.intellij.idea.StartupUtil;
+import com.intellij.util.lang.UrlClassLoader;
 
 import java.lang.ref.WeakReference;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -29,7 +30,7 @@
     new WeakReference<Thread>(Thread.currentThread());
 
   static {
-    System.loadLibrary("jumpListBridge");
+    UrlClassLoader.loadPlatformLibrary("jumpListBridge");
   }
 
   private synchronized static void init() {
@@ -54,7 +55,12 @@
     clearNative();
   }
 
+  /**
+   * Use #clearNative method instead of passing empty array of tasks.
+   * @param tasks
+   */
   public synchronized static void addTasks(final Task[] tasks) {
+    if (tasks.length == 0) return;
     init();
     checkThread();
     addTasksNativeForCategory("Recent", tasks);
diff --git a/platform/platform-impl/src/com/intellij/ui/win/SocketControlHelper.java b/platform/platform-impl/src/com/intellij/ui/win/SocketControlHelper.java
index 84372bf..b2f7738 100644
--- a/platform/platform-impl/src/com/intellij/ui/win/SocketControlHelper.java
+++ b/platform/platform-impl/src/com/intellij/ui/win/SocketControlHelper.java
@@ -46,7 +46,7 @@
       DataOutputStream out = new DataOutputStream(socket.getOutputStream());
       try {
 
-        out.writeUTF(ACTIVATE_COMMAND + new File(".").getAbsolutePath() + "\0" + pathToProject);
+        out.writeUTF(ACTIVATE_COMMAND + new File(".").getAbsolutePath() + "\0" + "reopen" + "\0" + pathToProject);
         out.flush();
         String response = in.readUTF();
         if (response.equals("ok")) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/ClassInstanceCache.java b/platform/platform-impl/src/com/intellij/util/SingletonInstancesCache.java
similarity index 86%
rename from plugins/groovy/src/org/jetbrains/plugins/groovy/util/ClassInstanceCache.java
rename to platform/platform-impl/src/com/intellij/util/SingletonInstancesCache.java
index 7a9f055..5d7810b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/ClassInstanceCache.java
+++ b/platform/platform-impl/src/com/intellij/util/SingletonInstancesCache.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.groovy.util;
+package com.intellij.util;
 
 import com.intellij.util.containers.ConcurrentHashMap;
 import org.jetbrains.annotations.NotNull;
@@ -6,11 +6,11 @@
 /**
  * @author Sergey Evdokimov
  */
-public class ClassInstanceCache {
+public class SingletonInstancesCache {
 
   private static final ConcurrentHashMap<String, Object> CACHE = new ConcurrentHashMap<String, Object>();
 
-  private ClassInstanceCache() {
+  private SingletonInstancesCache() {
   }
 
   @SuppressWarnings("unchecked")
diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
index 85d70892..cff39b5 100644
--- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
+++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
 import com.intellij.util.net.NetUtils;
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.*;
@@ -34,6 +35,7 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.ServerSocket;
 import java.util.Map;
 
 public class BuiltInServer implements Disposable {
@@ -68,7 +70,7 @@
       bootstrap.childHandler(new ChannelInitializer() {
         @Override
         protected void initChannel(Channel channel) throws Exception {
-          channel.pipeline().addLast(channelRegistrar, portUnificationServerHandler);
+          channel.pipeline().addLast(channelRegistrar, portUnificationServerHandler, ChannelExceptionHandler.getInstance());
         }
       });
     }
@@ -79,7 +81,7 @@
         protected void initChannel(Channel channel) throws Exception {
           channel.pipeline().addLast(channelRegistrar);
           NettyUtil.initHttpHandlers(channel.pipeline());
-          channel.pipeline().addLast(handler);
+          channel.pipeline().addLast(handler, ChannelExceptionHandler.getInstance());
         }
       });
     }
@@ -106,6 +108,23 @@
     InetAddress loopbackAddress = NetUtils.getLoopbackAddress();
     for (int i = 0; i < portsCount; i++) {
       int port = firstPort + i;
+
+      // we check if any port free too
+      if (!SystemInfo.isLinux && (!SystemInfo.isWindows || SystemInfo.isWinVistaOrNewer)) {
+        try {
+          ServerSocket serverSocket = new ServerSocket();
+          try {
+            serverSocket.bind(new InetSocketAddress(port), 1);
+          }
+          finally {
+            serverSocket.close();
+          }
+        }
+        catch (IOException ignored) {
+          continue;
+        }
+      }
+
       ChannelFuture future = bootstrap.bind(loopbackAddress, port).awaitUninterruptibly();
       if (future.isSuccess()) {
         channelRegistrar.add(future.channel());
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
index 93def2e..54ba57f 100644
--- a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandler;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 
 import java.net.ConnectException;
@@ -26,6 +27,15 @@
 public final class ChannelExceptionHandler extends ChannelInboundHandlerAdapter {
   private static final Logger LOG = Logger.getInstance(ChannelExceptionHandler.class);
 
+  private static final ChannelInboundHandler INSTANCE = new ChannelExceptionHandler();
+
+  private ChannelExceptionHandler() {
+  }
+
+  public static ChannelInboundHandler getInstance() {
+    return INSTANCE;
+  }
+
   @Override
   public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
     // don't report about errors while connecting
diff --git a/platform/platform-impl/src/org/jetbrains/io/Decoder.java b/platform/platform-impl/src/org/jetbrains/io/Decoder.java
index 30052bd..c4ad246 100644
--- a/platform/platform-impl/src/org/jetbrains/io/Decoder.java
+++ b/platform/platform-impl/src/org/jetbrains/io/Decoder.java
@@ -21,7 +21,7 @@
 import io.netty.channel.SimpleChannelInboundHandler;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class Decoder<I> extends SimpleChannelInboundHandler<I> {
+public abstract class Decoder extends SimpleChannelInboundHandler<ByteBuf> {
   protected ByteBuf cumulation;
 
   protected Decoder() {
diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
index e7809ac..305565a 100644
--- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
@@ -29,7 +29,6 @@
 import org.apache.sanselan.ImageFormat;
 import org.apache.sanselan.ImageWriteException;
 import org.apache.sanselan.Sanselan;
-import org.jetbrains.ide.BuiltInServerManager;
 import org.jetbrains.ide.HttpRequestHandler;
 
 import javax.swing.*;
@@ -52,7 +51,7 @@
       prevHandlerAttribute.set(null);
     }
 
-    for (HttpRequestHandler handler : BuiltInServerManager.EP_NAME.getExtensions()) {
+    for (HttpRequestHandler handler : HttpRequestHandler.EP_NAME.getExtensions()) {
       try {
         if (handler.isSupported(request) && handler.process(urlDecoder, request, context)) {
           prevHandlerAttribute.set(handler);
diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
index 86ae505..86dce36 100644
--- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
+++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
@@ -20,8 +20,10 @@
 import io.netty.bootstrap.Bootstrap;
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.oio.OioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
 import io.netty.channel.socket.oio.OioSocketChannel;
 import io.netty.handler.codec.http.HttpObjectAggregator;
 import io.netty.handler.codec.http.HttpRequestDecoder;
@@ -111,6 +113,12 @@
     return bootstrap;
   }
 
+  public static Bootstrap nioClientBootstrap() {
+    Bootstrap bootstrap = new Bootstrap().group(new NioEventLoopGroup(1, PooledThreadExecutor.INSTANCE)).channel(NioSocketChannel.class);
+    bootstrap.option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true);
+    return bootstrap;
+  }
+
   public static void initHttpHandlers(ChannelPipeline pipeline) {
     pipeline.addLast(new HttpRequestDecoder(), new HttpObjectAggregator(1048576), new HttpResponseEncoder());
   }
diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
index 1169763..4a9b802 100644
--- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
@@ -25,15 +25,17 @@
 import io.netty.handler.ssl.SslHandler;
 import io.netty.handler.stream.ChunkedWriteHandler;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.ide.BinaryRequestHandler;
 
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import java.security.KeyStore;
 import java.security.Security;
+import java.util.UUID;
 
 @ChannelHandler.Sharable
-final class PortUnificationServerHandler extends Decoder<ByteBuf> {
+class PortUnificationServerHandler extends Decoder {
   private static final AtomicNotNullLazyValue<SSLContext> SSL_SERVER_CONTEXT = new AtomicNotNullLazyValue<SSLContext>() {
     @NotNull
     @Override
@@ -86,22 +88,22 @@
     }
   }
 
-  private void decode(ChannelHandlerContext context, ByteBuf buffer) throws Exception {
+  protected void decode(ChannelHandlerContext context, ByteBuf buffer) throws Exception {
     ChannelPipeline pipeline = context.pipeline();
     if (detectSsl && SslHandler.isEncrypted(buffer)) {
       SSLEngine engine = SSL_SERVER_CONTEXT.getValue().createSSLEngine();
       engine.setUseClientMode(false);
-      pipeline.addLast(new SslHandler(engine), new ChunkedWriteHandler());
-      pipeline.addLast(new PortUnificationServerHandler(delegatingHttpRequestHandler, false, detectGzip));
+      pipeline.addLast(new SslHandler(engine), new ChunkedWriteHandler(),
+                       new PortUnificationServerHandler(delegatingHttpRequestHandler, false, detectGzip));
     }
     else {
       int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
       int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
       if (detectGzip && magic1 == 31 && magic2 == 139) {
-        pipeline.addLast(new JZlibEncoder(ZlibWrapper.GZIP), new JdkZlibDecoder(ZlibWrapper.GZIP));
-        pipeline.addLast(new PortUnificationServerHandler(delegatingHttpRequestHandler, detectSsl, false));
+        pipeline.addLast(new JZlibEncoder(ZlibWrapper.GZIP), new JdkZlibDecoder(ZlibWrapper.GZIP),
+                         new PortUnificationServerHandler(delegatingHttpRequestHandler, detectSsl, false));
       }
-      else {
+      else if (isHttp(magic1, magic2)) {
         NettyUtil.initHttpHandlers(pipeline);
         pipeline.addLast(delegatingHttpRequestHandler);
         if (BuiltInServer.LOG.isDebugEnabled()) {
@@ -116,14 +118,66 @@
           });
         }
       }
+      else if (magic1 == 'C' && magic2 == 'H') {
+        buffer.skipBytes(2);
+        pipeline.addLast(new CustomHandlerDelegator());
+      }
+      else {
+        BuiltInServer.LOG.warn("unknown request, first two bytes " + magic1 + " " + magic2);
+        context.close();
+      }
     }
     // must be after new channels handlers addition (netty bug?)
+    ensureThatExceptionHandlerIsLast(pipeline);
     pipeline.remove(this);
     context.fireChannelRead(buffer);
   }
 
-  @Override
-  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
-    NettyUtil.log(cause, BuiltInServer.LOG);
+  private static void ensureThatExceptionHandlerIsLast(ChannelPipeline pipeline) {
+    ChannelInboundHandler exceptionHandler = ChannelExceptionHandler.getInstance();
+    if (pipeline.last() != exceptionHandler || pipeline.context(exceptionHandler) == null) {
+      return;
+    }
+
+    pipeline.remove(exceptionHandler);
+    pipeline.addLast(exceptionHandler);
+  }
+
+  private static boolean isHttp(int magic1, int magic2) {
+    return
+      magic1 == 'G' && magic2 == 'E' || // GET
+      magic1 == 'P' && magic2 == 'O' || // POST
+      magic1 == 'P' && magic2 == 'U' || // PUT
+      magic1 == 'H' && magic2 == 'E' || // HEAD
+      magic1 == 'O' && magic2 == 'P' || // OPTIONS
+      magic1 == 'P' && magic2 == 'A' || // PATCH
+      magic1 == 'D' && magic2 == 'E' || // DELETE
+      magic1 == 'T' && magic2 == 'R' || // TRACE
+      magic1 == 'C' && magic2 == 'O';   // CONNECT
+  }
+
+  private static class CustomHandlerDelegator extends Decoder {
+    private static final int UUID_LENGTH = 16;
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+      ByteBuf buffer = getBufferIfSufficient(message, UUID_LENGTH, context);
+      if (buffer == null) {
+        message.release();
+      }
+      else {
+        UUID uuid = new UUID(buffer.readLong(), buffer.readLong());
+        for (BinaryRequestHandler customHandler : BinaryRequestHandler.EP_NAME.getExtensions()) {
+          if (uuid.equals(customHandler.getId())) {
+            ChannelPipeline pipeline = context.pipeline();
+            pipeline.addLast(customHandler.getInboundHandler());
+            ensureThatExceptionHandlerIsLast(pipeline);
+            pipeline.remove(this);
+            context.fireChannelRead(buffer);
+            break;
+          }
+        }
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties
index dbfb892..e88bcf0 100644
--- a/platform/platform-resources-en/src/messages/IdeBundle.properties
+++ b/platform/platform-resources-en/src/messages/IdeBundle.properties
@@ -260,7 +260,7 @@
 message.personal.license=Personal License
 aboutbox.build.number=Build #{0}
 aboutbox.build.date=, built on {0}
-aboutbox.jdk=JRE : {0}
+aboutbox.jdk=JRE : {0} {1}
 aboutbox.vm=VM: {0} by {1}
 aboutbox.maintenance.due=Entitled for free updates and upgrades until {0,date,MMMM dd, yyyy}
 title.warning=Warning
diff --git a/platform/platform-resources-en/src/messages/VfsBundle.properties b/platform/platform-resources-en/src/messages/VfsBundle.properties
index 7e7bf75..9ea22a3 100644
--- a/platform/platform-resources-en/src/messages/VfsBundle.properties
+++ b/platform/platform-resources-en/src/messages/VfsBundle.properties
@@ -5,7 +5,7 @@
 file.write.error=Cannot write to file {0}.
 file.delete.root.error=Cannot delete root file {0}.
 jar.copy.progress=Copying {0}...
-jar.copy.error.message=Cannot copy {0} to {1}.\nReason: {2}.
+jar.copy.error.message=Cannot copy ''{0}'' to ''{1}''.\nReason: {2}.
 jar.copy.error.title=Error Copying File
 jar.modification.not.supported.error=Cannot modify jar or zip file {0}
 file.synchronize.progress=Synchronizing files...
diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
index 0d6e267..b9a857d 100644
--- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
@@ -780,6 +780,9 @@
 
     <extensionPoint name="moduleRendererFactory" interface="com.intellij.ide.util.ModuleRendererFactory"/>
 
+    <extensionPoint name="projectStructure.sourceRootEditHandler"
+                    interface="com.intellij.openapi.roots.ui.configuration.ModuleSourceRootEditHandler"/>
+
     <extensionPoint name="toolsProvider" interface="com.intellij.tools.ToolsProvider"/>
 
     <extensionPoint name="defaultHighlightingSettingProvider"
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index 59550dc..d2710f4 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -848,6 +848,9 @@
     <applicationService serviceInterface="com.intellij.ide.util.treeView.TreeAnchorizer"
                         serviceImplementation="com.intellij.ide.projectView.impl.nodes.PsiTreeAnchorizer"/>
 
+    <projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaModuleSourceRootEditHandler"/>
+    <projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaTestSourceRootEditHandler"/>
+
     <elementPreviewProvider implementation="com.intellij.codeInsight.preview.ElementPreviewHintProvider"/>
   </extensions>
 </idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
index bd4ff01..f8f0c6c 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
@@ -190,6 +190,7 @@
     <extensionPoint name="pathMacroExpandableProtocol" beanClass="com.intellij.application.options.PathMacroExpandableProtocolBean"/>
 
     <extensionPoint name="httpRequestHandler" interface="org.jetbrains.ide.HttpRequestHandler"/>
+    <extensionPoint name="binaryRequestHandler" interface="org.jetbrains.ide.BinaryRequestHandler"/>
     <extensionPoint name="customPortServerManager" interface="org.jetbrains.ide.CustomPortServerManager"/>
 
     <extensionPoint name="colorPickerListenerFactory" interface="com.intellij.ui.ColorPickerListenerFactory"/>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index 8c05bb9..8e19ac9 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -3,6 +3,7 @@
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
     <appStarter implementation="com.intellij.openapi.diff.DiffApplication"/>
     <appStarter implementation="com.intellij.openapi.diff.MergeApplication"/>
+    <appStarter implementation="com.intellij.ui.win.RecentProjectApplication"/>
     <appStarter implementation="com.intellij.help.impl.KeymapGenerator"/>
 
     <applicationService serviceInterface="com.intellij.ide.util.PropertiesComponent"
@@ -307,5 +308,7 @@
                      implementationClass="com.intellij.codeStyle.InconsistentLineSeparatorsInspection"/>
     <search.topHitProvider implementation="com.intellij.platform.DefaultPlatformTopHitProvider"/>
     <search.topHitProvider implementation="com.intellij.ide.ui.UISimpleSettingsProvider"/>
+    <projectService serviceImplementation="com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector"/>
+    <postStartupActivity implementation="com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser"/>
   </extensions>
 </idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/XmlActions.xml b/platform/platform-resources/src/META-INF/XmlActions.xml
index 6d334dd..c727bd7 100644
--- a/platform/platform-resources/src/META-INF/XmlActions.xml
+++ b/platform/platform-resources/src/META-INF/XmlActions.xml
@@ -71,5 +71,13 @@
             description="Generate a new XML tag according to schema information">
       <add-to-group group-id="GenerateGroup" anchor="first"/>
     </action>
+
+    <action id="OpenInBrowser" class="com.intellij.ide.browsers.OpenFileInDefaultBrowserAction"
+            text="Open in _Browser" description="Open a selected file in browser"
+            icon="AllIcons.Nodes.PpWeb">
+      <add-to-group group-id="ViewMenu" anchor="after" relative-to-action="ViewSource"/>
+      <add-to-group group-id="EditorPopupMenu" anchor="after" relative-to-action="CutCopyPasteGroup"/>
+      <add-to-group group-id="ProjectViewPopupMenu" anchor="after" relative-to-action="EditSource"/>
+    </action>
   </actions>
 </component>
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index 769a2c2..ca2ddbc 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -20,8 +20,8 @@
                     interface="com.intellij.xml.XmlExtension"/>
     <extensionPoint name="xml.namespaceHelper"
                     interface="com.intellij.xml.XmlNamespaceHelper"/>
-    <extensionPoint name="xml.tagNameProvider"
-                    interface="com.intellij.xml.XmlTagNameProvider"/>
+    <extensionPoint name="xml.completionExtension"
+                    interface="com.intellij.xml.XmlCompletionExtension"/>
     <extensionPoint name="xml.fileNSInfoProvider"
                     interface="com.intellij.psi.xml.XmlFileNSInfoProvider"/>
     <extensionPoint name="xml.attributeDescriptorsProvider"
@@ -493,7 +493,7 @@
     <xml.psiPolicy language="HTML" implementationClass="com.intellij.psi.impl.source.xml.behavior.EncodeEachSymbolPolicy"/>
     <xml.psiPolicy language="XHTML" implementationClass="com.intellij.psi.impl.source.xml.behavior.EncodeEachSymbolPolicy"/>
 
-    <xml.tagNameProvider implementation="com.intellij.psi.impl.source.xml.DefaultXmlTagNameProvider"/>
+    <xml.completionExtension implementation="com.intellij.psi.impl.source.xml.DefaultXmlCompletionExtension"/>
     <xml.fileNSInfoProvider implementation="com.intellij.xml.util.HtmlFileNSInfoProvider"/>
 
     <codeInsight.unresolvedReferenceQuickFixProvider
diff --git a/platform/platform-tests/platform-tests.iml b/platform/platform-tests/platform-tests.iml
index 74ebc8f..a2fe526 100644
--- a/platform/platform-tests/platform-tests.iml
+++ b/platform/platform-tests/platform-tests.iml
@@ -21,6 +21,7 @@
     <orderEntry type="module" module-name="xdebugger-impl" scope="RUNTIME" />
     <orderEntry type="module" module-name="xml-openapi" />
     <orderEntry type="library" name="Groovy" level="project" />
+    <orderEntry type="library" name="Netty" level="project" />
   </component>
 </module>
 
diff --git a/platform/platform-tests/testSrc/META-INF/plugin.xml b/platform/platform-tests/testSrc/META-INF/plugin.xml
new file mode 100644
index 0000000..905cbe6
--- /dev/null
+++ b/platform/platform-tests/testSrc/META-INF/plugin.xml
@@ -0,0 +1,8 @@
+<idea-plugin>
+  <name>Platform Tests</name>
+  <id>org.jetbrains.platform.tests</id>
+
+  <extensions defaultExtensionNs="com.intellij">
+    <binaryRequestHandler implementation="com.intellij.ide.BinaryRequestHandlerTest$MyBinaryRequestHandler"/>
+  </extensions>
+</idea-plugin>
\ No newline at end of file
diff --git a/platform/platform-tests/testSrc/com/intellij/execution/filters/RegexpFilterTest.java b/platform/platform-tests/testSrc/com/intellij/execution/filters/RegexpFilterTest.java
index 02568e7..84b77f17 100644
--- a/platform/platform-tests/testSrc/com/intellij/execution/filters/RegexpFilterTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/execution/filters/RegexpFilterTest.java
@@ -1,14 +1,33 @@
+/*
+ * 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.intellij.execution.filters;
 
 import com.intellij.openapi.project.Project;
-import junit.framework.TestCase;
+import org.junit.Test;
 
-public class RegexpFilterTest extends TestCase {
+import static org.junit.Assert.assertEquals;
+
+public class RegexpFilterTest {
   private static final String FILE = RegexpFilter.FILE_PATH_MACROS;
   private static final String LINE = RegexpFilter.LINE_MACROS;
   private static final String COLUMN = RegexpFilter.COLUMN_MACROS;
+
   private RegexpFilter myFilter;
 
+  @Test
   public void test() {
     createFilter(FILE);
     String line = "C:\\Work\\SampleProjects\\makeOutput.cmd";
@@ -19,7 +38,8 @@
     info.checkInfo(line, 0, 0);
   }
 
-  public void testFileLineComlumn() {
+  @Test
+  public void testFileLineColumn() {
     createFilter(FILE + "x" + LINE + "y" + COLUMN);
     String fileName = "C:\\file";
     Filter.Result result = applyFilter(fileName + "x12y34");
@@ -29,6 +49,7 @@
     info.checkInfo(fileName, 11, 33);
   }
 
+  @Test
   public void testFileLineColumnWithTail() {
     createFilter(FILE + ":" + LINE + ":" + COLUMN + ".*");
     String fileName = "C:/file";
@@ -39,15 +60,17 @@
     info.checkInfo(fileName, 11, 33);
   }
 
+  @Test
   public void test4814() {
     createFilter(FILE + ":" + LINE + ":" + COLUMN + ".*");
-    String fileName = "C:/work/dev/C3C/V9_9_9_9/src/java/strata/pswitch/ss5e/dataSync/BFGParser.java";
+    String fileName = "C:/work/dev/C3C/V9_9_9_9/src/java/strata/p_switch/ss5e/dataSync/BFGParser.java";
     String line = fileName + ":544:13:544:13:";
     Filter.Result result = applyFilter(line);
     HLInfo info = (HLInfo) result.hyperlinkInfo;
     info.checkInfo(fileName, 543, 12);
   }
 
+  @Test
   public void testWithSpaces() {
     createFilter("$FILE_PATH$\\s+\\($LINE$\\:$COLUMN$\\)");
     String line = "C:\\d ir\\file.ext (1:2)message";
@@ -69,7 +92,9 @@
     };
   }
 
-  public HyperlinkInfo createOpenFile(String fileName, int line, int comumn) {return new HLInfo(fileName, line, comumn); }
+  private static HyperlinkInfo createOpenFile(String fileName, int line, int column) {
+    return new HLInfo(fileName, line, column);
+  }
 
   private static class HLInfo implements HyperlinkInfo {
     public String myFileName;
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java
new file mode 100644
index 0000000..5f2f557
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java
@@ -0,0 +1,134 @@
+package com.intellij.ide;
+
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.testFramework.LightPlatformTestCase;
+import com.intellij.util.Consumer;
+import com.intellij.util.net.NetUtils;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.util.CharsetUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.ide.BinaryRequestHandler;
+import org.jetbrains.ide.BuiltInServerManager;
+import org.jetbrains.io.ChannelExceptionHandler;
+import org.jetbrains.io.Decoder;
+import org.jetbrains.io.NettyUtil;
+
+import java.util.UUID;
+
+public class BinaryRequestHandlerTest extends LightPlatformTestCase {
+  public void test() throws InterruptedException {
+    final String text = "Hello!";
+    final AsyncResult<String> result = new AsyncResult<String>();
+
+    Bootstrap bootstrap = NettyUtil.oioClientBootstrap().handler(new ChannelInitializer() {
+      @Override
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(new Decoder() {
+          @Override
+          protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+            int requiredLength = 4 + text.length();
+            ByteBuf buffer = getBufferIfSufficient(message, requiredLength, context);
+            if (buffer == null) {
+              message.release();
+            }
+            else {
+              String response = buffer.toString(buffer.readerIndex(), requiredLength, CharsetUtil.UTF_8);
+              buffer.skipBytes(requiredLength);
+              buffer.release();
+              result.setDone(response);
+            }
+          }
+        }, ChannelExceptionHandler.getInstance());
+      }
+    });
+
+    int port = BuiltInServerManager.getInstance().waitForStart().getPort();
+    Channel channel = bootstrap.connect(NetUtils.getLoopbackAddress(), port).syncUninterruptibly().channel();
+    ByteBuf buffer = channel.alloc().buffer();
+    buffer.writeByte('C');
+    buffer.writeByte('H');
+    buffer.writeLong(MyBinaryRequestHandler.ID.getMostSignificantBits());
+    buffer.writeLong(MyBinaryRequestHandler.ID.getLeastSignificantBits());
+
+    ByteBuf message = Unpooled.copiedBuffer(text, CharsetUtil.UTF_8);
+    buffer.writeShort(message.readableBytes());
+
+    channel.write(buffer);
+    channel.writeAndFlush(message).syncUninterruptibly();
+
+    try {
+      result.doWhenRejected(new Consumer<String>() {
+        @Override
+        public void consume(String error) {
+          fail(error);
+        }
+      });
+
+      assertEquals("got-" + text, result.getResultSync(5000));
+    }
+    finally {
+      channel.close();
+    }
+  }
+
+  static class MyBinaryRequestHandler extends BinaryRequestHandler {
+    private static final UUID ID = UUID.fromString("E5068DD6-1DB7-437C-A3FC-3CA53B6E1AC9");
+
+    @NotNull
+    @Override
+    public UUID getId() {
+      return ID;
+    }
+
+    @Override
+    public ChannelInboundHandler getInboundHandler() {
+      return new MyDecoder();
+    }
+
+    private static class MyDecoder extends Decoder {
+      private State state = State.HEADER;
+      private int contentLength = -1;
+
+      private enum State {
+        HEADER, CONTENT
+      }
+
+      @Override
+      protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+        while (true) {
+          switch (state) {
+            case HEADER: {
+              ByteBuf buffer = getBufferIfSufficient(message, 2, context);
+              if (buffer == null) {
+                message.release();
+                return;
+              }
+
+              contentLength = buffer.readUnsignedShort();
+              state = State.CONTENT;
+            }
+
+            case CONTENT: {
+              ByteBuf buffer = getBufferIfSufficient(message, contentLength, context);
+              if (buffer == null) {
+                message.release();
+                return;
+              }
+
+              String messageText = buffer.toString(buffer.readerIndex(), contentLength, CharsetUtil.UTF_8);
+              buffer.skipBytes(contentLength);
+              state = State.HEADER;
+              context.writeAndFlush(Unpooled.copiedBuffer("got-" + messageText, CharsetUtil.UTF_8));
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java
index 7082647..5a0ee9d 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -109,7 +109,7 @@
    * @param module the module for which the list of dependent modules is requested.
    * @return list of <i>modules that depend on</i> given module.
    *
-   * @see ModuleUtil#getAllDependentModules(Module)
+   * @see ModuleUtilCore#getAllDependentModules(Module)
    */
   @NotNull public abstract List<Module> getModuleDependentModules(@NotNull Module module);
 
diff --git a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/ProjectJdkTable.java b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/ProjectJdkTable.java
index 0c97fd6..8fee9a1 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/ProjectJdkTable.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/ProjectJdkTable.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.util.messages.Topic;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.EventListener;
@@ -88,7 +89,7 @@
 
   public abstract SdkTypeId getDefaultSdkType();
 
-  public abstract SdkTypeId getSdkTypeByName(String name);
+  public abstract SdkTypeId getSdkTypeByName(@NotNull String name);
 
   public abstract Sdk createSdk(final String name, final SdkTypeId sdkType);
 
diff --git a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkTypeId.java b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkTypeId.java
index b4ff275..bc4fd56 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkTypeId.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkTypeId.java
@@ -16,19 +16,21 @@
 package com.intellij.openapi.projectRoots;
 
 import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * @author yole
  */
 public interface SdkTypeId {
+  @NotNull
   String getName();
 
   @Nullable
-  String getVersionString(Sdk sdk);
+  String getVersionString(@NotNull Sdk sdk);
 
-  void saveAdditionalData(SdkAdditionalData additionalData, Element additional);
+  void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional);
 
   @Nullable
-  SdkAdditionalData loadAdditionalData(Sdk currentSdk, Element additional);
+  SdkAdditionalData loadAdditionalData(@NotNull Sdk currentSdk, Element additional);
 }
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/ContentEntry.java b/platform/projectModel-api/src/com/intellij/openapi/roots/ContentEntry.java
index d2e22de..c44cd90 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ContentEntry.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ContentEntry.java
@@ -18,6 +18,8 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 /**
  * Represents a module content root.
@@ -95,6 +97,10 @@
    */
   SourceFolder addSourceFolder(@NotNull VirtualFile file, boolean isTestSource, @NotNull String packagePrefix);
 
+  @NotNull
+  <P extends JpsElement>
+  SourceFolder addSourceFolder(@NotNull VirtualFile file, @NotNull JpsModuleSourceRootType<P> type, @NotNull P properties);
+
   /**
    * Adds a source or test source root under the content root.
    *
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
index 83fd86d..6dd2db4 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.roots;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 /**
  * Represents a source or test source root under the content root of a module.
@@ -45,4 +46,7 @@
    * @param packagePrefix the package prefix, or an empty string if the root has no package prefix.
    */
   void setPackagePrefix(@NotNull String packagePrefix);
+
+  @NotNull
+  JpsModuleSourceRootType<?> getRootType();
 }
diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreProjectJdkTable.java b/platform/projectModel-impl/src/com/intellij/core/CoreProjectJdkTable.java
index ef055c0..7a7e885 100644
--- a/platform/projectModel-impl/src/com/intellij/core/CoreProjectJdkTable.java
+++ b/platform/projectModel-impl/src/com/intellij/core/CoreProjectJdkTable.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.projectRoots.SdkTypeId;
 import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -99,7 +100,7 @@
   }
 
   @Override
-  public SdkTypeId getSdkTypeByName(String name) {
+  public SdkTypeId getSdkTypeByName(@NotNull String name) {
     return CoreSdkType.INSTANCE;
   }
 
diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreSdkType.java b/platform/projectModel-impl/src/com/intellij/core/CoreSdkType.java
index 3beedf6..63d86aa 100644
--- a/platform/projectModel-impl/src/com/intellij/core/CoreSdkType.java
+++ b/platform/projectModel-impl/src/com/intellij/core/CoreSdkType.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.projectRoots.SdkAdditionalData;
 import com.intellij.openapi.projectRoots.SdkTypeId;
 import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author yole
@@ -29,22 +30,23 @@
 
   public static CoreSdkType INSTANCE = new CoreSdkType();
 
+  @NotNull
   @Override
   public String getName() {
     return "";
   }
 
   @Override
-  public String getVersionString(Sdk sdk) {
+  public String getVersionString(@NotNull Sdk sdk) {
     return "";
   }
 
   @Override
-  public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
+  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
   }
 
   @Override
-  public SdkAdditionalData loadAdditionalData(Sdk currentSdk, Element additional) {
+  public SdkAdditionalData loadAdditionalData(@NotNull Sdk currentSdk, Element additional) {
     return null;
   }
 }
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 32fba97..752036e 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
@@ -105,4 +105,16 @@
     final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex();
     return !projectFileIndex.isInSource(file) && !projectFileIndex.isInLibraryClasses(file);
   }
+
+  @Nullable
+  public static SourceFolder findSourceFolder(@NotNull Module module, @NotNull VirtualFile root) {
+    for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
+      for (SourceFolder folder : entry.getSourceFolders()) {
+        if (root.equals(folder.getFile())) {
+          return folder;
+        }
+      }
+    }
+    return null;
+  }
 }
\ No newline at end of file
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java
index 984b9f1..64d379a 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java
@@ -19,7 +19,10 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ContentFolder;
+import com.intellij.openapi.roots.ExcludeFolder;
+import com.intellij.openapi.roots.SourceFolder;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.WriteExternalException;
@@ -33,6 +36,12 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer;
 
 import java.util.*;
@@ -156,20 +165,30 @@
 
   @Override
   public SourceFolder addSourceFolder(@NotNull VirtualFile file, boolean isTestSource) {
-    assertCanAddFolder(file);
-    return addSourceFolder(new SourceFolderImpl(file, isTestSource, this));
+    return addSourceFolder(file, isTestSource, SourceFolderImpl.DEFAULT_PACKAGE_PREFIX);
   }
 
   @Override
   public SourceFolder addSourceFolder(@NotNull VirtualFile file, boolean isTestSource, @NotNull String packagePrefix) {
+    JavaSourceRootType type = isTestSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+    JpsSimpleElement<JavaSourceRootProperties> properties = JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties(""));
+    return addSourceFolder(file, type, properties);
+  }
+
+  @Override
+  @NotNull
+  public <P extends JpsElement> SourceFolder addSourceFolder(@NotNull VirtualFile file, @NotNull JpsModuleSourceRootType<P> type,
+                                                             @NotNull P properties) {
     assertCanAddFolder(file);
-    return addSourceFolder(new SourceFolderImpl(file, isTestSource, packagePrefix, this));
+    return addSourceFolder(new SourceFolderImpl(file, JpsElementFactory.getInstance().createModuleSourceRoot(file.getUrl(), type, properties), this));
   }
 
   @Override
   public SourceFolder addSourceFolder(@NotNull String url, boolean isTestSource) {
     assertFolderUnderMe(url);
-    return addSourceFolder(new SourceFolderImpl(url, isTestSource, this));
+    JavaSourceRootType type = isTestSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+    JpsSimpleElement<JavaSourceRootProperties> properties = JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties(""));
+    return addSourceFolder(new SourceFolderImpl(JpsElementFactory.getInstance().createModuleSourceRoot(url, type, properties), this));
   }
 
   private SourceFolder addSourceFolder(SourceFolderImpl f) {
@@ -293,9 +312,7 @@
     element.setAttribute(URL_ATTRIBUTE, myRoot.getUrl());
     for (final SourceFolder sourceFolder : mySourceFolders) {
       if (sourceFolder instanceof SourceFolderImpl) {
-        final Element subElement = new Element(SourceFolderImpl.ELEMENT_NAME);
-        ((SourceFolderImpl)sourceFolder).writeExternal(subElement);
-        element.addContent(subElement);
+        JpsModuleRootModelSerializer.saveSourceRoot(element, sourceFolder.getUrl(), ((SourceFolderImpl)sourceFolder).getJpsElement().asTyped());
       }
     }
 
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
index 71d8679..9c0f76f 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
@@ -16,7 +16,6 @@
 
 package com.intellij.openapi.roots.impl;
 
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.roots.ContentEntry;
 import com.intellij.openapi.roots.ContentFolder;
 import com.intellij.openapi.roots.SourceFolder;
@@ -25,78 +24,85 @@
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
 import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer;
 
 /**
  *  @author dsl
  */
 public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFolder, ClonableContentFolder {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.SimpleSourceFolderImpl");
-  private final boolean myIsTestSource;
+  private JpsModuleSourceRoot myJpsElement;
   @NonNls public static final String ELEMENT_NAME = JpsModuleRootModelSerializer.SOURCE_FOLDER_TAG;
   @NonNls public static final String TEST_SOURCE_ATTR = JpsModuleRootModelSerializer.IS_TEST_SOURCE_ATTRIBUTE;
-  private String myPackagePrefix;
   static final String DEFAULT_PACKAGE_PREFIX = "";
 
-  SourceFolderImpl(@NotNull VirtualFile file, boolean isTestSource, @NotNull ContentEntryImpl contentEntry) {
-    this(file, isTestSource, DEFAULT_PACKAGE_PREFIX, contentEntry);
-  }
-
-  SourceFolderImpl(@NotNull VirtualFile file, boolean isTestSource, @NotNull String packagePrefix, @NotNull ContentEntryImpl contentEntry) {
+  SourceFolderImpl(@NotNull VirtualFile file, @NotNull JpsModuleSourceRoot jpsElement, @NotNull ContentEntryImpl contentEntry) {
     super(file, contentEntry);
-    myIsTestSource = isTestSource;
-    myPackagePrefix = packagePrefix;
+    myJpsElement = jpsElement;
   }
 
-  public SourceFolderImpl(@NotNull String url, boolean isTestSource, @NotNull ContentEntryImpl contentEntry) {
-    super(url, contentEntry);
-    myIsTestSource = isTestSource;
-    myPackagePrefix = DEFAULT_PACKAGE_PREFIX;
+  public SourceFolderImpl(@NotNull JpsModuleSourceRoot jpsElement, @NotNull ContentEntryImpl contentEntry) {
+    super(jpsElement.getUrl(), contentEntry);
+    myJpsElement = jpsElement;
   }
 
   SourceFolderImpl(Element element, ContentEntryImpl contentEntry) throws InvalidDataException {
     super(element, contentEntry);
-    LOG.assertTrue(element.getName().equals(ELEMENT_NAME));
-    final String testSource = element.getAttributeValue(TEST_SOURCE_ATTR);
-    if (testSource == null) throw new InvalidDataException();
-    myIsTestSource = Boolean.valueOf(testSource).booleanValue();
-    final String packagePrefix = element.getAttributeValue(JpsModuleRootModelSerializer.PACKAGE_PREFIX_ATTRIBUTE);
-    if (packagePrefix != null) {
-      myPackagePrefix = packagePrefix;
-    }
-    else {
-      myPackagePrefix = DEFAULT_PACKAGE_PREFIX;
-    }
+    myJpsElement = JpsModuleRootModelSerializer.loadSourceRoot(element);
   }
 
   private SourceFolderImpl(SourceFolderImpl that, ContentEntryImpl contentEntry) {
     super(that, contentEntry);
-    myIsTestSource = that.myIsTestSource;
-    myPackagePrefix = that.myPackagePrefix;
+    myJpsElement = createCopy(that, that.myJpsElement.asTyped());
+  }
+
+  private static <P extends JpsElement> JpsModuleSourceRoot createCopy(SourceFolderImpl that, final JpsTypedModuleSourceRoot<P> jpsElement) {
+    return JpsElementFactory.getInstance().createModuleSourceRoot(that.getUrl(), jpsElement.getRootType(), (P)jpsElement.getProperties().getBulkModificationSupport().createCopy());
   }
 
   @Override
   public boolean isTestSource() {
-    return myIsTestSource;
+    return getRootType().equals(JavaSourceRootType.TEST_SOURCE);
   }
 
   @NotNull
   @Override
   public String getPackagePrefix() {
-    return myPackagePrefix;
+    JpsSimpleElement<JavaSourceRootProperties> properties = getJavaProperties();
+    return properties != null ? properties.getData().getPackagePrefix() : DEFAULT_PACKAGE_PREFIX;
+  }
+
+  @Nullable
+  private JpsSimpleElement<JavaSourceRootProperties> getJavaProperties() {
+    if (myJpsElement.getRootType() == JavaSourceRootType.SOURCE) {
+      return myJpsElement.getProperties(JavaSourceRootType.SOURCE);
+    }
+    if (myJpsElement.getRootType() == JavaSourceRootType.TEST_SOURCE) {
+      return myJpsElement.getProperties(JavaSourceRootType.TEST_SOURCE);
+    }
+    return null;
   }
 
   @Override
   public void setPackagePrefix(@NotNull String packagePrefix) {
-    myPackagePrefix = packagePrefix;
+    JpsSimpleElement<JavaSourceRootProperties> properties = getJavaProperties();
+    if (properties != null) {
+      properties.setData(new JavaSourceRootProperties(packagePrefix));
+    }
   }
 
-  void writeExternal(Element element) {
-    writeFolder(element, ELEMENT_NAME);
-    element.setAttribute(TEST_SOURCE_ATTR, Boolean.toString(myIsTestSource));
-    if (!DEFAULT_PACKAGE_PREFIX.equals(myPackagePrefix)) {
-      element.setAttribute(JpsModuleRootModelSerializer.PACKAGE_PREFIX_ATTRIBUTE, myPackagePrefix);
-    }
+  @NotNull
+  @Override
+  public JpsModuleSourceRootType<?> getRootType() {
+    return myJpsElement.getRootType();
   }
 
   @Override
@@ -106,6 +112,10 @@
     return new SourceFolderImpl(this, (ContentEntryImpl)contentEntry);
   }
 
+  public JpsModuleSourceRoot getJpsElement() {
+    return myJpsElement;
+  }
+
   @Override
   public int compareTo(ContentFolderBaseImpl folder) {
     if (!(folder instanceof SourceFolderImpl)) return -1;
@@ -113,8 +123,8 @@
     int i = super.compareTo(folder);
     if (i!= 0) return i;
 
-    i = myPackagePrefix.compareTo(((SourceFolderImpl)folder).myPackagePrefix);
+    i = getPackagePrefix().compareTo(((SourceFolderImpl)folder).getPackagePrefix());
     if (i!= 0) return i;
-    return Boolean.valueOf(myIsTestSource).compareTo(((SourceFolderImpl)folder).myIsTestSource);
+    return Boolean.valueOf(isTestSource()).compareTo(((SourceFolderImpl)folder).isTestSource());
   }
 }
diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsContentEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsContentEntry.java
index b5b79c9..f2d76a3 100644
--- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsContentEntry.java
+++ b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsContentEntry.java
@@ -31,11 +31,14 @@
 import com.intellij.project.model.impl.module.JpsRootModel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
 import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
 import org.jetbrains.jps.model.java.JavaSourceRootProperties;
 import org.jetbrains.jps.model.java.JavaSourceRootType;
 import org.jetbrains.jps.model.module.JpsModule;
 import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -141,10 +144,21 @@
     return addSourceFolder(file.getUrl(), isTestSource, packagePrefix);
   }
 
+  @NotNull
+  @Override
+  public <P extends JpsElement> SourceFolder addSourceFolder(@NotNull VirtualFile file,
+                                                             @NotNull JpsModuleSourceRootType<P> type,
+                                                             @NotNull P properties) {
+    final JpsModuleSourceRoot sourceRoot = myModule.addSourceRoot(file.getUrl(), type, properties);
+    final JpsSourceFolder sourceFolder = new JpsSourceFolder(sourceRoot, this);
+    mySourceFolders.add(sourceFolder);
+    return sourceFolder;
+  }
+
   private SourceFolder addSourceFolder(final String url, boolean isTestSource, String packagePrefix) {
     final JavaSourceRootType rootType = isTestSource ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
-    final JpsModuleSourceRoot sourceRoot = myModule.addSourceRoot(url, rootType, JpsElementFactory.getInstance()
-      .createSimpleElement(new JavaSourceRootProperties(packagePrefix)));
+    JpsSimpleElement<JavaSourceRootProperties> properties = JpsElementFactory.getInstance().createSimpleElement(new JavaSourceRootProperties(packagePrefix));
+    final JpsModuleSourceRoot sourceRoot = myModule.addSourceRoot(url, rootType, properties);
     final JpsSourceFolder sourceFolder = new JpsSourceFolder(sourceRoot, this);
     mySourceFolders.add(sourceFolder);
     return sourceFolder;
diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
index 3092c36..8bd6a93a38 100644
--- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
+++ b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
@@ -22,6 +22,7 @@
 import org.jetbrains.jps.model.java.JavaSourceRootProperties;
 import org.jetbrains.jps.model.java.JavaSourceRootType;
 import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
 
 /**
  * @author nik
@@ -68,4 +69,10 @@
       properties.setData(new JavaSourceRootProperties(packagePrefix));
     }
   }
+
+  @NotNull
+  @Override
+  public JpsModuleSourceRootType<?> getRootType() {
+    return mySourceRoot.getRootType();
+  }
 }
diff --git a/platform/projectModel-impl/src/messages/ProjectBundle.properties b/platform/projectModel-impl/src/messages/ProjectBundle.properties
index 370b8f0..a8eefc9 100644
--- a/platform/projectModel-impl/src/messages/ProjectBundle.properties
+++ b/platform/projectModel-impl/src/messages/ProjectBundle.properties
@@ -173,9 +173,8 @@
 module.toggle.excluded.action=Excluded
 module.toggle.excluded.action.description=Include/Exclude directory from module
 module.toggle.test.sources.action=Test Sources
-module.toggle.test.sources.action.description=Mark directory as a Test Sources root
 module.toggle.sources.action=Sources
-module.toggle.sources.action.description=Mark directory as a Sources root
+module.toggle.sources.action.description=Mark directory as a {0} root
 library.classes.node=Classes
 library.javadocs.node=JavaDocs
 library.empty.item=<empty library>
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
index 7d61aff..8eeed5e 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
@@ -55,6 +55,8 @@
   private boolean myDurationIsCached = false; // is used for separating unknown and unset duration
   private boolean myHasCriticalErrors = false;
   private boolean myHasErrorsCached = false;
+  private boolean myHasPassedTests = false;
+  private boolean myHasPassedTestsCached = false;
 
   @Nullable private String myStacktrace;
 
@@ -154,9 +156,37 @@
     return myState.wasTerminated();
   }
 
-  @Override
+  boolean hasPassedTests() {
+    if (myHasPassedTestsCached) {
+      return myHasPassedTests;
+    }
+    boolean hasPassedTests = calcPassedTests();
+    boolean canCache = !myState.isInProgress();
+    if (canCache) {
+      myHasPassedTests = hasPassedTests;
+      myHasPassedTestsCached = true;
+    }
+    return hasPassedTests;
+  }
+
+  private boolean calcPassedTests() {
+    if (isPassed()) {
+      return true;
+    }
+    for (SMTestProxy child : getChildren()) {
+      if (child.hasPassedTests()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+    @Override
   public boolean isIgnored() {
-    return myState.getMagnitude() == TestStateInfo.Magnitude.SKIPPED_INDEX;
+    if (hasPassedTests()) {
+      return false;
+    }
+    return myState.getMagnitude() == TestStateInfo.Magnitude.IGNORED_INDEX;
   }
 
   public boolean isPassed() {
diff --git a/platform/testFramework/src/com/intellij/testFramework/Timings.java b/platform/testFramework/src/com/intellij/testFramework/Timings.java
index f8ec372..cb94d32 100644
--- a/platform/testFramework/src/com/intellij/testFramework/Timings.java
+++ b/platform/testFramework/src/com/intellij/testFramework/Timings.java
@@ -122,7 +122,7 @@
     return
       " Timings: CPU=" + CPU_TIMING + " (" + (int)(CPU_TIMING*1.0/ ETALON_CPU_TIMING*100) + "% of the etalon)" +
       ", I/O=" + IO_TIMING + " (" + (int)(IO_TIMING*1.0/ ETALON_IO_TIMING*100) + "% of the etalon)" +
-      ", total=" + MACHINE_TIMING + " ("+(int)(MACHINE_TIMING*1.0/ ETALON_TIMING*100) + "% of the etalon)" +
-      ".";
+      ", total=" + MACHINE_TIMING + " ("+(int)(MACHINE_TIMING*1.0/ ETALON_TIMING*100) + "% of the etalon) " +
+      Runtime.getRuntime().availableProcessors() + " cores.";
   }
 }
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 7a181b8..3db5eb3 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
@@ -24,6 +24,7 @@
 import com.intellij.codeInsight.completion.CompletionType;
 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
+import com.intellij.codeInsight.daemon.GutterMark;
 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
 import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
@@ -67,7 +68,6 @@
 import com.intellij.openapi.editor.ex.util.EditorUtil;
 import com.intellij.openapi.editor.impl.DocumentImpl;
 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
-import com.intellij.codeInsight.daemon.GutterMark;
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.extensions.ExtensionPoint;
 import com.intellij.openapi.extensions.ExtensionPointName;
@@ -78,6 +78,7 @@
 import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.*;
@@ -1284,6 +1285,8 @@
           vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(getTempDirPath(), fileName));
         }
 
+        prepareVirtualFile(vFile);
+
         final Document document = FileDocumentManager.getInstance().getCachedDocument(vFile);
         if (document != null) {
           PsiDocumentManager.getInstance(getProject()).doPostponedOperationsAndUnblockDocument(document);
@@ -1374,6 +1377,9 @@
     return myFile;
   }
 
+  protected void prepareVirtualFile(@NotNull VirtualFile file) {
+  }
+
   private void setupEditorForInjectedLanguage() {
     Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile);
     if (editor instanceof EditorWindow) {
@@ -1495,9 +1501,19 @@
     ensureIndexesUpToDate(project);
     DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
     TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
-    List<HighlightInfo> infos = codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, toIgnore, canChangeDocument, null);
-    infos.addAll(DaemonCodeAnalyzerImpl.getFileLevelHighlights(project, file));
-    return infos;
+    ProcessCanceledException exception = null;
+    for (int i = 0; i < 100; i++) {
+      try {
+        List<HighlightInfo> infos = codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, toIgnore, canChangeDocument, null);
+        infos.addAll(DaemonCodeAnalyzerImpl.getFileLevelHighlights(project, file));
+        return infos;
+      }
+      catch (ProcessCanceledException e) {
+        exception = e;
+      }
+    }
+    // unable to highlight after 100 retries
+    throw exception;
   }
 
   public static void ensureIndexesUpToDate(Project project) {
diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
index 7107808..a4869d9 100644
--- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
+++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
@@ -11,6 +11,7 @@
 import com.intellij.util.continuation.ContinuationPause;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 import java.io.File;
 import java.util.*;
@@ -66,6 +67,7 @@
     afterUpdate.run();
   }
 
+  @TestOnly
   @Override
   public boolean ensureUpToDate(boolean canBeCanceled) {
     throw new UnsupportedOperationException();
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java b/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
index 57f60f7..dac5a49 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
@@ -53,7 +53,9 @@
       }
     }
 
-    throw new AssertionError(message);
+    AssertionError error = new AssertionError(message);
+    error.initCause(t);
+    throw error;
   }
 
   @Override
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/Logger.java b/platform/util/src/com/intellij/openapi/diagnostic/Logger.java
index 3edd6cd..1bee158 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/Logger.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/Logger.java
@@ -59,6 +59,17 @@
 
   public abstract void debug(@NonNls String message, @Nullable Throwable t);
 
+  public void debug(@NotNull String message, Object... details) {
+    if (isDebugEnabled()) {
+      StringBuilder sb = new StringBuilder();
+      sb.append(message);
+      for (Object detail : details) {
+        sb.append(String.valueOf(detail));
+      }
+      debug(sb.toString());
+    }
+  }
+
   public void info(@NotNull Throwable t) {
     info(t.getMessage(), t);
   }
@@ -102,19 +113,18 @@
 
   public abstract void error(@NonNls String message, @Nullable Throwable t, @NonNls @NotNull String... details);
 
-  public boolean assertTrue(boolean value, @NonNls Object message) {
+  public boolean assertTrue(boolean value, @Nullable @NonNls Object message) {
     if (!value) {
-      @NonNls StringBuilder resultMessage = new StringBuilder("Assertion failed");
-      if (message != null) resultMessage.append(": ").append(message);
-
-      error(resultMessage.toString(), new Throwable());
+      @NonNls String resultMessage = "Assertion failed";
+      if (message != null) resultMessage += ": " + message;
+      error(resultMessage, new Throwable());
     }
 
     return value;
   }
 
   public boolean assertTrue(boolean value) {
-    return value || assertTrue(value, "");
+    return value || assertTrue(false, null);
   }
 
   public abstract void setLevel(Level level);
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 4d89732..ce0ec3d 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
@@ -15,16 +15,12 @@
  */
 package com.intellij.openapi.util.io.win32;
 
-import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.util.lang.UrlClassLoader;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.Arrays;
-
 /**
  * Do not use this class directly.
  *
@@ -38,36 +34,10 @@
   private static final IdeaWin32 ourInstance;
 
   static {
-    boolean available = false;
-    if (SystemInfo.isWin2kOrNewer) {
-      String libName = SystemInfo.is64Bit ? "IdeaWin64.dll" : "IdeaWin32.dll";
-      try {
-        String path = PathManager.getBinPath() + "/" + libName;
-        if (!new File(path).exists()) {
-          path = PathManager.getHomePath() + "/community/bin/win/" + libName;
-          if (!new File(path).exists()) {
-            path = PathManager.getHomePath() + "/bin/win/" + libName;
-            if (!new File(path).exists()) {
-              path = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libName;
-              if (!new File(path).exists()) {
-                throw new FileNotFoundException("Native filesystem .dll is missing (path=" + PathManager.getBinPath() +
-                                                " content=" + Arrays.toString(new File(PathManager.getBinPath()).list()) + ")");
-              }
-            }
-          }
-        }
-        LOG.debug("Loading " + path);
-        System.load(path);
-        available = true;
-      }
-      catch (Throwable t) {
-        LOG.error("Failed to load native filesystem for Windows", t);
-      }
-    }
-
     IdeaWin32 instance = null;
-    if (available) {
+    if (SystemInfo.isWin2kOrNewer) {
       try {
+        UrlClassLoader.loadPlatformLibrary("IdeaWin32");
         instance = new IdeaWin32();
         LOG.info("Native filesystem for Windows is operational");
       }
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 afafbaf..225a51f 100644
--- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
@@ -43,6 +43,7 @@
 
   @NonNls private static final String VOWELS = "aeiouy";
   @NonNls private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *");
+  @NonNls private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *");
 
   public static final NotNullFunction<String, String> QUOTER = new NotNullFunction<String, String>() {
     @Override
@@ -535,10 +536,16 @@
   @NotNull
   public static String escapeStringCharacters(@NotNull String s) {
     StringBuilder buffer = new StringBuilder(s.length());
-    escapeStringCharacters(s.length(), s, buffer);
+    escapeStringCharacters(s.length(), s, "\"", buffer);
     return buffer.toString();
   }
 
+  @NotNull
+  public static String escapeCharCharacters(@NotNull String s) {
+    StringBuilder buffer = new StringBuilder(s.length());
+    escapeStringCharacters(s.length(), s, "\'", buffer);
+    return buffer.toString();
+  }
 
   @NotNull
   public static String unescapeStringCharacters(@NotNull String s) {
@@ -2132,7 +2139,19 @@
    */
   @NotNull
   public static String[] splitByLines(@NotNull String string) {
-    return EOL_SPLIT_PATTERN.split(string);
+    return splitByLines(string, true);
+  }
+
+  /**
+   * Splits string by lines. If several line separators are in a row corresponding empty lines
+   * are also added to result if {@code excludeEmptyStrings} is {@code false}.
+   *
+   * @param string String to split
+   * @return array of strings
+   */
+  @NotNull
+  public static String[] splitByLines(@NotNull String string, boolean excludeEmptyStrings) {
+    return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string);
   }
 
   @NotNull
diff --git a/platform/util/src/com/intellij/util/PatternUtil.java b/platform/util/src/com/intellij/util/PatternUtil.java
index 18f6245..7159a90 100644
--- a/platform/util/src/com/intellij/util/PatternUtil.java
+++ b/platform/util/src/com/intellij/util/PatternUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,8 @@
 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 org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 import java.util.Map;
@@ -25,9 +27,6 @@
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
-
 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>();
@@ -50,17 +49,17 @@
   }
 
   private static void escape2(char symbol) {
-    ourEscapeRules.put(""+symbol, "\\" + symbol);
+    ourEscapeRules.put(String.valueOf(symbol), "\\" + symbol);
   }
 
   public static String convertToRegex(String mask) {
-    List<String> strings = StringUtil.split(mask,"\\");
-    StringBuffer pattern = new StringBuffer();
+    List<String> strings = StringUtil.split(mask, "\\");
+    StringBuilder pattern = new StringBuilder();
     String separator = "";
 
-    for (String string:strings) {
+    for (String string : strings) {
       string = StringUtil.replace(string, ".", "\\.");
-      for (Map.Entry<String, String> e: ourEscapeRules.entrySet()) {
+      for (Map.Entry<String, String> e : ourEscapeRules.entrySet()) {
         string = StringUtil.replace(string, e.getKey(), e.getValue());
       }
       pattern.append(separator);
@@ -74,7 +73,8 @@
 //    String pattern = mask.replaceAll("\\.", "\\.").replaceAll("\\*", ".*").replaceAll("\\?", ".");
     try {
       return Pattern.compile(convertToRegex(mask));
-    } catch (PatternSyntaxException e) {
+    }
+    catch (PatternSyntaxException e) {
       LOG.error(mask, e);
       return Pattern.compile("");
     }
diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
index 6067814..9faef08 100644
--- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java
+++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
@@ -98,7 +98,7 @@
   private final byte[] myTypedIOBuffer;
   private volatile boolean isDirty = false;
   private final File myFile;
-  protected long mySize = -1;
+  protected volatile long mySize = -1;
   protected final int myPageSize;
   protected final boolean myValuesAreBufferAligned;
   @NonNls private static final String RW = "rw";
@@ -239,7 +239,7 @@
                                            "buffer.limit=" + buffer.limit() + ", " +
                                            "page=" + page + ", " +
                                            "file=" + myFile.getName() + ", "+
-                                           "file.length=" + mySize);
+                                           "file.length=" + length());
       }
       buffer.get(dst, o, page_len);
 
@@ -298,10 +298,10 @@
 
   public void resize(int newSize) throws IOException {
     int oldSize = (int)myFile.length();
-    if (oldSize == newSize) return;
+    if (oldSize == newSize && oldSize == length()) return;
 
     final long started = IOStatistics.DEBUG ? System.currentTimeMillis():0;
-    myStorageLockContext.myStorageLock.invalidateBuffer((int)(myStorageIndex | (mySize / myPageSize)));
+    myStorageLockContext.myStorageLock.invalidateBuffer(myStorageIndex | (oldSize / myPageSize));
     //unmapAll(); // we do not need it since all page alighned buffers can be reused
     final long unmapAllFinished = IOStatistics.DEBUG ? System.currentTimeMillis():0;
 
@@ -322,6 +322,7 @@
 
   private void resizeFile(int newSize) throws IOException {
     RandomAccessFile raf = new RandomAccessFile(myFile, RW);
+    mySize = -1;
     try {
       raf.setLength(newSize);
     }
@@ -345,10 +346,11 @@
   }
 
   public final long length() {
-    if (mySize == -1) {
-      mySize = myFile.length();
+    long size = mySize;
+    if (size == -1) {
+      mySize = size = myFile.length();
     }
-    return mySize;
+    return size;
   }
 
   private ByteBuffer getBuffer(int page) {
diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
index 70a71f97..b6f9816 100644
--- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
+++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.win32.IdeaWin32;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
@@ -31,7 +32,10 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
 
 public class UrlClassLoader extends ClassLoader {
   @NonNls static final String CLASS_EXTENSION = ".class";
@@ -43,7 +47,6 @@
     private boolean myUseCache = false;
     private boolean myAcceptUnescaped = false;
     private boolean myPreload = true;
-    private String[] myNativeLibs = null;
 
     private Builder() { }
 
@@ -56,7 +59,6 @@
     public Builder useCache(boolean useCache) { myUseCache = useCache; return this; }
     public Builder allowUnescaped() { myAcceptUnescaped = true; return this; }
     public Builder noPreload() { myPreload = false; return this; }
-    public Builder nativeLibs(String... libNames) { myNativeLibs = libNames; return this; }
     public UrlClassLoader get() { return new UrlClassLoader(this); }
   }
 
@@ -66,7 +68,6 @@
 
   private final List<URL> myURLs;
   private final ClassPath myClassPath;
-  private final Set<String> myNativeLibs;
 
   /** @deprecated use {@link #build()} (to remove in IDEA 14) */
   public UrlClassLoader(@NotNull ClassLoader parent) {
@@ -98,7 +99,6 @@
       }
     });
     myClassPath = new ClassPath(myURLs, lockJars, useCache, allowUnescaped, preload);
-    myNativeLibs = Collections.emptySet();
   }
 
   protected UrlClassLoader(@NotNull Builder builder) {
@@ -110,7 +110,6 @@
       }
     });
     myClassPath = new ClassPath(myURLs, builder.myLockJars, builder.myUseCache, builder.myAcceptUnescaped, builder.myPreload);
-    myNativeLibs = builder.myNativeLibs != null ? ContainerUtil.newHashSet(builder.myNativeLibs) : Collections.<String>emptySet();
   }
 
   public static URL internProtocol(@NotNull URL url) {
@@ -151,12 +150,6 @@
     }
   }
 
-
-  @Override
-  protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
-    return super.loadClass(name, resolve);
-  }
-
   @Nullable
   protected Class _findClass(@NotNull String name) {
     Resource res = myClassPath.getResource(name.replace('.', '/').concat(CLASS_EXTENSION), false);
@@ -233,38 +226,22 @@
     return myClassPath.getResources(name, true);
   }
 
-  @Override
-  protected String findLibrary(String libName) {
-    if (BinPathHolder.path != null && myNativeLibs.contains(libName)) {
-      String fileName = mapLibraryName(libName);
-      return BinPathHolder.path + File.separator + fileName;
-    }
+  public static void loadPlatformLibrary(@NotNull String libName) {
+    String libFileName = mapLibraryName(libName);
+    String libPath = PathManager.getBinPath() + "/" + libFileName;
 
-    return super.findLibrary(libName);
-  }
-
-  private static class BinPathHolder {
-    private static final String path;
-
-    static {
-      String homePath = PathManager.getHomePath();
-      if (new File(homePath, ".idea").exists()) {
-        if (new File(homePath, "community").exists()) {
-          homePath += File.separator + "community";
+    if (!new File(libPath).exists()) {
+      String platform = getPlatformName();
+      if (!new File(libPath = PathManager.getHomePath() + "/community/bin/" + platform + libFileName).exists()) {
+        if (!new File(libPath = PathManager.getHomePath() + "/bin/" + platform + libFileName).exists()) {
+          if (!new File(libPath = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libFileName).exists()) {
+            throw new UnsatisfiedLinkError("'" + libFileName + "' not found among " + Arrays.toString(new File(PathManager.getBinPath()).listFiles()));
+          }
         }
-
-        String libDir = null;
-        String prefix = homePath + File.separator + "bin" + File.separator;
-        if (SystemInfo.isWindows) libDir = prefix + "win";
-        else if (SystemInfo.isMac) libDir = prefix + "mac";
-        else if (SystemInfo.isLinux) libDir = prefix + "linux";
-
-        path = libDir;
-      }
-      else {
-        path = PathManager.getBinPath();
       }
     }
+
+    System.load(libPath);
   }
 
   private static String mapLibraryName(String libName) {
@@ -278,4 +255,11 @@
     }
     return fileName;
   }
+
+  private static String getPlatformName() {
+    if (SystemInfo.isWindows) return "win/";
+    else if (SystemInfo.isMac) return "mac/";
+    else if (SystemInfo.isLinux) return "linux/";
+    else return "";
+  }
 }
diff --git a/platform/util/src/com/intellij/util/ui/ListTableModel.java b/platform/util/src/com/intellij/util/ui/ListTableModel.java
index 3acc799..df39acc 100644
--- a/platform/util/src/com/intellij/util/ui/ListTableModel.java
+++ b/platform/util/src/com/intellij/util/ui/ListTableModel.java
@@ -193,7 +193,9 @@
 
   public void addRows(@NotNull Collection<Item> items) {
     myItems.addAll(items);
-    fireTableRowsInserted(myItems.size() - items.size(), myItems.size() - 1);
+    if (!myItems.isEmpty()) {
+      fireTableRowsInserted(myItems.size() - items.size(), myItems.size() - 1);
+    }
   }
 
   public Object getItem(final int rowIndex) {
diff --git a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java
index 6b5e4ff..9e1ba5a 100644
--- a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java
+++ b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java
@@ -44,7 +44,7 @@
   private static final Border LIST_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListBackgroundPainter");
   private static final Border LIST_SELECTION_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListSelectionBackgroundPainter");
   private static final Border LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListFocusedSelectionBackgroundPainter");
-  
+
   @NotNull private final Condition<Integer> myWideSelectionCondition;
   private boolean myWideSelection;
   private boolean myOldRepaintAllRowValue;
@@ -58,7 +58,7 @@
 
   /**
    * Creates new <code>WideSelectionTreeUI</code> object.
-   * 
+   *
    * @param wideSelection           flag that determines if wide selection should be used
    * @param wideSelectionCondition  strategy that determine if wide selection should be used for a target row (it's zero-based index
    *                                is given to the condition as an argument)
@@ -80,7 +80,7 @@
 
         final TreePath pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY());
         if (pressedPath != null) {
-          Rectangle bounds = getPathBounds(tree, pressedPath);
+          Rectangle bounds = getWidePathBounds(tree, pressedPath);
 
           if (e.getY() >= bounds.y + bounds.height) {
             return;
@@ -98,6 +98,15 @@
     }
   };
 
+  public Rectangle getWidePathBounds(JTree tree, TreePath path) {
+    Rectangle bounds = super.getPathBounds(tree, path);
+    if (bounds != null && tree != null) {
+      bounds.x = 0;
+      bounds.width = tree.getWidth();
+    }
+    return bounds;
+  }
+
   @Override
   protected void completeUIInstall() {
     super.completeUIInstall();
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 b8150ce..16013cf 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
@@ -1459,10 +1459,12 @@
     ourUpdateAlarm.get().execute(r);
   }
 
-  /**
-   * Can be called only from not AWT thread; to do smthg after ChangeListManager refresh, call invokeAfterUpdate
-   */
+  @TestOnly
   public boolean ensureUpToDate(final boolean canBeCanceled) {
+    if (ApplicationManager.getApplication().isDispatchThread()) {
+      updateImmediately();
+      return true;
+    }
     myVfsListener.flushDirt();
     final EnsureUpToDateFromNonAWTThread worker = new EnsureUpToDateFromNonAWTThread(myProject);
     worker.execute();
diff --git a/platform/xdebugger-api/src/com/intellij/chromeConnector/debugger/frame/XGroupingValuePresenter.java b/platform/xdebugger-api/src/com/intellij/chromeConnector/debugger/frame/XGroupingValuePresenter.java
new file mode 100644
index 0000000..63b2e98
--- /dev/null
+++ b/platform/xdebugger-api/src/com/intellij/chromeConnector/debugger/frame/XGroupingValuePresenter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.intellij.chromeConnector.debugger.frame;
+
+import com.intellij.ui.ColoredTextContainer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.xdebugger.frame.XValuePresenter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class XGroupingValuePresenter extends XValuePresenter {
+  public static final XGroupingValuePresenter INSTANCE = new XGroupingValuePresenter();
+
+  @Nullable
+  @Override
+  public SimpleTextAttributes getNameAttributes() {
+    return SimpleTextAttributes.REGULAR_ATTRIBUTES;
+  }
+
+  @Override
+  public void appendSeparator(@NotNull ColoredTextContainer text) {
+  }
+
+  @Override
+  public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
index 1e9cf57..39a5091 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
@@ -207,4 +207,12 @@
   public void setLayoutCustomizer(@Nullable XDebugLayoutCustomizer layoutCustomizer) {
     myLayoutCustomizer = layoutCustomizer;
   }
-}
+
+  /**
+   * Add or not SortValuesAction (alphabetically sort)
+   * @todo this action should be moved to "Variables" as gear action
+   */
+  public boolean isValuesCustomSorted() {
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/PrimitiveXValuePresenter.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/PrimitiveXValuePresenter.java
index 93890c0..68222d2 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/PrimitiveXValuePresenter.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/PrimitiveXValuePresenter.java
@@ -18,10 +18,11 @@
 import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
-import com.intellij.ui.SimpleColoredText;
+import com.intellij.ui.ColoredTextContainer;
 import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
 
-public class PrimitiveXValuePresenter implements XValuePresenter {
+public class PrimitiveXValuePresenter extends XValuePresenter {
   public static final XValuePresenter KEYWORD = new PrimitiveXValuePresenter(DefaultLanguageHighlighterColors.KEYWORD);
   public static final XValuePresenter NUMBER = new PrimitiveXValuePresenter(DefaultLanguageHighlighterColors.NUMBER);
 
@@ -32,7 +33,7 @@
   }
 
   @Override
-  public void append(String value, SimpleColoredText text, boolean changed) {
+  public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
     text.append(value, SimpleTextAttributes.fromTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(textAttributesKey)));
   }
 }
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/StringValuePresenter.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/StringValuePresenter.java
index c3ca0a5..ac5361e 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/StringValuePresenter.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/StringValuePresenter.java
@@ -18,12 +18,13 @@
 import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.ui.ColoredTextContainer;
 import com.intellij.ui.JBColor;
-import com.intellij.ui.SimpleColoredText;
 import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class StringValuePresenter implements XValuePresenter {
+public class StringValuePresenter extends XValuePresenter {
   public static final XValuePresenter DEFAULT = new StringValuePresenter(XValueNode.MAX_VALUE_LENGTH, "\"\\");
 
   private final int maxLength;
@@ -35,21 +36,26 @@
   }
 
   @Override
-  public void append(String value, SimpleColoredText text, boolean changed) {
+  public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
     SimpleTextAttributes attributes = SimpleTextAttributes.fromTextAttributes(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(DefaultLanguageHighlighterColors.STRING));
     text.append("\"", attributes);
     doAppend(value, text, attributes);
     text.append("\"", attributes);
   }
 
-  protected void doAppend(String value, SimpleColoredText text, SimpleTextAttributes attributes) {
+  protected void doAppend(@NotNull String value, @NotNull ColoredTextContainer text, @NotNull SimpleTextAttributes attributes) {
+    append(value, text, attributes, maxLength, additionalChars);
+  }
+
+  public static void append(@NotNull String value, @NotNull ColoredTextContainer text, @NotNull SimpleTextAttributes attributes, int maxLength, @Nullable String additionalChars) {
     SimpleTextAttributes escapeAttributes = null;
     int lastOffset = 0;
     int length = maxLength == -1 ? value.length() : Math.min(value.length(), maxLength);
     for (int i = 0; i < length; i++) {
       char ch = value.charAt(i);
       int additionalCharIndex = -1;
-      if (ch == '\n' || ch == '\r' || ch == '\t' || ch == '\b' || ch == '\f' || (additionalChars != null && (additionalCharIndex = additionalChars.indexOf(ch)) != -1)) {
+      if (ch == '\n' || ch == '\r' || ch == '\t' || ch == '\b' || ch == '\f' || (additionalChars != null && (additionalCharIndex = additionalChars
+        .indexOf(ch)) != -1)) {
         if (i > lastOffset) {
           text.append(value.substring(lastOffset, i), attributes);
         }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XGroupingValue.java
similarity index 60%
copy from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java
copy to platform/xdebugger-api/src/com/intellij/xdebugger/frame/XGroupingValue.java
index 7888121..2c44f94 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FileTypeUtils.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XGroupingValue.java
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.siyeh.ig.psiutils;
+package com.intellij.xdebugger.frame;
 
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.ServerPageFile;
-import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.chromeConnector.debugger.frame.XGroupingValuePresenter;
+import org.jetbrains.annotations.NotNull;
 
-public class FileTypeUtils {
-  public static boolean isInServerPageFile(PsiElement file) {
-    return PsiUtilCore.getTemplateLanguageFile(file) instanceof ServerPageFile;
+public abstract class XGroupingValue extends XValue {
+  @Override
+  public final void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
+    node.setPresentation(null, null, XGroupingValuePresenter.INSTANCE, true);
   }
-}
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java
index b932b03..b079d7e 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java
@@ -49,8 +49,7 @@
   void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @Nullable String value, boolean hasChildren);
 
   /**
-   * The same as {@link #setPresentation(javax.swing.Icon, String, String, boolean)} but also allows to
-   * customize {@code separator} between name and value
+   * @deprecated use XVariableValuePresenter
    */
   void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @Nullable String value, boolean hasChildren);
 
@@ -65,18 +64,21 @@
    * are escaped in the value. {@code valuePresenter} function doesn't affect 'Copy Value' action. It can be used to escape additional
    * characters and/or surround value by quotes.
    *
-   * @see com.intellij.openapi.util.text.StringUtil#QUOTER
-   * @see com.intellij.openapi.util.text.StringUtil#escaper
-   * @see com.intellij.util.FunctionUtil#composition
+   * @deprecated use {@link XValuePresenter}
    */
   void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value,
                        @Nullable NotNullFunction<String, String> valuePresenter, boolean hasChildren);
 
+  void setPresentation(@Nullable Icon icon,
+                       @NonNls @Nullable String type,
+                       @NonNls @NotNull String value,
+                       @Nullable XValuePresenter valuePresenter,
+                       boolean hasChildren);
+
   void setPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean hasChildren);
 
   /**
-   * The same as {@link #setPresentation(javax.swing.Icon, String, String, com.intellij.util.NotNullFunction, boolean)} but also allows to
-   * customize {@code separator} between name and value
+   * @deprecated use XVariableValuePresenter
    */
   void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @NotNull String value,
                        @Nullable NotNullFunction<String, String> valuePresenter, boolean hasChildren);
@@ -89,16 +91,4 @@
    * @see #MAX_VALUE_LENGTH
    */
   void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator);
-
-  /**
-   * @deprecated use {@link #setPresentation(javax.swing.Icon, String, String, boolean)} instead. Names for values should be passed to
-   * {@link XCompositeNode#addChildren(XValueChildrenProvider, boolean)}
-   */
-  void setPresentation(@NonNls String name, @Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value, boolean hasChildren);
-
-  /**
-   * @deprecated use {@link #setPresentation(javax.swing.Icon, String, String, String, boolean)} instead. Names for values should be passed to
-   * {@link XCompositeNode#addChildren(XValueChildrenProvider, boolean)}
-   */
-  void setPresentation(@NonNls String name, @Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @NotNull String value, boolean hasChildren);
-}
+}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValuePresenter.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValuePresenter.java
index 68bc4e9..f5f7937 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValuePresenter.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValuePresenter.java
@@ -15,8 +15,24 @@
  */
 package com.intellij.xdebugger.frame;
 
-import com.intellij.ui.SimpleColoredText;
+import com.intellij.ui.ColoredTextContainer;
+import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
-public interface XValuePresenter {
-  void append(String value, SimpleColoredText text, boolean changed);
+public abstract class XValuePresenter {
+  public void appendSeparator(@NotNull ColoredTextContainer text) {
+    text.append(" = ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
+  }
+
+  public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
+  }
+
+  @Nullable
+  /**
+   * if returns null, default value (depends on implementation) will be used
+   */
+  public SimpleTextAttributes getNameAttributes() {
+    return null;
+  }
 }
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/ui/XDebugLayoutCustomizer.java b/platform/xdebugger-api/src/com/intellij/xdebugger/ui/XDebugLayoutCustomizer.java
index f5a9ec3..fa02615 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/ui/XDebugLayoutCustomizer.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/ui/XDebugLayoutCustomizer.java
@@ -11,7 +11,6 @@
  * @author Sergey Simonchik
  */
 public interface XDebugLayoutCustomizer {
-
   /**
    * Registers tab for the given {@code console}, that is returned by {@link com.intellij.xdebugger.XDebugProcess#createConsole()}.
    *
@@ -27,4 +26,4 @@
    * @param ui {@code RunnerLayoutUi} instance
    */
   void registerAdditionalContent(@NotNull RunnerLayoutUi ui);
-}
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
index 06756b7..573c8fa 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
@@ -39,14 +39,17 @@
     myOffset = offset;
   }
 
+  @Override
   public int getLine() {
     return myLine;
   }
 
+  @Override
   public int getOffset() {
     return myOffset;
   }
 
+  @Override
   @NotNull
   public VirtualFile getFile() {
     return myFile;
@@ -78,6 +81,7 @@
     return new XSourcePositionImpl(file, line, offset);
   }
 
+  @Override
   @NotNull
   public Navigatable createNavigatable(final @NotNull Project project) {
     return myOffset != -1 ? new OpenFileDescriptor(project, myFile, myOffset) : new OpenFileDescriptor(project, myFile, getLine(), 0);
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 1c24e82..e1598fb 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
@@ -24,15 +24,15 @@
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.AppUIUtil;
 import com.intellij.ui.SimpleColoredText;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.NotNullFunction;
 import com.intellij.xdebugger.XDebugSession;
 import com.intellij.xdebugger.XDebuggerUtil;
 import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.intellij.xdebugger.frame.*;
+import com.intellij.xdebugger.frame.XFullValueEvaluator;
+import com.intellij.xdebugger.frame.XValue;
+import com.intellij.xdebugger.frame.XValuePlace;
+import com.intellij.xdebugger.frame.XValuePresenter;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
 import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
@@ -40,8 +40,7 @@
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationCallbackBase;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresenterAdapter;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -71,71 +70,52 @@
   }
 
 
+  @Override
   protected boolean canShowHint() {
     return true;
   }
 
+  @Override
   protected void evaluateAndShowHint() {
     myEvaluator.evaluate(myExpression, new XEvaluationCallbackBase() {
+      @Override
       public void evaluated(@NotNull final XValue result) {
-        result.computePresentation(new XValueNode() {
+        result.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() {
           @Override
-          public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value, boolean hasChildren) {
-            setPresentation(icon, type, XDebuggerUIConstants.EQ_TEXT, value, hasChildren);
+          public void applyPresentation(@Nullable Icon icon,
+                                        @Nullable String type,
+                                        @Nullable String value,
+                                        @NotNull XValuePresenter valuePresenter,
+                                        boolean hasChildren,
+                                        boolean expand) {
+            if (isHintHidden()) return;
+
+            SimpleColoredText text = new SimpleColoredText();
+            text.append(myExpression, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
+            XValueNodeImpl.buildText(type, value, valuePresenter, text, false);
+            if (!hasChildren) {
+              showHint(HintUtil.createInformationLabel(text));
+            }
+            else if (getType() == ValueHintType.MOUSE_CLICK_HINT) {
+              showTree(result, myExpression);
+            }
+            else {
+              JComponent component = createExpandableHintComponent(text, new Runnable() {
+                @Override
+                public void run() {
+                  showTree(result, myExpression);
+                }
+              });
+              showHint(component);
+            }
           }
 
           @Override
-          public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @NotNull String value,
-                                      boolean hasChildren) {
-            setPresentation(icon, type, separator, value, null, hasChildren);
-          }
-
-          @Override
-          public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value,
-                                      @Nullable NotNullFunction<String, String> valuePresenter, boolean hasChildren) {
-            setPresentation(icon, type, XDebuggerUIConstants.EQ_TEXT, value, valuePresenter, hasChildren);
-          }
-
-          @Override
-          public void setGroupingPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean expand) {
-            setPresentation(icon, value, valuePresenter, true);
-          }
-
-          @Override
-          public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean hasChildren) {
-            doSetPresentation(icon, null, XDebuggerUIConstants.EQ_TEXT, value, valuePresenter, hasChildren);
-          }
-
-          @Override
-          public void setPresentation(@Nullable Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String separator,
-                                      @NonNls @NotNull final String value, @Nullable final NotNullFunction<String, String> valuePresenter, final boolean hasChildren) {
-            doSetPresentation(icon, type, separator, value, valuePresenter == null ? null : new XValuePresenterAdapter(valuePresenter), hasChildren);
-          }
-
-          private void doSetPresentation(@Nullable Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String separator,
-                                      @NonNls @Nullable final String value, @Nullable final XValuePresenter valuePresenter, final boolean hasChildren) {
-            AppUIUtil.invokeOnEdt(new Runnable() {
-              public void run() {
-                doShowHint(result, separator, value, type, valuePresenter == null ? XValueNodeImpl.DEFAULT_VALUE_PRESENTER : valuePresenter, hasChildren);
-              }
-            });
-          }
-
-          public void setPresentation(@NonNls final String name, @Nullable final Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String value,
-                                      final boolean hasChildren) {
-            setPresentation(icon, type, value, hasChildren);
-          }
-
-          public void setPresentation(@NonNls final String name, @Nullable final Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String separator,
-                                      @NonNls @NotNull final String value,
-                                      final boolean hasChildren) {
-            setPresentation(icon, type, separator, value, hasChildren);
-          }
-
           public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) {
             //todo[nik] implement?
           }
 
+          @Override
           public boolean isObsolete() {
             //todo[nik]
             return false;
@@ -143,40 +123,13 @@
         }, XValuePlace.TOOLTIP);
       }
 
+      @Override
       public void errorOccurred(@NotNull final String errorMessage) {
         LOG.debug("Cannot evaluate '" + myExpression + "':" + errorMessage);
       }
     }, myExpressionPosition);
   }
 
-  private void doShowHint(final XValue xValue, final String separator, final String value, String type,
-                          @NotNull XValuePresenter valuePresenter, final boolean hasChildren) {
-    if (isHintHidden()) return;
-
-    SimpleColoredText text = new SimpleColoredText();
-    text.append(myExpression, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
-    text.append(separator, SimpleTextAttributes.REGULAR_ATTRIBUTES);
-    if (type != null) {
-      text.append("{" + type + "} ", XDebuggerUIConstants.TYPE_ATTRIBUTES);
-    }
-    valuePresenter.append(value, text, false);
-
-    if (!hasChildren) {
-      showHint(HintUtil.createInformationLabel(text));
-    }
-    else if (getType() == ValueHintType.MOUSE_CLICK_HINT) {
-      showTree(xValue, myExpression);
-    }
-    else {
-      JComponent component = createExpandableHintComponent(text, new Runnable() {
-        public void run() {
-          showTree(xValue, myExpression);
-        }
-      });
-      showHint(component);
-    }
-  }
-
   private void showTree(final XValue value, final String name) {
     XDebuggerTree tree = new XDebuggerTree(myDebugSession, myDebugSession.getDebugProcess().getEditorsProvider(),
                                            myDebugSession.getCurrentPosition(), XDebuggerActions.VALUE_HINT_TREE_POPUP_GROUP);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java
index d31414f..eb476c9 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java
@@ -35,11 +35,13 @@
     updateTree(initialItem);
   }
 
+  @Override
   protected void updateTree(final Pair<XValue, String> selectedItem) {
     myTree.setRoot(new XValueNodeImpl(myTree, null, selectedItem.getSecond(), selectedItem.getFirst()), true);
     myValueHint.showTreePopup(this, myTree, selectedItem.getSecond());
   }
 
+  @Override
   protected void setNodeAsRoot(final Object node) {
     if (node instanceof XValueNodeImpl) {
       final XValueNodeImpl valueNode = (XValueNodeImpl)node;
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 d7a5468..b407be6 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
@@ -197,11 +197,12 @@
     if (commonSettings.length > 0) {
       settings.addSeparator();
     }
-    settings.add(new ToggleSortValuesAction(commonSettings.length == 0));
+    if (!debugProcess.isValuesCustomSorted()) {
+      settings.add(new ToggleSortValuesAction(commonSettings.length == 0));
+    }
 
     leftToolbar.add(settings);
 
-
     leftToolbar.addSeparator();
 
     leftToolbar.add(PinToolwindowTabAction.getPinAction());
@@ -247,4 +248,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java
index 010e452..8bd8c99 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java
@@ -20,8 +20,8 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.ui.AppUIUtil;
 import com.intellij.ui.SimpleColoredComponent;
-import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.xdebugger.frame.XValueModifier;
+import com.intellij.xdebugger.frame.XValuePresenter;
 import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
 import org.jetbrains.annotations.NotNull;
@@ -47,11 +47,9 @@
     SimpleColoredComponent nameLabel = new SimpleColoredComponent();
     nameLabel.setIcon(getNode().getIcon());
     nameLabel.append(nodeName, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
-    final String separator = node.getSeparator();
-    if (separator != null) {
-      nameLabel.append(separator, SimpleTextAttributes.REGULAR_ATTRIBUTES);
-    }
-
+    XValuePresenter presenter = node.getValuePresenter();
+    assert presenter != null;
+    presenter.appendSeparator(nameLabel);
     myEditorPanel.add(nameLabel, BorderLayout.WEST);
 
     myEditorPanel.add(myExpressionEditor.getComponent(), BorderLayout.CENTER);
@@ -60,10 +58,12 @@
     myExpressionEditor.selectAll();
   }
 
+  @Override
   protected JComponent createInplaceEditorComponent() {
     return myEditorPanel;
   }
 
+  @Override
   public void doOKAction() {
     if (myModifier == null) return;
 
@@ -71,16 +71,20 @@
     final XDebuggerTreeState treeState = XDebuggerTreeState.saveState(myTree);
     myValueNode.setValueModificationStarted();
     myModifier.setValue(myExpressionEditor.getText(), new XValueModifier.XModificationCallback() {
+      @Override
       public void valueModified() {
         AppUIUtil.invokeOnEdt(new Runnable() {
+          @Override
           public void run() {
             myTree.rebuildAndRestore(treeState);
           }
         });
       }
 
+      @Override
       public void errorOccurred(@NotNull final String errorMessage) {
         AppUIUtil.invokeOnEdt(new Runnable() {
+          @Override
           public void run() {
             myTree.rebuildAndRestore(treeState);
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
index 25205fa..4480049 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
@@ -45,16 +45,19 @@
     init();
   }
 
+  @Override
   @Nullable
   protected JComponent createCenterPanel() {
     return myTreePanel.getMainPanel();
   }
 
+  @Override
   @Nullable
   protected JComponent createSouthPanel() {
     return null;
   }
 
+  @Override
   @NonNls
   protected String getDimensionServiceKey() {
     return "#xdebugger.XInspectDialog";
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java
index 00d3bfb..2c06c20 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java
@@ -15,8 +15,8 @@
  */
 package com.intellij.xdebugger.impl.ui.tree.nodes;
 
-import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import com.intellij.xdebugger.frame.XValue;
+import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -31,8 +31,9 @@
     myExpression = expression;
   }
 
+  @Override
   @NotNull
   public String getExpression() {
     return myExpression;
   }
-}
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
index 472b356a..2b6ab6f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
@@ -46,32 +46,39 @@
     myTree = tree;
   }
 
+  @Override
   public TreeNode getChildAt(final int childIndex) {
     if (isLeaf()) return null;
     return getChildren().get(childIndex);
   }
 
+  @Override
   public int getChildCount() {
     return isLeaf() ? 0 : getChildren().size();
   }
 
+  @Override
   public TreeNode getParent() {
     return myParent;
   }
 
+  @Override
   public int getIndex(final TreeNode node) {
     if (isLeaf()) return -1;
     return getChildren().indexOf(node);
   }
 
+  @Override
   public boolean getAllowsChildren() {
     return true;
   }
 
+  @Override
   public boolean isLeaf() {
     return myLeaf;
   }
 
+  @Override
   public Enumeration children() {
     if (isLeaf()) {
       return EmptyEnumeration.INSTANCE;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java
index afc718b..f77daf1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java
@@ -16,7 +16,6 @@
 package com.intellij.xdebugger.impl.ui.tree.nodes;
 
 import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.SmartList;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.SortedList;
 import com.intellij.xdebugger.frame.XCompositeNode;
@@ -92,7 +91,7 @@
             myValueChildren = new ArrayList<XValueNodeImpl>();
           }
         }
-        List<XValueContainerNode<?>> newChildren = new SmartList<XValueContainerNode<?>>();
+        List<XValueContainerNode<?>> newChildren = new ArrayList<XValueContainerNode<?>>(children.size());
         for (int i = 0; i < children.size(); i++) {
           XValueNodeImpl node = new XValueNodeImpl(myTree, XValueContainerNode.this, children.getName(i), children.getValue(i));
           myValueChildren.add(node);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
index a435bc5..285ea3e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
@@ -18,9 +18,10 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.AppUIUtil;
-import com.intellij.ui.SimpleColoredText;
+import com.intellij.ui.ColoredTextContainer;
 import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.util.NotNullFunction;
+import com.intellij.util.ObjectUtils;
 import com.intellij.xdebugger.frame.*;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.frame.XValueMarkers;
@@ -39,27 +40,20 @@
 /**
  * @author nik
  */
-public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValueNode, XCompositeNode {
+public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValueNode, XCompositeNode, XValueNodePresentationConfigurator.ConfigurableXValueNode {
   public static final Comparator<XValueNodeImpl> COMPARATOR = new Comparator<XValueNodeImpl>() {
     @Override
     public int compare(XValueNodeImpl o1, XValueNodeImpl o2) {
+      //noinspection ConstantConditions
       return StringUtil.naturalCompare(o1.getName(), o2.getName());
     }
   };
 
-  public static final XValuePresenter DEFAULT_VALUE_PRESENTER = new StringValuePresenter(-1, null) {
-    @Override
-    public void append(String value, SimpleColoredText text, boolean changed) {
-      doAppend(value, text, changed ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
-    }
-  };
-
-  private String myName;
+  private final String myName;
   private String myType;
   @Nullable
   private String myValue;
   private XFullValueEvaluator myFullValueEvaluator;
-  private String mySeparator;
   private boolean myChanged;
   private XValuePresenter myValuePresenter;
 
@@ -76,13 +70,13 @@
 
   @Override
   public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @Nullable String value, boolean hasChildren) {
-    setPresentation(icon, type, XDebuggerUIConstants.EQ_TEXT, value, hasChildren);
+    XValueNodePresentationConfigurator.setPresentation(icon, type, value, hasChildren, this);
   }
 
   @Override
   public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator,
                               @NonNls @Nullable String value, boolean hasChildren) {
-    setPresentation(null, icon, type, separator, value, hasChildren);
+    XValueNodePresentationConfigurator.setPresentation(icon, type, separator, value, hasChildren, this);
   }
 
   @Override
@@ -91,13 +85,16 @@
                               @NonNls @NotNull String value,
                               @Nullable NotNullFunction<String, String> valuePresenter,
                               boolean hasChildren) {
-    setPresentation(icon, type, XDebuggerUIConstants.EQ_TEXT, value, valuePresenter, hasChildren);
+    XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this);
   }
 
-
-  public void setPresentation(final String name, @Nullable final Icon icon, @Nullable final String type, @NotNull final String value,
-                              final boolean hasChildren) {
-    setPresentation(name, icon, type, XDebuggerUIConstants.EQ_TEXT, value, hasChildren);
+  @Override
+  public void setPresentation(@Nullable Icon icon,
+                              @NonNls @Nullable String type,
+                              @NonNls @NotNull String value,
+                              @Nullable XValuePresenter valuePresenter,
+                              boolean hasChildren) {
+    XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this);
   }
 
   @Override
@@ -105,59 +102,59 @@
                               @NonNls @Nullable String type,
                               @NonNls @NotNull String separator,
                               @NonNls @NotNull String value,
-                              final  @Nullable NotNullFunction<String, String> valuePresenter,
+                              final @Nullable NotNullFunction<String, String> valuePresenter,
                               boolean hasChildren) {
-    setPresentation(null, icon, type, separator, value, valuePresenter == null ? null : new XValuePresenterAdapter(valuePresenter), hasChildren, false);
-  }
-
-  public void setPresentation(@NonNls final String name, @Nullable final Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String separator,
-                              @NonNls @Nullable final String value, final boolean hasChildren) {
-    setPresentation(name, icon, type, separator, value, null, hasChildren, false);
+    XValueNodePresentationConfigurator.setPresentation(icon, type, separator, valuePresenter, hasChildren, this);
   }
 
   @Override
-  public void setGroupingPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean expand) {
-    setPresentation(null, icon, null, value == null ? "" : XDebuggerUIConstants.EQ_TEXT, value, valuePresenter, true, expand);
+  public void setGroupingPresentation(@Nullable Icon icon,
+                                      @NonNls @Nullable String value,
+                                      @Nullable XValuePresenter valuePresenter,
+                                      boolean expand) {
+    XValueNodePresentationConfigurator.setGroupingPresentation(icon, value, valuePresenter, expand, this);
   }
 
   @Override
-  public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean hasChildren) {
-    setPresentation(null, icon, null, XDebuggerUIConstants.EQ_TEXT, value, valuePresenter, hasChildren, false);
+  public void setPresentation(@Nullable Icon icon,
+                              @NonNls @Nullable String value,
+                              @Nullable XValuePresenter valuePresenter,
+                              boolean hasChildren) {
+    XValueNodePresentationConfigurator.setPresentation(icon, value, valuePresenter, hasChildren, this);
   }
 
-  private void setPresentation(@NonNls final String name, @Nullable final Icon icon, @NonNls @Nullable final String type, @NonNls @NotNull final String separator,
-                               @NonNls @Nullable final String value, @Nullable final XValuePresenter valuePresenter, final boolean hasChildren, final boolean expand) {
-    AppUIUtil.invokeOnEdt(new Runnable() {
-      public void run() {
-        setIcon(icon);
-        if (name != null) {
-          myName = name;
-        }
-        myValue = value;
-        mySeparator = separator;
-        myType = type;
-        myValuePresenter = valuePresenter != null ? valuePresenter : DEFAULT_VALUE_PRESENTER;
+  @Override
+  public void applyPresentation(@Nullable Icon icon,
+                                @Nullable String type,
+                                @Nullable String value,
+                                @NotNull XValuePresenter valuePresenter,
+                                boolean hasChildren,
+                                boolean expand) {
+    setIcon(icon);
+    myValue = value;
+    myType = type;
+    myValuePresenter = valuePresenter;
 
-        updateText();
-        setLeaf(!hasChildren);
-        fireNodeChanged();
-        myTree.nodeLoaded(XValueNodeImpl.this, myName, value);
-        if (expand) {
-          ApplicationManager.getApplication().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-              if (!isObsolete()) {
-                myTree.expandPath(getPath());
-              }
-            }
-          });
+    updateText();
+    setLeaf(!hasChildren);
+    fireNodeChanged();
+    myTree.nodeLoaded(this, myName, value);
+    if (expand) {
+      ApplicationManager.getApplication().invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          if (!isObsolete()) {
+            myTree.expandPath(getPath());
+          }
         }
-      }
-    });
+      });
+    }
   }
 
+  @Override
   public void setFullValueEvaluator(@NotNull final XFullValueEvaluator fullValueEvaluator) {
     AppUIUtil.invokeOnEdt(new Runnable() {
+      @Override
       public void run() {
         myFullValueEvaluator = fullValueEvaluator;
         fireNodeChanged();
@@ -174,15 +171,28 @@
         myText.append("[" + markup.getText() + "] ", new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, markup.getColor()));
       }
     }
-    myText.append(myName, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
-    if (!StringUtil.isEmpty(mySeparator)) {
-      myText.append(mySeparator, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+    if (!StringUtil.isEmpty(myName)) {
+      StringValuePresenter.append(myName, myText,
+                                  ObjectUtils.notNull(myValuePresenter.getNameAttributes(), XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES),
+                                  MAX_VALUE_LENGTH, null);
     }
-    if (myType != null) {
-      myText.append("{" + myType + "} ", XDebuggerUIConstants.TYPE_ATTRIBUTES);
+
+    buildText(myType, myValue, myValuePresenter, myText, myChanged);
+  }
+
+  public static void buildText(@Nullable String type,
+                               @Nullable String value,
+                               @NotNull XValuePresenter valuePresenter,
+                               @NotNull ColoredTextContainer text,
+                               boolean changed) {
+    if (value != null) {
+      valuePresenter.appendSeparator(text);
     }
-    if (myValue != null) {
-      myValuePresenter.append(myValue, myText, myChanged);
+    if (type != null) {
+      text.append("{" + type + "} ", XDebuggerUIConstants.TYPE_ATTRIBUTES);
+    }
+    if (value != null) {
+      valuePresenter.append(value, text, changed);
     }
   }
 
@@ -222,8 +232,8 @@
   }
 
   @Nullable
-  public String getSeparator() {
-    return mySeparator;
+  public XValuePresenter getValuePresenter() {
+    return myValuePresenter;
   }
 
   @Nullable
@@ -237,7 +247,7 @@
   }
 
   public boolean isComputed() {
-    return myName != null && myValuePresenter != null;
+    return myValuePresenter != null;
   }
 
   public void setValueModificationStarted() {
@@ -245,7 +255,7 @@
     myValue = null;
     myText.clear();
     myText.append(myName, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
-    myText.append(mySeparator, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+    myValuePresenter.appendSeparator(myText);
     myText.append(XDebuggerUIConstants.MODIFYING_VALUE_MESSAGE, XDebuggerUIConstants.MODIFYING_VALUE_HIGHLIGHT_ATTRIBUTES);
     setLeaf(true);
     fireNodeStructureChanged();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java
new file mode 100644
index 0000000..555efa6
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java
@@ -0,0 +1,182 @@
+package com.intellij.xdebugger.impl.ui.tree.nodes;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.ui.ColoredTextContainer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.ObjectUtils;
+import com.intellij.xdebugger.frame.XValueNode;
+import com.intellij.xdebugger.frame.XValuePresenter;
+import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public final class XValueNodePresentationConfigurator {
+  private static final XValuePresenter DEFAULT_VALUE_PRESENTER = new XVariableValuePresenter(XDebuggerUIConstants.EQ_TEXT);
+
+  public interface ConfigurableXValueNode {
+    void applyPresentation(@Nullable Icon icon,
+                           @Nullable String type,
+                           @Nullable String value,
+                           @NotNull XValuePresenter valuePresenter,
+                           boolean hasChildren,
+                           boolean expand);
+  }
+
+  public static abstract class ConfigurableXValueNodeImpl implements ConfigurableXValueNode, XValueNode {
+    @Override
+    public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @Nullable String value, boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, type, value, hasChildren, this);
+    }
+
+    @Override
+    public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator,
+                                @NonNls @Nullable String value, boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, type, separator, value, hasChildren, this);
+    }
+
+    @Override
+    public void setPresentation(@Nullable Icon icon,
+                                @NonNls @Nullable String type,
+                                @NonNls @NotNull String value,
+                                @Nullable NotNullFunction<String, String> valuePresenter,
+                                boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this);
+    }
+
+    @Override
+    public void setPresentation(@Nullable Icon icon,
+                                @NonNls @Nullable String type,
+                                @NonNls @NotNull String value,
+                                @Nullable XValuePresenter valuePresenter,
+                                boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this);
+    }
+
+    @Override
+    public void setPresentation(@Nullable Icon icon,
+                                @NonNls @Nullable String type,
+                                @NonNls @NotNull String separator,
+                                @NonNls @NotNull String value,
+                                final @Nullable NotNullFunction<String, String> valuePresenter,
+                                boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, type, separator, valuePresenter, hasChildren, this);
+    }
+
+    @Override
+    public void setGroupingPresentation(@Nullable Icon icon,
+                                        @NonNls @Nullable String value,
+                                        @Nullable XValuePresenter valuePresenter,
+                                        boolean expand) {
+      XValueNodePresentationConfigurator.setGroupingPresentation(icon, value, valuePresenter, expand, this);
+    }
+
+    @Override
+    public void setPresentation(@Nullable Icon icon,
+                                @NonNls @Nullable String value,
+                                @Nullable XValuePresenter valuePresenter,
+                                boolean hasChildren) {
+      XValueNodePresentationConfigurator.setPresentation(icon, value, valuePresenter, hasChildren, this);
+    }
+  }
+
+  public static void setPresentation(@Nullable Icon icon,
+                                     @NonNls @Nullable String type,
+                                     @NonNls @Nullable String value,
+                                     boolean hasChildren,
+                                     ConfigurableXValueNode node) {
+    doSetPresentation(icon, type, value, DEFAULT_VALUE_PRESENTER, hasChildren, false, node);
+  }
+
+  public static void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator,
+                                     @NonNls @Nullable String value, boolean hasChildren, ConfigurableXValueNode node) {
+    doSetPresentation(icon, type, value, createPresenter(separator), hasChildren, false, node);
+  }
+
+  private static XValuePresenter createPresenter(@NotNull String separator) {
+    return separator.equals(XDebuggerUIConstants.EQ_TEXT) ? DEFAULT_VALUE_PRESENTER : new XVariableValuePresenter(separator);
+  }
+
+  public static void setPresentation(@Nullable Icon icon,
+                                     @NonNls @Nullable String type,
+                                     @NonNls @NotNull String value,
+                                     @Nullable NotNullFunction<String, String> valuePresenter,
+                                     boolean hasChildren, ConfigurableXValueNode node) {
+    doSetPresentation(icon, type, value,
+                      valuePresenter == null ? DEFAULT_VALUE_PRESENTER : new XValuePresenterAdapter(valuePresenter),
+                      hasChildren, false, node);
+  }
+
+  public static void setPresentation(@Nullable Icon icon,
+                                     @NonNls @Nullable String type,
+                                     @NonNls @NotNull String value,
+                                     @Nullable XValuePresenter valuePresenter,
+                                     boolean hasChildren, ConfigurableXValueNode node) {
+    doSetPresentation(icon, type, value, valuePresenter, hasChildren, false, node);
+  }
+
+  public static void setPresentation(@Nullable Icon icon,
+                                     @NonNls @Nullable String type,
+                                     @SuppressWarnings("UnusedParameters") @NonNls @NotNull String separator,
+                                     @NonNls @NotNull String value,
+                                     final @Nullable NotNullFunction<String, String> valuePresenter,
+                                     boolean hasChildren, ConfigurableXValueNode node) {
+    // yes, we ignore separator, it is deprecated method
+    doSetPresentation(icon, type, value, valuePresenter == null ? DEFAULT_VALUE_PRESENTER : new XValuePresenterAdapter(valuePresenter), hasChildren, false, node);
+  }
+
+  public static void setGroupingPresentation(@Nullable Icon icon,
+                                             @NonNls @Nullable String value,
+                                             @Nullable XValuePresenter valuePresenter,
+                                             boolean expand,
+                                             ConfigurableXValueNode node) {
+    doSetPresentation(icon, null, value, valuePresenter, true, expand, node);
+  }
+
+  public static void setPresentation(@Nullable Icon icon,
+                                     @NonNls @Nullable String value,
+                                     @Nullable XValuePresenter valuePresenter,
+                                     boolean hasChildren,
+                                     ConfigurableXValueNode node) {
+    doSetPresentation(icon, null, value, valuePresenter, hasChildren, false, node);
+  }
+
+  private static void doSetPresentation(@Nullable final Icon icon,
+                                        @NonNls @Nullable final String type,
+                                        @NonNls @Nullable final String value,
+                                        @Nullable XValuePresenter valuePresenter,
+                                        final boolean hasChildren,
+                                        final boolean expand,
+                                        final ConfigurableXValueNode node) {
+    Application application = ApplicationManager.getApplication();
+    final XValuePresenter finalValuePresenter = ObjectUtils.notNull(valuePresenter, DEFAULT_VALUE_PRESENTER);
+    if (application.isDispatchThread()) {
+      node.applyPresentation(icon, type, value, finalValuePresenter, hasChildren, expand);
+    }
+    else {
+      application.invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          node.applyPresentation(icon, type, value, finalValuePresenter, hasChildren, expand);
+        }
+      });
+    }
+  }
+
+  private static final class XValuePresenterAdapter extends XValuePresenter {
+    private final NotNullFunction<String, String> valuePresenter;
+
+    public XValuePresenterAdapter(NotNullFunction<String, String> valuePresenter) {
+      this.valuePresenter = valuePresenter;
+    }
+
+    @Override
+    public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
+      text.append(valuePresenter.fun(value), changed ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresenterAdapter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresenterAdapter.java
deleted file mode 100644
index fa7df03..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresenterAdapter.java
+++ /dev/null
@@ -1,35 +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 com.intellij.xdebugger.impl.ui.tree.nodes;
-
-import com.intellij.ui.SimpleColoredText;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.NotNullFunction;
-import com.intellij.xdebugger.frame.XValuePresenter;
-import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
-
-public class XValuePresenterAdapter implements XValuePresenter {
-  private final NotNullFunction<String, String> valuePresenter;
-
-  public XValuePresenterAdapter(NotNullFunction<String, String> valuePresenter) {
-    this.valuePresenter = valuePresenter;
-  }
-
-  @Override
-  public void append(String value, SimpleColoredText text, boolean changed) {
-    text.append(valuePresenter.fun(value), changed ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
-  }
-}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XVariableValuePresenter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XVariableValuePresenter.java
new file mode 100644
index 0000000..4411dc0
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XVariableValuePresenter.java
@@ -0,0 +1,27 @@
+package com.intellij.xdebugger.impl.ui.tree.nodes;
+
+import com.intellij.ui.ColoredTextContainer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.xdebugger.frame.StringValuePresenter;
+import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
+import org.jetbrains.annotations.NotNull;
+
+public final class XVariableValuePresenter extends StringValuePresenter {
+  private final String separator;
+
+  public XVariableValuePresenter(@NotNull String separator) {
+    super(-1, null);
+
+    this.separator = separator;
+  }
+
+  @Override
+  public void appendSeparator(@NotNull ColoredTextContainer text) {
+    text.append(separator, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+  }
+
+  @Override
+  public void append(@NotNull String value, @NotNull ColoredTextContainer text, boolean changed) {
+    doAppend(value, text, changed ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java
index 6c4ba46..7ce4891 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java
@@ -1,17 +1,15 @@
 package com.intellij.xdebugger;
 
-import com.intellij.util.NotNullFunction;
 import com.intellij.xdebugger.frame.XFullValueEvaluator;
-import com.intellij.xdebugger.frame.XValueNode;
 import com.intellij.xdebugger.frame.XValuePresenter;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.util.concurrent.Semaphore;
 
-public class XTestValueNode implements XValueNode {
+public class XTestValueNode extends XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl {
   public String myName;
   public String myType;
   public String myValue;
@@ -21,9 +19,13 @@
 
   private final Semaphore myFinished = new Semaphore(0);
 
-
   @Override
-  public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value, boolean hasChildren) {
+  public void applyPresentation(@Nullable Icon icon,
+                                @Nullable String type,
+                                @Nullable String value,
+                                @NotNull XValuePresenter valuePresenter,
+                                boolean hasChildren,
+                                boolean expand) {
     myType = type;
     myValue = value;
     myHasChildren = hasChildren;
@@ -32,64 +34,11 @@
   }
 
   @Override
-  public void setGroupingPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean expand) {
-    setPresentation(icon, value, valuePresenter, true);
-  }
-
-  @Override
-  public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String value, @Nullable XValuePresenter valuePresenter, boolean hasChildren) {
-    setPresentation(icon, null, value, hasChildren);
-  }
-
-  @Override
-  public void setPresentation(@Nullable Icon icon,
-                              @NonNls @Nullable String type,
-                              @NonNls @NotNull String separator,
-                              @NonNls @NotNull String value,
-                              @Nullable NotNullFunction<String, String> valuePresenter,
-                              boolean hasChildren) {
-    setPresentation(icon, type, value, hasChildren);
-  }
-
-  @Override
-  public void setPresentation(@Nullable Icon icon,
-                              @NonNls @Nullable String type,
-                              @NonNls @NotNull String separator,
-                              @NonNls @NotNull String value,
-                              boolean hasChildren) {
-    setPresentation(icon, type, value, hasChildren);
-  }
-
-  @Override
-  public void setPresentation(@Nullable Icon icon,
-                              @NonNls @Nullable String type,
-                              @NonNls @NotNull String value,
-                              @Nullable NotNullFunction<String, String> valuePresenter,
-                              boolean hasChildren) {
-    setPresentation(icon, type, value, hasChildren);
-  }
-
-  public void setPresentation(@NonNls @NotNull String name,
-                              @Nullable Icon icon,
-                              @NonNls @Nullable String type,
-                              @NonNls @NotNull String value,
-                              boolean hasChildren) {
-    setPresentation(icon, type, value, hasChildren);
-  }
-
-  public void setPresentation(@NonNls @NotNull String name,
-                              @Nullable Icon icon,
-                              @NonNls @Nullable String type,
-                              @NonNls @NotNull String separator,
-                              @NonNls @NotNull String value,
-                              boolean hasChildren) {
-    setPresentation(icon, type, value, hasChildren);
-  }
-
   public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) {
     myFullValueEvaluator = fullValueEvaluator;
   }
 
+  @Override
   public boolean isObsolete() {
     return false;
   }
diff --git a/plugins/ByteCodeViewer/src/META-INF/plugin.xml b/plugins/ByteCodeViewer/src/META-INF/plugin.xml
index 9a0135a..e9c6e32 100644
--- a/plugins/ByteCodeViewer/src/META-INF/plugin.xml
+++ b/plugins/ByteCodeViewer/src/META-INF/plugin.xml
@@ -5,6 +5,9 @@
   <description>Viewing java bytecode inside IntelliJ IDEA.</description>
   <vendor>JetBrains</vendor>
 
+  <extensionPoints>
+    <extensionPoint name="classSearcher" interface="com.intellij.byteCodeViewer.ClassSearcher"/>
+  </extensionPoints>
   <extensions defaultExtensionNs="com.intellij">
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
     <projectService serviceInterface="com.intellij.byteCodeViewer.ByteCodeViewerManager"
diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
index a5fc96c..7d958bb6 100644
--- a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
+++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
@@ -5,6 +5,7 @@
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
@@ -35,6 +36,8 @@
  * Date: 5/7/12
  */
 public class ByteCodeViewerManager extends DockablePopupManager<ByteCodeViewerComponent> {
+  private static final ExtensionPointName<ClassSearcher> CLASS_SEARCHER_EP = ExtensionPointName.create("ByteCodeViewer.classSearcher");
+
   private static final Logger LOG = Logger.getInstance("#" + ByteCodeViewerManager.class.getName());
 
   public static final String TOOLWINDOW_ID = "Byte Code Viewer";
@@ -232,10 +235,20 @@
     return ClassUtil.getJVMClassName(containingClass);
   }
 
-  private static PsiClass getContainingClass(PsiElement psiElement) {
+  public static PsiClass getContainingClass(PsiElement psiElement) {
+    for (ClassSearcher searcher : CLASS_SEARCHER_EP.getExtensions()) {
+      PsiClass aClass = searcher.findClass(psiElement);
+      if (aClass != null) {
+        return aClass;
+      }
+    }
+    return findClass(psiElement);
+  }
+
+  public static PsiClass findClass(@NotNull PsiElement psiElement) {
     PsiClass containingClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class, false);
     while (containingClass instanceof PsiTypeParameter) {
-      containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class); 
+      containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class);
     }
     if (containingClass == null) return null;
 
diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ClassSearcher.java b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ClassSearcher.java
new file mode 100644
index 0000000..9a778d1
--- /dev/null
+++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ClassSearcher.java
@@ -0,0 +1,14 @@
+package com.intellij.byteCodeViewer;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by Max Medvedev on 8/23/13
+ */
+public interface ClassSearcher {
+  @Nullable
+  PsiClass findClass(@NotNull PsiElement place);
+}
diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
index 34b5d44..76cf133 100644
--- a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
+++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
@@ -20,7 +20,6 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.ui.popup.NotLookupOrSearchCondition;
@@ -43,7 +42,7 @@
       final PsiElement psiElement = getPsiElement(e.getDataContext(), project, e.getData(PlatformDataKeys.EDITOR));
       if (psiElement != null) {
         if (psiElement.getContainingFile() instanceof PsiClassOwner &&
-            PsiTreeUtil.getParentOfType(psiElement, PsiClass.class, false) != null) {
+            ByteCodeViewerManager.getContainingClass(psiElement) != null) {
           e.getPresentation().setEnabled(true);
         }
       }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index f62b033..8bb0e68 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1228,6 +1228,9 @@
 synchronized.method.move.quickfix=Move synchronization into method
 thread.run.replace.quickfix=Replace with 'start()'
 volatile.field.problem.descriptor=Volatile field <code>#ref</code> of type ''{0}'' #loc
+string.format.choose.class=Choose Formatter class
+string.format.class.column.name=Additional formatter classes
+string.format.class.method.name=Additional formatter methods
 exception.class.column.name=Exception class
 bad.exception.thrown.problem.descriptor=Prohibited exception ''{0}'' thrown #loc
 empty.catch.block.comments.option=Comments count as content
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
index 7cd60f3b..d0feec6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
@@ -29,7 +29,7 @@
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyStatementBodyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyStatementBodyInspection.java
index 5e3b4c4..afea6ec 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyStatementBodyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyStatementBodyInspection.java
@@ -21,7 +21,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java
similarity index 76%
rename from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java
rename to plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java
index 1cf1973..052e742 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java
@@ -15,6 +15,8 @@
  */
 package com.siyeh.ig.bugs;
 
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.*;
 import com.intellij.psi.util.ConstantExpressionUtil;
 import com.intellij.psi.util.PsiUtil;
@@ -23,9 +25,47 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.ExpressionUtils;
 import com.siyeh.ig.psiutils.FormatUtils;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-public class MalformedFormatStringInspection extends BaseInspection {
+import java.util.ArrayList;
+import java.util.List;
+
+public class MalformedFormatStringInspectionBase extends BaseInspection {
+  /**
+   * @noinspection PublicField
+   */
+  @NonNls public String additionalClasses = "";
+
+  /**
+   * @noinspection PublicField
+   */
+  @NonNls public String additionalMethods = "";
+
+  final List<String> classNames;
+  final List<String> methodNames;
+
+  public MalformedFormatStringInspectionBase() {
+    classNames = new ArrayList<String>();
+    methodNames = new ArrayList<String>();
+    parseString(additionalClasses, classNames);
+    parseString(additionalMethods, methodNames);
+  }
+
+  @Override
+  public void readSettings(@NotNull Element node) throws InvalidDataException {
+    super.readSettings(node);
+    parseString(additionalClasses, classNames);
+    parseString(additionalMethods, methodNames);
+  }
+
+  @Override
+  public void writeSettings(@NotNull Element node) throws WriteExternalException {
+    additionalClasses = formatString(classNames);
+    additionalMethods = formatString(methodNames);
+    super.writeSettings(node);
+  }
 
   @Override
   @NotNull
@@ -61,12 +101,12 @@
     return new MalformedFormatStringVisitor();
   }
 
-  private static class MalformedFormatStringVisitor extends BaseInspectionVisitor {
+  private class MalformedFormatStringVisitor extends BaseInspectionVisitor {
 
     @Override
     public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
       super.visitMethodCallExpression(expression);
-      if (!FormatUtils.isFormatCall(expression)) {
+      if (!FormatUtils.isFormatCall(expression, methodNames, classNames)) {
         return;
       }
       final PsiExpressionList argumentList = expression.getArgumentList();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryContinueInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryContinueInspection.java
index 36a0dc90..77a3ab3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryContinueInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryContinueInspection.java
@@ -24,7 +24,7 @@
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.DeleteUnnecessaryStatementFix;
 import com.siyeh.ig.psiutils.ControlFlowUtils;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java
index 5c8f1df..48c1018 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java
@@ -24,7 +24,7 @@
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.DeleteUnnecessaryStatementFix;
 import com.siyeh.ig.psiutils.ControlFlowUtils;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java
index 07b7786..435dd24 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java
@@ -27,7 +27,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.ClassUtils;
 import com.siyeh.ig.psiutils.ExpressionUtils;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ig.psiutils.VariableAccessUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
index 4a9b58b..fa50fb4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
@@ -24,7 +24,7 @@
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ig.psiutils.TestUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java
index 8e3fbeb..741d7cf 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java
@@ -25,7 +25,7 @@
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class EmptyFinallyBlockInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyTryBlockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyTryBlockInspection.java
index 57003f5..04f50af 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyTryBlockInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyTryBlockInspection.java
@@ -20,7 +20,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class EmptyTryBlockInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/JavaLangImportInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/JavaLangImportInspection.java
index 36c31ac..f0d521d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/JavaLangImportInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/JavaLangImportInspection.java
@@ -22,7 +22,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.DeleteImportFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ig.psiutils.ImportUtils;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/OnDemandImportInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/OnDemandImportInspection.java
index d9d9dd9..f9d5aea 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/OnDemandImportInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/OnDemandImportInspection.java
@@ -19,7 +19,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class OnDemandImportInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SamePackageImportInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SamePackageImportInspection.java
index 579a20b..3d9ee11 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SamePackageImportInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SamePackageImportInspection.java
@@ -21,7 +21,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.DeleteImportFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class SamePackageImportInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SingleClassImportInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SingleClassImportInspection.java
index 91692ab..9bcad8f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SingleClassImportInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/SingleClassImportInspection.java
@@ -22,7 +22,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class SingleClassImportInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/UnusedImportInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/UnusedImportInspection.java
index 49c58d1..7b6b72a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/UnusedImportInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/UnusedImportInspection.java
@@ -21,7 +21,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.DeleteImportFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
index bc1fbe0..a1952f0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
@@ -25,7 +25,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.psiutils.ClassUtils;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java
index 2aa3c07..d1bd35e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java
@@ -24,7 +24,7 @@
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class ClassWithoutConstructorInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FormatUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FormatUtils.java
index 68e431e..9be61bc 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FormatUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FormatUtils.java
@@ -20,7 +20,9 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 public class FormatUtils {
@@ -48,9 +50,13 @@
   private FormatUtils() {}
 
   public static boolean isFormatCall(PsiMethodCallExpression expression) {
+    return isFormatCall(expression, Collections.<String>emptyList(), Collections.<String>emptyList());
+  }
+
+  public static boolean isFormatCall(PsiMethodCallExpression expression, List<String> optionalMethods, List<String> optionalClasses) {
     final PsiReferenceExpression methodExpression = expression.getMethodExpression();
     final String name = methodExpression.getReferenceName();
-    if (!formatMethodNames.contains(name)) {
+    if (!formatMethodNames.contains(name) && !optionalMethods.contains(name)) {
       return false;
     }
     final PsiMethod method = expression.resolveMethod();
@@ -62,7 +68,7 @@
       return false;
     }
     final String className = containingClass.getQualifiedName();
-    return formatClassNames.contains(className);
+    return formatClassNames.contains(className) || optionalClasses.contains(className);
   }
 
   public static boolean isFormatCallArgument(PsiElement element) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java
index 29c8b46..67c6a32 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -21,58 +21,43 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 public class InitializationUtils {
 
   private InitializationUtils() {}
 
-  public static boolean methodAssignsVariableOrFails(
-    @Nullable PsiMethod method, @NotNull PsiVariable variable) {
+  public static boolean methodAssignsVariableOrFails(@Nullable PsiMethod method, @NotNull PsiVariable variable) {
     return methodAssignsVariableOrFails(method, variable, false);
   }
 
-  public static boolean expressionAssignsVariableOrFails(
-    @Nullable PsiExpression expression, @NotNull PsiVariable variable) {
-    return expressionAssignsVariableOrFails(expression, variable,
-                                            new HashSet(), true);
+  public static boolean expressionAssignsVariableOrFails(@Nullable PsiExpression expression, @NotNull PsiVariable variable) {
+    return expressionAssignsVariableOrFails(expression, variable, new HashSet(), true);
   }
 
-  public static boolean methodAssignsVariableOrFails(
-    @Nullable PsiMethod method, @NotNull PsiVariable variable,
-    boolean strict) {
+  public static boolean methodAssignsVariableOrFails(@Nullable PsiMethod method, @NotNull PsiVariable variable, boolean strict) {
     if (method == null) {
       return false;
     }
-    final PsiCodeBlock body = method.getBody();
-    return body != null && blockAssignsVariableOrFails(body, variable,
-                                                       strict);
+    return blockAssignsVariableOrFails(method.getBody(), variable, strict);
   }
 
-  public static boolean blockAssignsVariableOrFails(
-    @Nullable PsiCodeBlock block, @NotNull PsiVariable variable) {
+  public static boolean blockAssignsVariableOrFails(@Nullable PsiCodeBlock block, @NotNull PsiVariable variable) {
     return blockAssignsVariableOrFails(block, variable, false);
   }
 
-  public static boolean blockAssignsVariableOrFails(
-    @Nullable PsiCodeBlock block, @NotNull PsiVariable variable,
-    boolean strict) {
-    return blockAssignsVariableOrFails(block, variable,
-                                       new HashSet<MethodSignature>(), strict);
+  public static boolean blockAssignsVariableOrFails(@Nullable PsiCodeBlock block, @NotNull PsiVariable variable, boolean strict) {
+    return blockAssignsVariableOrFails(block, variable, new HashSet<MethodSignature>(), strict);
   }
 
-  private static boolean blockAssignsVariableOrFails(
-    @Nullable PsiCodeBlock block, @NotNull PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+  private static boolean blockAssignsVariableOrFails(@Nullable PsiCodeBlock block, @NotNull PsiVariable variable,
+                                                     @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     if (block == null) {
       return false;
     }
-    final PsiStatement[] statements = block.getStatements();
     int assignmentCount = 0;
-    for (final PsiStatement statement : statements) {
-      if (statementAssignsVariableOrFails(statement, variable,
-                                          checkedMethods, strict)) {
+    for (final PsiStatement statement : block.getStatements()) {
+      if (statementAssignsVariableOrFails(statement, variable, checkedMethods, strict)) {
         if (strict) {
           assignmentCount++;
         }
@@ -84,9 +69,8 @@
     return assignmentCount == 1;
   }
 
-  private static boolean statementAssignsVariableOrFails(
-    @Nullable PsiStatement statement, PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+  private static boolean statementAssignsVariableOrFails(@Nullable PsiStatement statement, PsiVariable variable,
+                                                         @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     if (statement == null) {
       return false;
     }
@@ -101,107 +85,70 @@
       return false;
     }
     else if (statement instanceof PsiReturnStatement) {
-      final PsiReturnStatement returnStatement =
-        (PsiReturnStatement)statement;
-      final PsiExpression returnValue = returnStatement.getReturnValue();
-      return expressionAssignsVariableOrFails(returnValue, variable,
-                                              checkedMethods, strict);
+      final PsiReturnStatement returnStatement = (PsiReturnStatement)statement;
+      return expressionAssignsVariableOrFails(returnStatement.getReturnValue(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiThrowStatement) {
-      final PsiThrowStatement throwStatement =
-        (PsiThrowStatement)statement;
-      final PsiExpression exception = throwStatement.getException();
-      return expressionAssignsVariableOrFails(exception, variable,
-                                              checkedMethods, strict);
+      final PsiThrowStatement throwStatement = (PsiThrowStatement)statement;
+      return expressionAssignsVariableOrFails(throwStatement.getException(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiExpressionListStatement) {
-      final PsiExpressionListStatement list =
-        (PsiExpressionListStatement)statement;
+      final PsiExpressionListStatement list = (PsiExpressionListStatement)statement;
       final PsiExpressionList expressionList = list.getExpressionList();
-      final PsiExpression[] expressions = expressionList.getExpressions();
-      for (final PsiExpression expression : expressions) {
-        if (expressionAssignsVariableOrFails(expression, variable,
-                                             checkedMethods, strict)) {
+      for (final PsiExpression expression : expressionList.getExpressions()) {
+        if (expressionAssignsVariableOrFails(expression, variable, checkedMethods, strict)) {
           return true;
         }
       }
       return false;
     }
     else if (statement instanceof PsiExpressionStatement) {
-      final PsiExpressionStatement expressionStatement =
-        (PsiExpressionStatement)statement;
-      final PsiExpression expression =
-        expressionStatement.getExpression();
-      return expressionAssignsVariableOrFails(expression, variable,
-                                              checkedMethods, strict);
+      final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)statement;
+      return expressionAssignsVariableOrFails(expressionStatement.getExpression(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiDeclarationStatement) {
-      final PsiDeclarationStatement declarationStatement =
-        (PsiDeclarationStatement)statement;
-      return declarationStatementAssignsVariableOrFails(
-        declarationStatement, variable, checkedMethods, strict);
+      final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)statement;
+      return declarationStatementAssignsVariableOrFails(declarationStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiForStatement) {
       final PsiForStatement forStatement = (PsiForStatement)statement;
-      return forStatementAssignsVariableOrFails(forStatement,
-                                                variable,
-                                                checkedMethods, strict);
+      return forStatementAssignsVariableOrFails(forStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiForeachStatement) {
-      final PsiForeachStatement foreachStatement =
-        (PsiForeachStatement)statement;
-      return foreachStatementAssignsVariableOrFails(variable,
-                                                    foreachStatement);
+      final PsiForeachStatement foreachStatement = (PsiForeachStatement)statement;
+      return foreachStatementAssignsVariableOrFails(foreachStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiWhileStatement) {
-      final PsiWhileStatement whileStatement =
-        (PsiWhileStatement)statement;
-      return whileStatementAssignsVariableOrFails(whileStatement,
-                                                  variable, checkedMethods, strict);
+      final PsiWhileStatement whileStatement = (PsiWhileStatement)statement;
+      return whileStatementAssignsVariableOrFails(whileStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiDoWhileStatement) {
-      final PsiDoWhileStatement doWhileStatement =
-        (PsiDoWhileStatement)statement;
-      return doWhileAssignsVariableOrFails(doWhileStatement, variable,
-                                           checkedMethods, strict);
+      final PsiDoWhileStatement doWhileStatement = (PsiDoWhileStatement)statement;
+      return doWhileAssignsVariableOrFails(doWhileStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiSynchronizedStatement) {
-      final PsiSynchronizedStatement synchronizedStatement =
-        (PsiSynchronizedStatement)statement;
-      final PsiCodeBlock body = synchronizedStatement.getBody();
-      return blockAssignsVariableOrFails(body, variable,
-                                         checkedMethods, strict);
+      final PsiSynchronizedStatement synchronizedStatement = (PsiSynchronizedStatement)statement;
+      return blockAssignsVariableOrFails(synchronizedStatement.getBody(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiBlockStatement) {
-      final PsiBlockStatement blockStatement =
-        (PsiBlockStatement)statement;
-      final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
-      return blockAssignsVariableOrFails(codeBlock, variable,
-                                         checkedMethods, strict);
+      final PsiBlockStatement blockStatement = (PsiBlockStatement)statement;
+      return blockAssignsVariableOrFails(blockStatement.getCodeBlock(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiLabeledStatement) {
-      final PsiLabeledStatement labeledStatement =
-        (PsiLabeledStatement)statement;
-      final PsiStatement statementLabeled =
-        labeledStatement.getStatement();
-      return statementAssignsVariableOrFails(statementLabeled, variable,
-                                             checkedMethods, strict);
+      final PsiLabeledStatement labeledStatement = (PsiLabeledStatement)statement;
+      return statementAssignsVariableOrFails(labeledStatement.getStatement(), variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiIfStatement) {
       final PsiIfStatement ifStatement = (PsiIfStatement)statement;
-      return ifStatementAssignsVariableOrFails(ifStatement, variable,
-                                               checkedMethods, strict);
+      return ifStatementAssignsVariableOrFails(ifStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiTryStatement) {
       final PsiTryStatement tryStatement = (PsiTryStatement)statement;
-      return tryStatementAssignsVariableOrFails(tryStatement, variable,
-                                                checkedMethods, strict);
+      return tryStatementAssignsVariableOrFails(tryStatement, variable, checkedMethods, strict);
     }
     else if (statement instanceof PsiSwitchStatement) {
-      final PsiSwitchStatement switchStatement =
-        (PsiSwitchStatement)statement;
-      return switchStatementAssignsVariableOrFails(switchStatement,
-                                                   variable, checkedMethods, strict);
+      final PsiSwitchStatement switchStatement = (PsiSwitchStatement)statement;
+      return switchStatementAssignsVariableOrFails(switchStatement, variable, checkedMethods, strict);
     }
     else {
       // unknown statement type
@@ -209,21 +156,15 @@
     }
   }
 
-  public static boolean switchStatementAssignsVariableOrFails(
-    @NotNull PsiSwitchStatement switchStatement,
-    @NotNull PsiVariable variable,
-    boolean strict) {
-    return switchStatementAssignsVariableOrFails(switchStatement, variable,
-                                                 new HashSet(), strict);
+  public static boolean switchStatementAssignsVariableOrFails(@NotNull PsiSwitchStatement switchStatement, @NotNull PsiVariable variable,
+                                                              boolean strict) {
+    return switchStatementAssignsVariableOrFails(switchStatement, variable, new HashSet(), strict);
   }
 
-  private static boolean switchStatementAssignsVariableOrFails(
-    @NotNull PsiSwitchStatement switchStatement,
-    @NotNull PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+  private static boolean switchStatementAssignsVariableOrFails(@NotNull PsiSwitchStatement switchStatement, @NotNull PsiVariable variable,
+                                                               @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     final PsiExpression expression = switchStatement.getExpression();
-    if (expressionAssignsVariableOrFails(expression, variable,
-                                         checkedMethods, strict)) {
+    if (expressionAssignsVariableOrFails(expression, variable, checkedMethods, strict)) {
       return true;
     }
     final PsiCodeBlock body = switchStatement.getBody();
@@ -236,8 +177,7 @@
     for (int i = 0; i < statements.length; i++) {
       final PsiStatement statement = statements[i];
       if (statement instanceof PsiSwitchLabelStatement) {
-        final PsiSwitchLabelStatement labelStatement
-          = (PsiSwitchLabelStatement)statement;
+        final PsiSwitchLabelStatement labelStatement = (PsiSwitchLabelStatement)statement;
         if (i == statements.length - 1) {
           return false;
         }
@@ -247,8 +187,7 @@
         assigns = false;
       }
       else if (statement instanceof PsiBreakStatement) {
-        final PsiBreakStatement breakStatement
-          = (PsiBreakStatement)statement;
+        final PsiBreakStatement breakStatement = (PsiBreakStatement)statement;
         if (breakStatement.getLabelIdentifier() != null) {
           return false;
         }
@@ -258,8 +197,7 @@
         assigns = false;
       }
       else {
-        assigns |= statementAssignsVariableOrFails(statement, variable,
-                                                   checkedMethods, strict);
+        assigns |= statementAssignsVariableOrFails(statement, variable, checkedMethods, strict);
         if (i == statements.length - 1 && !assigns) {
           return false;
         }
@@ -268,18 +206,13 @@
     return containsDefault;
   }
 
-  private static boolean declarationStatementAssignsVariableOrFails(
-    PsiDeclarationStatement declarationStatement, PsiVariable variable,
-    Set<MethodSignature> checkedMethods, boolean strict) {
-    final PsiElement[] elements =
-      declarationStatement.getDeclaredElements();
+  private static boolean declarationStatementAssignsVariableOrFails(PsiDeclarationStatement declarationStatement, PsiVariable variable,
+                                                                    Set<MethodSignature> checkedMethods, boolean strict) {
+    final PsiElement[] elements = declarationStatement.getDeclaredElements();
     for (PsiElement element : elements) {
       if (element instanceof PsiVariable) {
         final PsiVariable declaredVariable = (PsiVariable)element;
-        final PsiExpression initializer =
-          declaredVariable.getInitializer();
-        if (expressionAssignsVariableOrFails(initializer, variable,
-                                             checkedMethods, strict)) {
+        if (expressionAssignsVariableOrFails(declaredVariable.getInitializer(), variable, checkedMethods, strict)) {
           return true;
         }
       }
@@ -291,16 +224,14 @@
                                                             @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     final PsiResourceList resourceList = tryStatement.getResourceList();
     if (resourceList != null) {
-      final List<PsiResourceVariable> resourceVariables = resourceList.getResourceVariables();
-      for (PsiResourceVariable resourceVariable : resourceVariables) {
+      for (PsiResourceVariable resourceVariable : resourceList.getResourceVariables()) {
         final PsiExpression initializer = resourceVariable.getInitializer();
         if (expressionAssignsVariableOrFails(initializer, variable, checkedMethods, strict)) {
           return true;
         }
       }
     }
-    final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
-    boolean initializedInTryAndCatch = blockAssignsVariableOrFails(tryBlock, variable, checkedMethods, strict);
+    boolean initializedInTryAndCatch = blockAssignsVariableOrFails(tryStatement.getTryBlock(), variable, checkedMethods, strict);
     final PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
     for (final PsiCodeBlock catchBlock : catchBlocks) {
       if (strict) {
@@ -310,101 +241,71 @@
         initializedInTryAndCatch &= blockAssignsVariableOrFails(catchBlock, variable, checkedMethods, strict);
       }
     }
-    if (initializedInTryAndCatch) {
-      return true;
-    }
-    final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
-    return blockAssignsVariableOrFails(finallyBlock, variable, checkedMethods, strict);
+    return initializedInTryAndCatch || blockAssignsVariableOrFails(tryStatement.getFinallyBlock(), variable, checkedMethods, strict);
   }
 
-  private static boolean ifStatementAssignsVariableOrFails(
-    @NotNull PsiIfStatement ifStatement,
-    PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods,
-    boolean strict) {
+  private static boolean ifStatementAssignsVariableOrFails(@NotNull PsiIfStatement ifStatement, PsiVariable variable,
+                                                           @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     final PsiExpression condition = ifStatement.getCondition();
-    if (expressionAssignsVariableOrFails(condition, variable,
-                                         checkedMethods, strict)) {
+    if (expressionAssignsVariableOrFails(condition, variable, checkedMethods, strict)) {
       return true;
     }
     final PsiStatement thenBranch = ifStatement.getThenBranch();
-    final PsiStatement elseBranch = ifStatement.getElseBranch();
     if (BoolUtils.isTrue(condition)) {
-      return statementAssignsVariableOrFails(thenBranch, variable,
-                                             checkedMethods, strict);
+      return statementAssignsVariableOrFails(thenBranch, variable, checkedMethods, strict);
     }
-    else if (BoolUtils.isFalse(condition)) {
-      return statementAssignsVariableOrFails(elseBranch, variable,
-                                             checkedMethods, strict);
+    final PsiStatement elseBranch = ifStatement.getElseBranch();
+    if (BoolUtils.isFalse(condition)) {
+      return statementAssignsVariableOrFails(elseBranch, variable, checkedMethods, strict);
     }
-    return statementAssignsVariableOrFails(thenBranch, variable,
-                                           checkedMethods, strict) &&
-           statementAssignsVariableOrFails(elseBranch, variable,
-                                           checkedMethods, strict);
+    return statementAssignsVariableOrFails(thenBranch, variable, checkedMethods, strict) &&
+           statementAssignsVariableOrFails(elseBranch, variable, checkedMethods, strict);
   }
 
-  private static boolean doWhileAssignsVariableOrFails(
-    @NotNull PsiDoWhileStatement doWhileStatement,
-    PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods,
-    boolean strict) {
-    final PsiExpression condition = doWhileStatement.getCondition();
-    final PsiStatement body = doWhileStatement.getBody();
-    return expressionAssignsVariableOrFails(condition, variable,
-                                            checkedMethods, strict) ||
-           statementAssignsVariableOrFails(body, variable, checkedMethods,
-                                           strict);
+  private static boolean doWhileAssignsVariableOrFails(@NotNull PsiDoWhileStatement doWhileStatement, PsiVariable variable,
+                                                       @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+    return statementAssignsVariableOrFails(doWhileStatement.getBody(), variable, checkedMethods, strict) ||
+           expressionAssignsVariableOrFails(doWhileStatement.getCondition(), variable, checkedMethods, strict);
   }
 
-  private static boolean whileStatementAssignsVariableOrFails(
-    @NotNull PsiWhileStatement whileStatement, PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods,
-    boolean strict) {
+  private static boolean whileStatementAssignsVariableOrFails(@NotNull PsiWhileStatement whileStatement, PsiVariable variable,
+                                                              @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     final PsiExpression condition = whileStatement.getCondition();
-    if (expressionAssignsVariableOrFails(condition, variable,
-                                         checkedMethods, strict)) {
+    if (expressionAssignsVariableOrFails(condition, variable, checkedMethods, strict)) {
       return true;
     }
     if (BoolUtils.isTrue(condition)) {
       final PsiStatement body = whileStatement.getBody();
-      if (statementAssignsVariableOrFails(body, variable, checkedMethods,
-                                          strict)) {
+      if (statementAssignsVariableOrFails(body, variable, checkedMethods, strict)) {
         return true;
       }
     }
     return false;
   }
 
-  private static boolean forStatementAssignsVariableOrFails(
-    @NotNull PsiForStatement forStatement, PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
-    final PsiStatement initialization = forStatement.getInitialization();
-    if (statementAssignsVariableOrFails(initialization, variable,
-                                        checkedMethods, strict)) {
+  private static boolean forStatementAssignsVariableOrFails(@NotNull PsiForStatement forStatement, PsiVariable variable,
+                                                            @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+    if (statementAssignsVariableOrFails(forStatement.getInitialization(), variable, checkedMethods, strict)) {
       return true;
     }
-    final PsiExpression test = forStatement.getCondition();
-    if (expressionAssignsVariableOrFails(test, variable, checkedMethods,
-                                         strict)) {
+    final PsiExpression condition = forStatement.getCondition();
+    if (expressionAssignsVariableOrFails(condition, variable, checkedMethods, strict)) {
       return true;
     }
-    if (BoolUtils.isTrue(test)) {
-      final PsiStatement body = forStatement.getBody();
-      if (statementAssignsVariableOrFails(body, variable, checkedMethods,
-                                          strict)) {
+    if (BoolUtils.isTrue(condition)) {
+      if (statementAssignsVariableOrFails(forStatement.getBody(), variable, checkedMethods, strict)) {
         return true;
       }
-      final PsiStatement update = forStatement.getUpdate();
-      if (statementAssignsVariableOrFails(update, variable,
-                                          checkedMethods, strict)) {
+      if (statementAssignsVariableOrFails(forStatement.getUpdate(), variable, checkedMethods, strict)) {
         return true;
       }
     }
     return false;
   }
 
-  private static boolean foreachStatementAssignsVariableOrFails(PsiVariable field, PsiForeachStatement forStatement) {
-    return false;
+  private static boolean foreachStatementAssignsVariableOrFails(@NotNull PsiForeachStatement foreachStatement, PsiVariable field,
+                                                                @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+    return expressionAssignsVariableOrFails(foreachStatement.getIteratedValue(), field, checkedMethods, strict);
   }
 
   private static boolean expressionAssignsVariableOrFails(@Nullable PsiExpression expression, PsiVariable variable,
@@ -421,8 +322,7 @@
     }
     else if (expression instanceof PsiParenthesizedExpression) {
       final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
-      final PsiExpression unparenthesizedExpression = parenthesizedExpression.getExpression();
-      return expressionAssignsVariableOrFails(unparenthesizedExpression, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(parenthesizedExpression.getExpression(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiMethodCallExpression) {
       final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
@@ -434,8 +334,7 @@
     }
     else if (expression instanceof PsiArrayInitializerExpression) {
       final PsiArrayInitializerExpression array = (PsiArrayInitializerExpression)expression;
-      final PsiExpression[] initializers = array.getInitializers();
-      for (final PsiExpression initializer : initializers) {
+      for (final PsiExpression initializer : array.getInitializers()) {
         if (expressionAssignsVariableOrFails(initializer, variable, checkedMethods, strict)) {
           return true;
         }
@@ -444,30 +343,24 @@
     }
     else if (expression instanceof PsiTypeCastExpression) {
       final PsiTypeCastExpression typeCast = (PsiTypeCastExpression)expression;
-      final PsiExpression operand = typeCast.getOperand();
-      return expressionAssignsVariableOrFails(operand, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(typeCast.getOperand(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiArrayAccessExpression) {
       final PsiArrayAccessExpression accessExpression = (PsiArrayAccessExpression)expression;
-      final PsiExpression arrayExpression = accessExpression.getArrayExpression();
-      final PsiExpression indexExpression = accessExpression.getIndexExpression();
-      return expressionAssignsVariableOrFails(arrayExpression, variable, checkedMethods, strict) ||
-             expressionAssignsVariableOrFails(indexExpression, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(accessExpression.getArrayExpression(), variable, checkedMethods, strict) ||
+             expressionAssignsVariableOrFails(accessExpression.getIndexExpression(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiPrefixExpression) {
       final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
-      final PsiExpression operand = prefixExpression.getOperand();
-      return expressionAssignsVariableOrFails(operand, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(prefixExpression.getOperand(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiPostfixExpression) {
       final PsiPostfixExpression postfixExpression = (PsiPostfixExpression)expression;
-      final PsiExpression operand = postfixExpression.getOperand();
-      return expressionAssignsVariableOrFails(operand, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(postfixExpression.getOperand(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiPolyadicExpression) {
       final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
-      final PsiExpression[] operands = polyadicExpression.getOperands();
-      for (PsiExpression operand : operands) {
+      for (PsiExpression operand : polyadicExpression.getOperands()) {
         if (expressionAssignsVariableOrFails(operand, variable, checkedMethods, strict)) {
           return true;
         }
@@ -476,14 +369,11 @@
     }
     else if (expression instanceof PsiConditionalExpression) {
       final PsiConditionalExpression conditional = (PsiConditionalExpression)expression;
-      final PsiExpression condition = conditional.getCondition();
-      if (expressionAssignsVariableOrFails(condition, variable, checkedMethods, strict)) {
+      if (expressionAssignsVariableOrFails(conditional.getCondition(), variable, checkedMethods, strict)) {
         return true;
       }
-      final PsiExpression thenExpression = conditional.getThenExpression();
-      final PsiExpression elseExpression = conditional.getElseExpression();
-      return expressionAssignsVariableOrFails(thenExpression, variable, checkedMethods, strict) &&
-             expressionAssignsVariableOrFails(elseExpression, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(conditional.getThenExpression(), variable, checkedMethods, strict) &&
+             expressionAssignsVariableOrFails(conditional.getElseExpression(), variable, checkedMethods, strict);
     }
     else if (expression instanceof PsiAssignmentExpression) {
       final PsiAssignmentExpression assignment = (PsiAssignmentExpression)expression;
@@ -491,13 +381,12 @@
       if (expressionAssignsVariableOrFails(lhs, variable, checkedMethods, strict)) {
         return true;
       }
-      final PsiExpression rhs = assignment.getRExpression();
-      if (expressionAssignsVariableOrFails(rhs, variable, checkedMethods, strict)) {
+      if (expressionAssignsVariableOrFails(assignment.getRExpression(), variable, checkedMethods, strict)) {
         return true;
       }
       if (lhs instanceof PsiReferenceExpression) {
         final PsiElement element = ((PsiReference)lhs).resolve();
-        if (element != null && element.equals(variable)) {
+        if (variable.equals(element)) {
           return true;
         }
       }
@@ -505,85 +394,64 @@
     }
     else if (expression instanceof PsiInstanceOfExpression) {
       final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression)expression;
-      final PsiExpression operand = instanceOfExpression.getOperand();
-      return expressionAssignsVariableOrFails(operand, variable, checkedMethods, strict);
+      return expressionAssignsVariableOrFails(instanceOfExpression.getOperand(), variable, checkedMethods, strict);
     }
     else {
       return false;
     }
   }
 
-  private static boolean newExpressionAssignsVariableOrFails(
-    @NotNull PsiNewExpression newExpression, PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+  private static boolean newExpressionAssignsVariableOrFails(@NotNull PsiNewExpression newExpression, PsiVariable variable,
+                                                             @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
     final PsiExpressionList argumentList = newExpression.getArgumentList();
     if (argumentList != null) {
-      final PsiExpression[] args = argumentList.getExpressions();
-      for (final PsiExpression arg : args) {
-        if (expressionAssignsVariableOrFails(arg, variable,
-                                             checkedMethods, strict)) {
+      for (final PsiExpression argument : argumentList.getExpressions()) {
+        if (expressionAssignsVariableOrFails(argument, variable, checkedMethods, strict)) {
           return true;
         }
       }
     }
-    final PsiArrayInitializerExpression arrayInitializer =
-      newExpression.getArrayInitializer();
-    if (expressionAssignsVariableOrFails(arrayInitializer, variable,
-                                         checkedMethods, strict)) {
+    if (expressionAssignsVariableOrFails(newExpression.getArrayInitializer(), variable, checkedMethods, strict)) {
       return true;
     }
-    final PsiExpression[] arrayDimensions =
-      newExpression.getArrayDimensions();
-    for (final PsiExpression dim : arrayDimensions) {
-      if (expressionAssignsVariableOrFails(dim, variable,
-                                           checkedMethods, strict)) {
+    for (final PsiExpression dimension : newExpression.getArrayDimensions()) {
+      if (expressionAssignsVariableOrFails(dimension, variable, checkedMethods, strict)) {
         return true;
       }
     }
     return false;
   }
 
-  private static boolean methodCallAssignsVariableOrFails(
-    @NotNull PsiMethodCallExpression callExpression,
-    PsiVariable variable,
-    @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
-    final PsiExpressionList argList = callExpression.getArgumentList();
-    final PsiExpression[] args = argList.getExpressions();
-    for (final PsiExpression arg : args) {
-      if (expressionAssignsVariableOrFails(arg, variable, checkedMethods,
-                                           strict)) {
+  private static boolean methodCallAssignsVariableOrFails(@NotNull PsiMethodCallExpression callExpression, PsiVariable variable,
+                                                          @NotNull Set<MethodSignature> checkedMethods, boolean strict) {
+    final PsiExpressionList argumentList = callExpression.getArgumentList();
+    for (final PsiExpression argument : argumentList.getExpressions()) {
+      if (expressionAssignsVariableOrFails(argument, variable, checkedMethods, strict)) {
         return true;
       }
     }
-    final PsiReferenceExpression methodExpression =
-      callExpression.getMethodExpression();
-    if (expressionAssignsVariableOrFails(methodExpression, variable,
-                                         checkedMethods, strict)) {
+    if (expressionAssignsVariableOrFails(callExpression.getMethodExpression(), variable, checkedMethods, strict)) {
       return true;
     }
     final PsiMethod method = callExpression.resolveMethod();
     if (method == null) {
       return false;
     }
-    final MethodSignature methodSignature =
-      method.getSignature(PsiSubstitutor.EMPTY);
+    final MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
     if (!checkedMethods.add(methodSignature)) {
       return false;
     }
-    final PsiClass containingClass =
-      ClassUtils.getContainingClass(callExpression);
+    final PsiClass containingClass = ClassUtils.getContainingClass(callExpression);
     final PsiClass calledClass = method.getContainingClass();
     if (calledClass == null || !calledClass.equals(containingClass)) {
       return false;
     }
     if (method.hasModifierProperty(PsiModifier.STATIC)
-        || method.isConstructor()
         || method.hasModifierProperty(PsiModifier.PRIVATE)
         || method.hasModifierProperty(PsiModifier.FINAL)
+        || method.isConstructor()
         || calledClass.hasModifierProperty(PsiModifier.FINAL)) {
-      final PsiCodeBlock body = method.getBody();
-      return blockAssignsVariableOrFails(body, variable,
-                                         checkedMethods, strict);
+      return blockAssignsVariableOrFails(method.getBody(), variable, checkedMethods, strict);
     }
     return false;
   }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/DesignForExtensionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/DesignForExtensionInspection.java
index 7df6ad2..5a90d4b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/DesignForExtensionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/DesignForExtensionInspection.java
@@ -20,7 +20,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class DesignForExtensionInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/EmptySynchronizedStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/EmptySynchronizedStatementInspection.java
index 43060f7..4a9e0f1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/EmptySynchronizedStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/EmptySynchronizedStatementInspection.java
@@ -21,7 +21,7 @@
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class EmptySynchronizedStatementInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java
new file mode 100644
index 0000000..4f657fd
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/MalformedFormatStringInspection.java
@@ -0,0 +1,45 @@
+/*
+ * 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.siyeh.ig.bugs;
+
+import com.intellij.codeInspection.ui.ListTable;
+import com.intellij.codeInspection.ui.ListWrappingTableModel;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.ui.UiUtils;
+
+import javax.swing.*;
+
+public class MalformedFormatStringInspection extends MalformedFormatStringInspectionBase {
+  @Override
+  public JComponent createOptionsPanel() {
+    ListWrappingTableModel classTableModel =
+      new ListWrappingTableModel(classNames, InspectionGadgetsBundle.message("string.format.class.column.name"));
+    JPanel classChooserPanel = UiUtils
+      .createAddRemoveTreeClassChooserPanel(new ListTable(classTableModel), InspectionGadgetsBundle.message("string.format.choose.class"));
+
+    ListWrappingTableModel methodTableModel =
+      new ListWrappingTableModel(methodNames, InspectionGadgetsBundle.message("string.format.class.method.name"));
+    JPanel methodPanel = UiUtils.createAddRemovePanel(new ListTable(methodTableModel));
+
+    final JPanel panel = new JPanel();
+    BoxLayout boxLayout = new BoxLayout(panel, BoxLayout.Y_AXIS);
+    panel.setLayout(boxLayout);
+
+    panel.add(classChooserPanel);
+    panel.add(methodPanel);
+    return panel;
+  }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassInTopLevelPackageInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassInTopLevelPackageInspection.java
index 9b5861c..9b52019 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassInTopLevelPackageInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassInTopLevelPackageInspection.java
@@ -24,7 +24,7 @@
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.MoveClassFix;
 import com.siyeh.ig.psiutils.ClassUtils;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class ClassInTopLevelPackageInspection extends BaseInspection {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassNameDiffersFromFileNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassNameDiffersFromFileNameInspection.java
index cd7c3c0..9866dc6 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassNameDiffersFromFileNameInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ClassNameDiffersFromFileNameInspection.java
@@ -23,7 +23,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.RenameFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/EmptyClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/EmptyClassInspection.java
index 85b42f1e..85a6dff 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/EmptyClassInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/EmptyClassInspection.java
@@ -25,7 +25,7 @@
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.fixes.AddToIgnoreIfAnnotatedByListQuickFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ig.ui.ExternalizableStringSet;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
index 98357a2..5ce1f40 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
@@ -133,10 +133,8 @@
       super.visitMethod(method);
       if (ignoreTestCases) {
         final PsiClass containingClass = method.getContainingClass();
-        if (containingClass != null && TestFrameworks.getInstance().isTestClass(containingClass)) {
-          return;
-        }
-        if (TestUtils.isJUnitTestMethod(method)) {
+        final TestFrameworks testFrameworks = TestFrameworks.getInstance();
+        if (containingClass != null && testFrameworks.isTestOrConfig(containingClass)) {
           return;
         }
       }
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
index 5defb34..e2a88f3 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
@@ -28,7 +28,7 @@
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ig.psiutils.StringUtils;
 import com.siyeh.ig.psiutils.TestUtils;
 import com.siyeh.ig.ui.UiUtils;
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java
index 4835464..dc58029 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java
@@ -27,4 +27,15 @@
     public void outOfMemory() {
         String.format("%2147483640$s", "s");
     }
+
+    public void optionalSettings() {
+        SomeOtherLogger logger = new SomeOtherLogger();
+        logger.d("%s %s", 1); // this is invalid according to the inspector (correct)
+    }
+
+    public class SomeOtherLogger {
+        public void d(String message, Object...args) {
+            // Do some logging.
+        }
+    }
 }
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml
index 7d528e9..494e160 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml
@@ -56,10 +56,17 @@
         <description>Too few arguments for format string &quot;%s %s&quot; + &quot;hmm&quot; #loc</description>
     </problem>
 
-  <problem>
-    <file>MalformedFormatString.java</file>
-    <line>28</line>
-    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Malformed format string</problem_class>
-    <description>Too few arguments for format string &quot;%2147483640$s&quot; #loc</description>
-  </problem>
+    <problem>
+        <file>MalformedFormatString.java</file>
+        <line>28</line>
+        <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Malformed format string</problem_class>
+        <description>Too few arguments for format string &quot;%2147483640$s&quot; #loc</description>
+    </problem>
+
+    <problem>
+        <file>MalformedFormatString.java</file>
+        <line>33</line>
+        <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Malformed format string</problem_class>
+        <description>Too few arguments for format string &quot;%s %s&quot; #loc</description>
+    </problem>
 </problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/field/InstanceVariableInitialization.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/field/InstanceVariableInitialization.java
index 7973f52..e5ce636 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/field/InstanceVariableInitialization.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/field/InstanceVariableInitialization.java
@@ -93,4 +93,10 @@
   C() {
     boolean b = (o = "") instanceof String;
   }
+}
+class D {
+  private java.util.List l;
+  D() {
+    for (Object o : l = new java.util.ArrayList()) {}
+  }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java
index 769a5fd..6d0149c 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java
@@ -5,7 +5,10 @@
 public class MalformedFormatStringInspectionTest extends IGInspectionTestCase {
 
   public void test() throws Exception {
-    doTest("com/siyeh/igtest/bugs/malformed_format_string",
-           new MalformedFormatStringInspection());
+    MalformedFormatStringInspection inspection = new MalformedFormatStringInspection();
+    inspection.classNames.add("com.siyeh.igtest.bugs.malformed_format_string.MalformedFormatString.SomeOtherLogger");
+    inspection.methodNames.add("d");
+
+    doTest("com/siyeh/igtest/bugs/malformed_format_string", inspection);
   }
 }
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
index b977e1c..e07e0df 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
@@ -17,7 +17,7 @@
 
 import com.intellij.psi.*;
 import com.intellij.util.IncorrectOperationException;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ipp.base.PsiElementPredicate;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfPredicate.java
index 5fe305e..597d95c4 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfPredicate.java
@@ -17,7 +17,7 @@
 
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
-import com.siyeh.ig.psiutils.FileTypeUtils;
+import com.intellij.psi.util.FileTypeUtils;
 import com.siyeh.ipp.base.PsiElementPredicate;
 
 class ReplaceConditionalWithIfPredicate implements PsiElementPredicate {
diff --git a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
index eec055f..a76c166 100644
--- a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
+++ b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
@@ -41,6 +41,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.devkit.dom.*;
 
+import java.lang.annotation.Annotation;
 import java.util.*;
 
 /**
@@ -48,16 +49,70 @@
  */
 public class ExtensionDomExtender extends DomExtender<Extensions> {
   private static final PsiClassConverter CLASS_CONVERTER = new PluginPsiClassConverter();
+
+  private static class MyRequired implements Required {
+    @Override
+    public boolean value() {
+      return true;
+    }
+
+    @Override
+    public boolean nonEmpty() {
+      return true;
+    }
+
+    @Override
+    public boolean identifier() {
+      return false;
+    }
+
+    @Override
+    public Class<? extends Annotation> annotationType() {
+      return Required.class;
+    }
+  }
+
+  private static class MyExtendClass extends ExtendClassImpl {
+    private final String myInterfaceName;
+
+    private MyExtendClass(String interfaceName) {
+      myInterfaceName = interfaceName;
+    }
+
+    @Override
+    public boolean allowAbstract() {
+      return false;
+    }
+
+    @Override
+    public boolean allowInterface() {
+      return false;
+    }
+
+    @Override
+    public boolean allowEnum() {
+      return false;
+    }
+
+    @Override
+    public String value() {
+      return myInterfaceName;
+    }
+  }
+
   private static final DomExtender EXTENSION_EXTENDER = new DomExtender() {
     public void registerExtensions(@NotNull final DomElement domElement, @NotNull final DomExtensionsRegistrar registrar) {
       final ExtensionPoint extensionPoint = (ExtensionPoint)domElement.getChildDescription().getDomDeclaration();
       assert extensionPoint != null;
 
-      String interfaceName = extensionPoint.getInterface().getStringValue();
+      final String interfaceName = extensionPoint.getInterface().getStringValue();
       final Project project = extensionPoint.getManager().getProject();
 
       if (interfaceName != null) {
-        registrar.registerGenericAttributeValueChildExtension(new XmlName("implementation"), PsiClass.class).setConverter(CLASS_CONVERTER);
+        registrar.registerGenericAttributeValueChildExtension(new XmlName("implementation"), PsiClass.class)
+          .setConverter(CLASS_CONVERTER)
+          .addCustomAnnotation(new MyExtendClass(interfaceName))
+          .addCustomAnnotation(new MyRequired());
         registerXmlb(registrar, JavaPsiFacade.getInstance(project).findClass(interfaceName, GlobalSearchScope.allScope(project)),
                      Collections.<With>emptyList());
       }
diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java
index 6b40ced..a958af1 100644
--- a/plugins/devkit/src/projectRoots/IdeaJdk.java
+++ b/plugins/devkit/src/projectRoots/IdeaJdk.java
@@ -121,7 +121,7 @@
   }
 
   @Nullable
-  public final String getVersionString(final Sdk sdk) {
+  public final String getVersionString(@NotNull final Sdk sdk) {
     final Sdk internalJavaSdk = getInternalJavaSdk(sdk);
     return internalJavaSdk != null ? internalJavaSdk.getVersionString() : null;
   }
@@ -401,13 +401,13 @@
   }
 
   @Nullable
-  public String getBinPath(Sdk sdk) {
+  public String getBinPath(@NotNull Sdk sdk) {
     final Sdk internalJavaSdk = getInternalJavaSdk(sdk);
     return internalJavaSdk == null ? null : JavaSdk.getInstance().getBinPath(internalJavaSdk);
   }
 
   @Nullable
-  public String getToolsPath(Sdk sdk) {
+  public String getToolsPath(@NotNull Sdk sdk) {
     final Sdk jdk = getInternalJavaSdk(sdk);
     if (jdk != null && jdk.getVersionString() != null){
       return JavaSdk.getInstance().getToolsPath(jdk);
@@ -416,12 +416,12 @@
   }
 
   @Nullable
-  public String getVMExecutablePath(Sdk sdk) {
+  public String getVMExecutablePath(@NotNull Sdk sdk) {
     final Sdk internalJavaSdk = getInternalJavaSdk(sdk);
     return internalJavaSdk == null ? null : JavaSdk.getInstance().getVMExecutablePath(internalJavaSdk);
   }
 
-  public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
+  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
     if (additionalData instanceof Sandbox) {
       try {
         ((Sandbox)additionalData).writeExternal(additional);
@@ -432,7 +432,7 @@
     }
   }
 
-  public SdkAdditionalData loadAdditionalData(Sdk sdk, Element additional) {
+  public SdkAdditionalData loadAdditionalData(@NotNull Sdk sdk, Element additional) {
     Sandbox sandbox = new Sandbox(sdk);
     try {
       sandbox.readExternal(additional);
diff --git a/plugins/devkit/testData/codeInsight/ExtensionQualifiedName.xml b/plugins/devkit/testData/codeInsight/ExtensionQualifiedName.xml
index e74bde4..d5b03f8 100644
--- a/plugins/devkit/testData/codeInsight/ExtensionQualifiedName.xml
+++ b/plugins/devkit/testData/codeInsight/ExtensionQualifiedName.xml
@@ -6,7 +6,12 @@
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij.myPlugin">
-    <ext implementation="java.lang.Runnable"/>
+    <<error descr="'implementation' attribute should be defined">ext</error>/>
+    <ext implementation="<error descr="Interface not allowed">java.lang.Runnable</error>"/>
+    <ext implementation="<error descr="'java.util.concurrent.TimeUnit' is not assignable to 'java.lang.Runnable'"><error descr="Enum not allowed">java.util.concurrent.TimeUnit</error></error>"/>
+    <ext implementation="<error descr="'java.lang.String' is not assignable to 'java.lang.Runnable'">java.lang.String</error>"/>
+
+    <ext implementation="foo.MyRunnable"/>
   </extensions>
 
 </idea-plugin>
\ No newline at end of file
diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
index 52c7857..1ba75d4 100644
--- a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
+++ b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
@@ -117,6 +117,7 @@
   }
 
   public void testExtensionQualifiedName() throws Throwable {
+    myFixture.addClass("package foo; public class MyRunnable implements java.lang.Runnable {}");
     configureByFile();
     myFixture.checkHighlighting(false, false, false);
   }
diff --git a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
index 6cef328..873b395 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
@@ -133,8 +133,7 @@
       return;
     }
     entire.append(text);
-    if (suppressed || myVcs == null) {
-      LOG.debug(text);
+    if (myVcs == null || (suppressed && !LOG.isDebugEnabled())) {
       return;
     }
     int last = lineRest.length() > 0 ? lineRest.charAt(lineRest.length() - 1) : -1;
@@ -158,13 +157,19 @@
           else {
             line = text.substring(start, savedPos);
           }
-          if (ProcessOutputTypes.STDOUT == outputType && !StringUtil.isEmptyOrSpaces(line)) {
-            myVcs.showMessages(line);
-            LOG.info(line.trim());
-          }
-          else if (ProcessOutputTypes.STDERR == outputType && !StringUtil.isEmptyOrSpaces(line)) {
-            myVcs.showErrorMessages(line);
-            LOG.info(line.trim());
+          if (!StringUtil.isEmptyOrSpaces(line)) {
+            if (!suppressed) {
+              LOG.info(line.trim());
+              if (ProcessOutputTypes.STDOUT == outputType) {
+                myVcs.showMessages(line);
+              }
+              else if (ProcessOutputTypes.STDERR == outputType) {
+                myVcs.showErrorMessages(line);
+              }
+            }
+            else {
+              LOG.debug(line.trim());
+            }
           }
         }
         start = savedPos;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
index 2f634d0..9854047 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
@@ -28,6 +28,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
 import org.jetbrains.plugins.github.exceptions.GithubJsonException;
+import org.jetbrains.plugins.github.exceptions.GithubRateLimitExceededException;
 import org.jetbrains.plugins.github.exceptions.GithubStatusCodeException;
 import org.jetbrains.plugins.github.util.GithubAuthData;
 import org.jetbrains.plugins.github.util.GithubSslSupport;
@@ -209,7 +210,11 @@
       case HttpStatus.SC_UNAUTHORIZED:
       case HttpStatus.SC_PAYMENT_REQUIRED:
       case HttpStatus.SC_FORBIDDEN:
-        throw new GithubAuthenticationException("Request response: " + getErrorMessage(method));
+        String message = getErrorMessage(method);
+        if (message.contains("API rate limit exceeded")) {
+          throw new GithubRateLimitExceededException(message);
+        }
+        throw new GithubAuthenticationException("Request response: " + message);
       default:
         throw new GithubStatusCodeException(code + ": " + getErrorMessage(method), code);
     }
@@ -535,11 +540,15 @@
     return createDataFromRaw(fromJson(postRequest(auth, path, gson.toJson(request)), GithubRepoRaw.class), GithubRepo.class);
   }
 
+  /*
+   * Open issues only
+   */
   @NotNull
   public static List<GithubIssue> getIssuesAssigned(@NotNull GithubAuthData auth,
                                                     @NotNull String user,
                                                     @NotNull String repo,
-                                                    @Nullable String assigned) throws IOException {
+                                                    @Nullable String assigned,
+                                                    int max) throws IOException {
     String path;
     if (StringUtil.isEmptyOrSpaces(assigned)) {
       path = "/repos/" + user + "/" + repo + "/issues?" + PER_PAGE;
@@ -550,10 +559,17 @@
 
     PagedRequest<GithubIssue> request = new PagedRequest<GithubIssue>(path, GithubIssue.class, GithubIssueRaw[].class);
 
-    return request.getAll(auth);
+    List<GithubIssue> result = new ArrayList<GithubIssue>();
+    while (request.hasNext() && max > result.size()) {
+      result.addAll(request.next(auth));
+    }
+    return result;
   }
 
   @NotNull
+  /*
+   * All issues - open and closed
+   */
   public static List<GithubIssue> getIssuesQueried(@NotNull GithubAuthData auth,
                                                    @NotNull String user,
                                                    @NotNull String repo,
@@ -601,6 +617,32 @@
   }
 
   @NotNull
+  public static List<GithubCommitComment> getCommitComments(@NotNull GithubAuthData auth,
+                                                            @NotNull String user,
+                                                            @NotNull String repo,
+                                                            @NotNull String sha) throws IOException {
+    String path = "/repos/" + user + "/" + repo + "/commits/" + sha + "/comments";
+
+    PagedRequest<GithubCommitComment> request =
+      new PagedRequest<GithubCommitComment>(path, GithubCommitComment.class, GithubCommitCommentRaw[].class, ACCEPT_HTML_BODY_MARKUP);
+
+    return request.getAll(auth);
+  }
+
+  @NotNull
+  public static List<GithubCommitComment> getPullRequestComments(@NotNull GithubAuthData auth,
+                                                            @NotNull String user,
+                                                            @NotNull String repo,
+                                                            long id) throws IOException {
+    String path = "/repos/" + user + "/" + repo + "/pulls/" + id + "/comments";
+
+    PagedRequest<GithubCommitComment> request =
+      new PagedRequest<GithubCommitComment>(path, GithubCommitComment.class, GithubCommitCommentRaw[].class, ACCEPT_HTML_BODY_MARKUP);
+
+    return request.getAll(auth);
+  }
+
+  @NotNull
   public static GithubPullRequest getPullRequest(@NotNull GithubAuthData auth, @NotNull String user, @NotNull String repo, int id)
     throws IOException {
     String path = "/repos/" + user + "/" + repo + "/pulls/" + id;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitComment.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitComment.java
new file mode 100644
index 0000000..1f13de7
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitComment.java
@@ -0,0 +1,102 @@
+/*
+ * 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 org.jetbrains.plugins.github.api;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Date;
+
+/**
+ * @author Aleksey Pivovarov
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class GithubCommitComment {
+  @NotNull private final String myHtmlUrl;
+
+  private final long myId;
+  @NotNull private final String mySha;
+  @NotNull private final String myPath;
+  private final long myPosition; // line number in diff
+  @NotNull private final String myBodyHtml;
+
+  @NotNull private final GithubUser myUser;
+
+  @NotNull private final Date myCreatedAt;
+  @NotNull private final Date myUpdatedAt;
+
+  public GithubCommitComment(@NotNull String htmlUrl,
+                             long id,
+                             @NotNull String sha,
+                             @NotNull String path,
+                             long position,
+                             @NotNull String bodyHtml,
+                             @NotNull GithubUser user,
+                             @NotNull Date createdAt,
+                             @NotNull Date updatedAt) {
+    myHtmlUrl = htmlUrl;
+    myId = id;
+    mySha = sha;
+    myPath = path;
+    myPosition = position;
+    myBodyHtml = bodyHtml;
+    myUser = user;
+    myCreatedAt = createdAt;
+    myUpdatedAt = updatedAt;
+  }
+
+  @NotNull
+  public String getHtmlUrl() {
+    return myHtmlUrl;
+  }
+
+  public long getId() {
+    return myId;
+  }
+
+  @NotNull
+  public String getSha() {
+    return mySha;
+  }
+
+  @NotNull
+  public String getPath() {
+    return myPath;
+  }
+
+  public long getPosition() {
+    return myPosition;
+  }
+
+  @NotNull
+  public String getBodyHtml() {
+    return myBodyHtml;
+  }
+
+  @NotNull
+  public GithubUser getUser() {
+    return myUser;
+  }
+
+  @NotNull
+  public Date getCreatedAt() {
+    return myCreatedAt;
+  }
+
+  @NotNull
+  public Date getUpdatedAt() {
+    return myUpdatedAt;
+  }
+}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitCommentRaw.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitCommentRaw.java
new file mode 100644
index 0000000..229b31a
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitCommentRaw.java
@@ -0,0 +1,59 @@
+/*
+ * 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 org.jetbrains.plugins.github.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Date;
+
+/**
+ * @author Aleksey Pivovarov
+ */
+class GithubCommitCommentRaw implements DataConstructor {
+  @Nullable public String htmlUrl;
+  @Nullable public String url;
+
+  @Nullable public Long id;
+  @Nullable public String commitId;
+  @Nullable public String path;
+  @Nullable public Long position;
+  @Nullable public Long line;
+  @Nullable public String body;
+  @Nullable public String bodyHtml;
+
+  @Nullable public GithubUserRaw user;
+
+  @Nullable public Date createdAt;
+  @Nullable public Date updatedAt;
+
+  @SuppressWarnings("ConstantConditions")
+  @NotNull
+  public GithubCommitComment createCommitComment() {
+    return new GithubCommitComment(htmlUrl, id, commitId, path, position, bodyHtml, user.createUser(), createdAt, updatedAt);
+  }
+
+  @SuppressWarnings("unchecked")
+  @NotNull
+  @Override
+  public <T> T create(@NotNull Class<T> resultClass) {
+    if (resultClass.isAssignableFrom(GithubCommitComment.class)) {
+      return (T)createCommitComment();
+    }
+
+    throw new ClassCastException(this.getClass().getName() + ": bad class type: " + resultClass.getName());
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubRateLimitExceededException.java
similarity index 65%
copy from plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
copy to plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubRateLimitExceededException.java
index 6830246..66272f4 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnPropDetailsProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubRateLimitExceededException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn.properties;
+package org.jetbrains.plugins.github.exceptions;
+
+import java.io.IOException;
 
 /**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/12/12
- * Time: 8:40 PM
+ * @author Aleksey Pivovarov
  */
-public class SvnPropDetailsProvider {
+public class GithubRateLimitExceededException extends IOException {
+  public GithubRateLimitExceededException(String message) {
+    super(message);
+  }
 }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java
index f4e4554..b975956 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java
@@ -20,6 +20,7 @@
 import org.jetbrains.plugins.github.api.GithubApiUtil;
 import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
 import org.jetbrains.plugins.github.exceptions.GithubJsonException;
+import org.jetbrains.plugins.github.exceptions.GithubRateLimitExceededException;
 import org.jetbrains.plugins.github.exceptions.GithubStatusCodeException;
 import org.jetbrains.plugins.github.util.GithubAuthData;
 import org.jetbrains.plugins.github.util.GithubUtil;
@@ -85,7 +86,10 @@
   @Override
   public Task[] getIssues(@Nullable String query, int max, long since) throws Exception {
     try {
-      return getIssues(query);
+      return getIssues(query, max);
+    }
+    catch (GithubRateLimitExceededException e) {
+      return new Task[0];
     }
     catch (GithubAuthenticationException e) {
       throw new Exception(e.getMessage(), e);
@@ -99,13 +103,13 @@
   }
 
   @NotNull
-  private Task[] getIssues(@Nullable String query) throws Exception {
+  private Task[] getIssues(@Nullable String query, int max) throws Exception {
     List<GithubIssue> issues;
     if (StringUtil.isEmptyOrSpaces(query)) {
       if (StringUtil.isEmptyOrSpaces(myUser)) {
         myUser = GithubApiUtil.getCurrentUser(getAuthData()).getLogin();
       }
-      issues = GithubApiUtil.getIssuesAssigned(getAuthData(), getRepoAuthor(), getRepoName(), myUser);
+      issues = GithubApiUtil.getIssuesAssigned(getAuthData(), getRepoAuthor(), getRepoName(), myUser, max);
     }
     else {
       issues = GithubApiUtil.getIssuesQueried(getAuthData(), getRepoAuthor(), getRepoName(), query);
@@ -266,6 +270,7 @@
 
   public void setToken(@NotNull String token) {
     myToken = token;
+    setUser("");
   }
 
   @Tag("token")
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 2a83c85..c926943 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -65,7 +65,6 @@
     myHost.getDocument().addDocumentListener(buttonUpdater);
     myRepoAuthor.getDocument().addDocumentListener(buttonUpdater);
     myRepoName.getDocument().addDocumentListener(buttonUpdater);
-    myURLText.getDocument().addDocumentListener(buttonUpdater);
   }
 
   @Nullable
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
index b540bd9..b166fce 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
@@ -47,7 +47,9 @@
       </component>
       <component id="5a680" class="com.intellij.openapi.ui.ComboBox" binding="myAuthTypeComboBox">
         <constraints>
-          <grid row="0" column="3" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+          <grid row="0" column="3" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+            <preferred-size width="120" height="-1"/>
+          </grid>
         </constraints>
         <properties/>
       </component>
@@ -143,7 +145,7 @@
           <text value="Test"/>
         </properties>
       </component>
-      <component id="b276a" class="com.intellij.ui.components.JBLabel">
+      <component id="b276a" class="com.intellij.ui.components.JBLabel" binding="myAuthTypeLabel">
         <constraints>
           <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
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 365fa2f..26cbbf6 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -33,6 +33,7 @@
 import org.jetbrains.plugins.github.api.GithubUser;
 
 import javax.swing.*;
+import javax.swing.border.EmptyBorder;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import javax.swing.event.HyperlinkEvent;
@@ -64,6 +65,7 @@
   private JTextField myHostTextField;
   private ComboBox myAuthTypeComboBox;
   private JPanel myCardPanel;
+  private JBLabel myAuthTypeLabel;
 
   private boolean myCredentialsModified;
 
@@ -75,10 +77,10 @@
         BrowserUtil.browse(e.getURL());
       }
     });
-    mySignupTextField.setText(
-      "<html>Do not have an account at github.com? <a href=\"https://github.com\">" + "Sign up" + "</a></html>");
+    mySignupTextField.setText("<html>Do not have an account at github.com? <a href=\"https://github.com\">" + "Sign up" + "</a></html>");
     mySignupTextField.setBackground(myPane.getBackground());
     mySignupTextField.setCursor(new Cursor(Cursor.HAND_CURSOR));
+    myAuthTypeLabel.setBorder(new EmptyBorder(0, 10, 0, 0));
     myAuthTypeComboBox.addItem(AUTH_PASSWORD);
     myAuthTypeComboBox.addItem(AUTH_TOKEN);
 
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistContentTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistContentTest.java
index e5bc04b..f5cae2a 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistContentTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistContentTest.java
@@ -30,9 +30,9 @@
  * @author Aleksey Pivovarov
  */
 public class GithubCreateGistContentTest extends GithubCreateGistTestBase {
+
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
+  protected void beforeTest() throws Exception {
     createProjectFiles();
   }
 
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
index b564267..150e7e8 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
@@ -38,20 +38,14 @@
   protected String GIST_DESCRIPTION;
 
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
+  protected void beforeTest() throws Exception {
     long time = Clock.getTime();
     GIST_DESCRIPTION = getTestName(false) + "_" + DateFormatUtil.formatDate(time);
   }
 
   @Override
-  public void tearDown() throws Exception {
-    try {
-      deleteGist();
-    }
-    finally {
-      super.tearDown();
-    }
+  protected void afterTest() throws Exception {
+    deleteGist();
   }
 
   protected void deleteGist() throws IOException {
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
index 24bb780..9db5ba8 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
@@ -41,9 +41,7 @@
   protected String BRANCH_NAME;
 
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
-
+  protected void beforeTest() throws Exception {
     Random rnd = new Random();
     long time = Clock.getTime();
     BRANCH_NAME = "branch_" + getTestName(false) + "_" + DateFormatUtil.formatDate(time).replace('/', '-') + "_" + rnd.nextLong();
@@ -58,13 +56,8 @@
   }
 
   @Override
-  public void tearDown() throws Exception {
-    try {
-      deleteRemoteBranch();
-    }
-    finally {
-      super.tearDown();
-    }
+  protected void afterTest() throws Exception {
+    deleteRemoteBranch();
   }
 
   protected void deleteRemoteBranch() {
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubIssuesTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubIssuesTest.java
new file mode 100644
index 0000000..1b47169
--- /dev/null
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubIssuesTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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 org.jetbrains.plugins.github;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.plugins.github.api.GithubApiUtil;
+import org.jetbrains.plugins.github.api.GithubIssue;
+import org.jetbrains.plugins.github.test.GithubTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Aleksey Pivovarov
+ */
+public class GithubIssuesTest extends GithubTest {
+  private static final String REPO_NAME = "IssuesTest";
+
+  public void testAssigneeIssues1() throws Exception {
+    List<GithubIssue> result = GithubApiUtil.getIssuesAssigned(myAuth, myLogin2, REPO_NAME, myLogin1, 100);
+    List<Long> issues = ContainerUtil.map(result, new Function<GithubIssue, Long>() {
+      @Override
+      public Long fun(GithubIssue githubIssue) {
+        return githubIssue.getNumber();
+      }
+    });
+
+    List<Long> expected = Arrays.asList(6L, 7L, 8L);
+
+    assertTrue(Comparing.haveEqualElements(issues, expected));
+  }
+
+  public void testAssigneeIssues2() throws Exception {
+    List<GithubIssue> result = GithubApiUtil.getIssuesAssigned(myAuth, myLogin2, REPO_NAME, myLogin2, 100);
+    List<Long> issues = ContainerUtil.map(result, new Function<GithubIssue, Long>() {
+      @Override
+      public Long fun(GithubIssue githubIssue) {
+        return githubIssue.getNumber();
+      }
+    });
+
+    List<Long> expected = Arrays.asList(1L, 2L);
+
+    assertTrue(Comparing.haveEqualElements(issues, expected));
+  }
+
+  public void testAssigneeIssues3() throws Exception {
+    List<GithubIssue> result = GithubApiUtil.getIssuesAssigned(myAuth, myLogin2, REPO_NAME, "", 100);
+    List<Long> issues = ContainerUtil.map(result, new Function<GithubIssue, Long>() {
+      @Override
+      public Long fun(GithubIssue githubIssue) {
+        return githubIssue.getNumber();
+      }
+    });
+
+    List<Long> expected = Arrays.asList(1L, 2L, 5L, 6L, 7L, 8L, 9L, 10L, 11L);
+
+    assertTrue(Comparing.haveEqualElements(issues, expected));
+  }
+
+  public void testQueriedIssues1() throws Exception {
+    List<GithubIssue> result = GithubApiUtil.getIssuesQueried(myAuth, myLogin2, REPO_NAME, "abracadabra");
+    List<Long> issues = ContainerUtil.map(result, new Function<GithubIssue, Long>() {
+      @Override
+      public Long fun(GithubIssue githubIssue) {
+        return githubIssue.getNumber();
+      }
+    });
+
+    List<Long> expected = Arrays.asList(10L, 12L);
+
+    assertContainsElements(issues, expected);
+  }
+
+  public void testQueriedIssues2() throws Exception {
+    List<GithubIssue> result = GithubApiUtil.getIssuesQueried(myAuth, myLogin2, REPO_NAME, "commentary");
+    List<Long> issues = ContainerUtil.map(result, new Function<GithubIssue, Long>() {
+      @Override
+      public Long fun(GithubIssue githubIssue) {
+        return githubIssue.getNumber();
+      }
+    });
+
+    List<Long> expected = Arrays.asList(11L);
+
+    assertContainsElements(issues, expected);
+  }
+}
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
index c72cbc3..4fec0d1c 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
@@ -28,9 +28,9 @@
  * @author Aleksey Pivovarov
  */
 public class GithubRequestPagingTest extends GithubTest {
+
   @Override
-  protected void setUp() throws Exception {
-    super.setUp();
+  protected void beforeTest() throws Exception {
     assumeNotNull(myLogin2);
   }
 
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
index 4eee8e1..5dd9b21 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
@@ -35,9 +35,7 @@
   protected String PROJECT_NAME;
 
   @Override
-  public void setUp() throws Exception {
-    super.setUp();
-
+  protected void beforeTest() throws Exception {
     Random rnd = new Random();
     long time = Clock.getTime();
     PROJECT_NAME = "new_project_from_" + getTestName(false) + "_" + DateFormatUtil.formatDate(time).replace('/', '-') + "_" + rnd.nextLong();
@@ -45,13 +43,8 @@
   }
 
   @Override
-  public void tearDown() throws Exception {
-    try {
-      deleteGithubRepo();
-    }
-    finally {
-      super.tearDown();
-    }
+  protected void afterTest() throws Exception {
+    deleteGithubRepo();
   }
 
   protected void deleteGithubRepo() throws IOException {
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 0f2da38..2c9496e 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
@@ -56,9 +56,11 @@
  * <li>Project base directory is the root of everything. </li>
  * </ul></p>
  * <p>All tests inherited from this class are required to have a login and a password to access the Github server.
- *    They are set up in System properties: <br/>
- *    <code>-Dtest.github.login=mylogin<br/>
- *           -Dtest.github.password=mypassword</code>
+ *    They are set up in Environment variables: <br/>
+ *    <code>idea.test.github.host=myHost<br/>
+ *          idea.test.github.login1=mylogin1<br/> // test user
+ *          idea.test.github.login2=mylogin2<br/> // user with configured test repositories
+ *          idea.test.github.password=mypassword</code> // password for test user
  * </p>
  *
  * @author Kirill Likhodedov
@@ -173,7 +175,7 @@
   }
 
   @Override
-  protected void setUp() throws Exception {
+  protected final void setUp() throws Exception {
     final String host = System.getenv("idea.test.github.host");
     final String login1 = System.getenv("idea.test.github.login1");
     final String login2 = System.getenv("idea.test.github.login2");
@@ -186,8 +188,14 @@
 
     super.setUp();
 
-    myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture();
-    myProjectFixture.setUp();
+    try {
+      myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture();
+      myProjectFixture.setUp();
+    }
+    catch (Exception e) {
+      super.tearDown();
+      throw e;
+    }
 
     myProject = myProjectFixture.getProject();
     myProjectRoot = myProject.getBaseDir();
@@ -209,17 +217,39 @@
     myHttpAuthService = (GitHttpAuthTestService)ServiceManager.getService(GitHttpAuthService.class);
 
     myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
+
+    try {
+      beforeTest();
+    }
+    catch (Exception e) {
+      try {
+        tearDown();
+      }
+      catch (Exception e2) {
+        e2.printStackTrace();
+      }
+      throw e;
+    }
   }
 
   @Override
-  protected void tearDown() throws Exception {
-    myHttpAuthService.cleanup();
-    myDialogManager.cleanup();
-    myNotificator.cleanup();
+  protected final void tearDown() throws Exception {
+    try {
+      afterTest();
+    }
+    finally {
+      myHttpAuthService.cleanup();
+      myDialogManager.cleanup();
+      myNotificator.cleanup();
 
-    myProjectFixture.tearDown();
-    super.tearDown();
+      myProjectFixture.tearDown();
+      super.tearDown();
+    }
   }
 
+  protected void beforeTest() throws Exception {
+  }
 
+  protected void afterTest() throws Exception {
+  }
 }
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java
index 669bc3a..5367556 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java
@@ -111,8 +111,8 @@
 
     initControls();
     content.add(myUseWrapperButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
-    content.add(myUseLocalDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
     content.add(myUseBundledDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
+    content.add(myUseLocalDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
 
     content.add(myGradleHomeLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel));
     content.add(myGradleHomePathField, ExternalSystemUiUtil.getFillLineConstraints(0));
diff --git a/plugins/groovy/jetgroovy.iml b/plugins/groovy/jetgroovy.iml
index d8531ae..bd8506c 100644
--- a/plugins/groovy/jetgroovy.iml
+++ b/plugins/groovy/jetgroovy.iml
@@ -34,6 +34,7 @@
     <orderEntry type="module" module-name="junit" scope="TEST" />
     <orderEntry type="module" module-name="java-indexing-api" />
     <orderEntry type="module" module-name="groovy-jps-plugin" />
+    <orderEntry type="module" module-name="ByteCodeViewer" />
   </component>
 </module>
 
diff --git a/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/after.groovy.template
new file mode 100644
index 0000000..1862911
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/after.groovy.template
@@ -0,0 +1 @@
+<spot>def</spot> list = ['a', 'b', 'c']
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/before.groovy.template
new file mode 100644
index 0000000..9cc469c
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/before.groovy.template
@@ -0,0 +1 @@
+<spot>ArrayList<String></spot> list = ['a', 'b', 'c']
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/description.html b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/description.html
new file mode 100644
index 0000000..f3c976c
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrRemoveExplicitTypeDeclarationIntention/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This intention removes explicit type elements from variables and methods
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index 926402f..1a086861 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -26,6 +26,7 @@
   <depends optional="true" config-file="intellilang-groovy-support.xml">org.intellij.intelliLang</depends>
   <depends optional="true">AntSupport</depends>
   <depends optional="true">cucumber</depends>
+  <depends optional="true">ByteCodeViewer</depends>
 
   <extensionPoints>
     <extensionPoint name="methodComparator" interface="org.jetbrains.plugins.groovy.lang.resolve.GrMethodComparator"/>
@@ -1393,6 +1394,11 @@
       <categoryKey>intention.category.groovy/intention.category.groovy.other</categoryKey>
       <className>org.jetbrains.plugins.groovy.intentions.other.GrCopyStringConcatenationContentIntention</className>
     </intentionAction>
+    <intentionAction>
+      <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
+      <categoryKey>intention.category.groovy/intention.category.groovy.declaration</categoryKey>
+      <className>org.jetbrains.plugins.groovy.intentions.declaration.GrRemoveExplicitTypeDeclarationIntention</className>
+    </intentionAction>
 
     <projectService serviceInterface="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"
                     serviceImplementation="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"/>
@@ -1431,6 +1437,10 @@
     <codeFragmentFactory implementation="org.jetbrains.plugins.groovy.debugger.GroovyCodeFragmentFactory"/>
   </extensions>
 
+  <extensions defaultExtensionNs="ByteCodeViewer">
+    <classSearcher implementation="org.jetbrains.plugins.groovy.byteCodeViewer.GroovyScriptClassSearcher"/>
+  </extensions>
+
   <actions>
     <action id="Groovy.Shell.Execute" class="com.intellij.openapi.actionSystem.EmptyAction" text="Execute Groovy Code"
             description="Execute Groovy code in console">
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/byteCodeViewer/GroovyScriptClassSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/byteCodeViewer/GroovyScriptClassSearcher.java
new file mode 100644
index 0000000..3365dc5
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/byteCodeViewer/GroovyScriptClassSearcher.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.byteCodeViewer;
+
+import com.intellij.byteCodeViewer.ClassSearcher;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiTypeParameter;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+
+/**
+ * Created by Max Medvedev on 8/23/13
+ */
+public class GroovyScriptClassSearcher implements ClassSearcher {
+  @Nullable
+  @Override
+  public PsiClass findClass(@NotNull PsiElement place) {
+    if (place.getLanguage() == GroovyFileType.GROOVY_LANGUAGE) {
+      PsiClass containingClass = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
+      while (containingClass instanceof PsiTypeParameter) {
+        containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class);
+      }
+      if (containingClass != null) return containingClass;
+
+      PsiFile file = place.getContainingFile();
+      if (file instanceof GroovyFile && ((GroovyFile)file).isScript()) {
+        return ((GroovyFile)file).getScriptClass();
+      }
+    }
+    return null;
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java
index 9570fb6..c66b967 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingGettersInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -57,6 +57,7 @@
     return GroovyInspectionBundle.message("getter.0.clashes.with.getter.1", args);
   }
 
+  @NotNull
   @Override
   protected BaseInspectionVisitor buildVisitor() {
     return new BaseInspectionVisitor() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyAnnotationNamingConventionInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyAnnotationNamingConventionInspection.java
index 62b21ed..dfaca8f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyAnnotationNamingConventionInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyAnnotationNamingConventionInspection.java
@@ -20,7 +20,6 @@
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
 import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnnotationTypeDefinition;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 
 public class GroovyAnnotationNamingConventionInspection extends ConventionInspection {
 
@@ -32,7 +31,7 @@
     return "Annotation naming convention";
   }
 
-  protected GroovyFix buildFix(PsiElement location) {
+  protected GroovyFix buildFix(@NotNull PsiElement location) {
     return new RenameFix();
   }
 
@@ -63,18 +62,15 @@
     return DEFAULT_MAX_LENGTH;
   }
 
+  @NotNull
   public BaseInspectionVisitor buildVisitor() {
     return new NamingConventionsVisitor();
   }
 
   private class NamingConventionsVisitor extends BaseInspectionVisitor {
-
-    public void visitTypeDefinition(GrTypeDefinition grTypeDefinition) {
-      super.visitTypeDefinition(grTypeDefinition);
-      if (!(grTypeDefinition instanceof GrAnnotationTypeDefinition)) {
-        return;
-      }
-      final GrAnnotationTypeDefinition aClass = (GrAnnotationTypeDefinition) grTypeDefinition;
+    @Override
+    public void visitAnnotationTypeDefinition(GrAnnotationTypeDefinition aClass) {
+      super.visitAnnotationTypeDefinition(aClass);
 
       final String name = aClass.getName();
       if (name == null) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyClassNamingConventionInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyClassNamingConventionInspection.java
index 66937b0..cc48722 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyClassNamingConventionInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyClassNamingConventionInspection.java
@@ -20,7 +20,6 @@
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
 import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrClassDefinition;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 
 public class GroovyClassNamingConventionInspection extends ConventionInspection {
 
@@ -32,7 +31,7 @@
     return "Class naming convention";
   }
 
-  protected GroovyFix buildFix(PsiElement location) {
+  protected GroovyFix buildFix(@NotNull PsiElement location) {
     return new RenameFix();
   }
 
@@ -63,26 +62,23 @@
     return DEFAULT_MAX_LENGTH;
   }
 
+  @NotNull
   public BaseInspectionVisitor buildVisitor() {
     return new NamingConventionsVisitor();
   }
 
   private class NamingConventionsVisitor extends BaseInspectionVisitor {
-
-    public void visitTypeDefinition(GrTypeDefinition grTypeDefinition) {
-      super.visitTypeDefinition(grTypeDefinition);
-      if (!(grTypeDefinition instanceof GrClassDefinition)) {
-        return;
-      }
-      GrClassDefinition aClass = (GrClassDefinition) grTypeDefinition;
-      final String name = aClass.getName();
+    @Override
+    public void visitClassDefinition(GrClassDefinition classDefinition) {
+      super.visitClassDefinition(classDefinition);
+      final String name = classDefinition.getName();
       if (name == null) {
         return;
       }
       if (isValid(name)) {
         return;
       }
-      registerClassError(aClass, name);
+      registerClassError(classDefinition, name);
     }
   }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyEnumerationNamingConventionInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyEnumerationNamingConventionInspection.java
index a53d2ed..15aa51b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyEnumerationNamingConventionInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyEnumerationNamingConventionInspection.java
@@ -20,7 +20,6 @@
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
 import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 
 public class GroovyEnumerationNamingConventionInspection extends ConventionInspection {
 
@@ -32,7 +31,7 @@
         return "Enumeration naming convention";
     }
 
-    protected GroovyFix buildFix(PsiElement location) {
+    protected GroovyFix buildFix(@NotNull PsiElement location) {
         return new RenameFix();
     }
 
@@ -63,27 +62,24 @@
         return DEFAULT_MAX_LENGTH;
     }
 
+    @NotNull
     public BaseInspectionVisitor buildVisitor() {
         return new NamingConventionsVisitor();
     }
 
     private class NamingConventionsVisitor extends BaseInspectionVisitor {
+      @Override
+      public void visitEnumDefinition(GrEnumTypeDefinition aClass) {
+        super.visitEnumDefinition(aClass);
 
-        public void visitTypeDefinition(GrTypeDefinition grTypeDefinition) {
-            super.visitTypeDefinition(grTypeDefinition);
-            if (!(grTypeDefinition instanceof GrEnumTypeDefinition)) {
-                return;
-            }
-            final GrEnumTypeDefinition aClass = (GrEnumTypeDefinition) grTypeDefinition;
-
-            final String name = aClass.getName();
-            if (name == null) {
-                return;
-            }
-            if (isValid(name)) {
-                return;
-            }
-            registerClassError(aClass, name);
+        final String name = aClass.getName();
+        if (name == null) {
+          return;
         }
+        if (isValid(name)) {
+          return;
+        }
+        registerClassError(aClass, name);
+      }
     }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInterfaceNamingConventionInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInterfaceNamingConventionInspection.java
index 832a888..188995a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInterfaceNamingConventionInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInterfaceNamingConventionInspection.java
@@ -20,7 +20,6 @@
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
 import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrInterfaceDefinition;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 
 public class GroovyInterfaceNamingConventionInspection extends ConventionInspection {
 
@@ -32,7 +31,7 @@
     return "Interface naming convention";
   }
 
-  protected GroovyFix buildFix(PsiElement location) {
+  protected GroovyFix buildFix(@NotNull PsiElement location) {
     return new RenameFix();
   }
 
@@ -63,18 +62,15 @@
     return DEFAULT_MAX_LENGTH;
   }
 
+  @NotNull
   public BaseInspectionVisitor buildVisitor() {
     return new NamingConventionsVisitor();
   }
 
   private class NamingConventionsVisitor extends BaseInspectionVisitor {
-
-    public void visitTypeDefinition(GrTypeDefinition grTypeDefinition) {
-      super.visitTypeDefinition(grTypeDefinition);
-      if (!(grTypeDefinition instanceof GrInterfaceDefinition)) {
-        return;
-      }
-      final GrInterfaceDefinition aClass = (GrInterfaceDefinition) grTypeDefinition;
+    @Override
+    public void visitInterfaceDefinition(GrInterfaceDefinition aClass) {
+      super.visitInterfaceDefinition(aClass);
 
       final String name = aClass.getName();
       if (name == null) {
@@ -85,5 +81,6 @@
       }
       registerClassError(aClass, name);
     }
+
   }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
index 985632a..3bc8412 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
@@ -695,7 +695,7 @@
     @Override
     public void unregister(@NotNull Condition<IntentionAction> condition) {
       if (myInfo != null) {
-        QuickFixAction.unregisterQuickFixAction(myInfo, condition);
+        myInfo.unregisterQuickFix(condition);
       }
     }
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
index fa4aaf3..f499eb1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
@@ -691,17 +691,15 @@
 
   @Nullable
   public static GrControlFlowOwner findControlFlowOwner(PsiElement place) {
-    if (place instanceof GrCodeBlock) {
-      place = place.getContext();
-    }
-    while (true) {
-      assert place != null;
-      place = place.getContext();
-      if (place == null) return null;
+    place = place.getContext();
+    while (place != null) {
       if (place instanceof GrControlFlowOwner && ((GrControlFlowOwner)place).isTopControlFlowOwner()) return (GrControlFlowOwner)place;
       if (place instanceof GrMethod) return ((GrMethod)place).getBlock();
       if (place instanceof GrClassInitializer) return ((GrClassInitializer)place).getBlock();
+
+      place = place.getContext();
     }
+    return null;
   }
 
   /**
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
index ae2972e..3d3f6e4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
@@ -4,6 +4,7 @@
 import com.intellij.psi.*;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.PairFunction;
+import com.intellij.util.SingletonInstancesCache;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -11,7 +12,6 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
 import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
-import org.jetbrains.plugins.groovy.util.ClassInstanceCache;
 import org.jetbrains.plugins.groovy.util.FixedValuesReferenceProvider;
 
 import java.lang.reflect.Modifier;
@@ -253,7 +253,7 @@
   @NotNull
   public PairFunction<GrMethodCall, PsiMethod, PsiType> getReturnTypeCalculator() {
     if (myReturnTypeCalculatorInstance == null) {
-      myReturnTypeCalculatorInstance = ClassInstanceCache.getInstance(myReturnTypeCalculatorClassName, myClassLoader);
+      myReturnTypeCalculatorInstance = SingletonInstancesCache.getInstance(myReturnTypeCalculatorClassName, myClassLoader);
     }
     return myReturnTypeCalculatorInstance;
   }
@@ -286,7 +286,7 @@
 
   public GroovyNamedArgumentProvider getNamedArgProvider() {
     if (myNamedArgProviderInstance == null) {
-      myNamedArgProviderInstance = ClassInstanceCache.getInstance(myNamedArgProviderClassName, myClassLoader);
+      myNamedArgProviderInstance = SingletonInstancesCache.getInstance(myNamedArgProviderClassName, myClassLoader);
     }
     return myNamedArgProviderInstance;
   }
@@ -328,7 +328,7 @@
 
     private Object doGetProvider(ClassLoader classLoader) {
       if (myProviderClassName != null) {
-        return ClassInstanceCache.getInstance(myProviderClassName, classLoader);
+        return SingletonInstancesCache.getInstance(myProviderClassName, classLoader);
       }
 
       return new FixedValuesReferenceProvider(myValues);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
index 49f772d..fc19f64 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
@@ -202,4 +202,6 @@
 replace.if.with.ternary.intention.name=Replace with ?:
 replace.if.with.ternary.intention.family.name=Replace if-statement with ternary operator
 gr.redundant.else.intention.name=Remove redundant 'else' keyword
-gr.redundant.else.intention.family.name=Remove redundant 'else' keyword
\ No newline at end of file
+gr.redundant.else.intention.family.name=Remove redundant 'else' keyword
+gr.remove.explicit.type.declaration.intention.name=Remove explicit type
+gr.remove.explicit.type.declaration.intention.family.name=Remove explicit type declaration
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java
new file mode 100644
index 0000000..5f530705
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.intentions.declaration;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.intentions.base.Intention;
+import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
+import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
+
+/**
+ * Created by Max Medvedev on 8/24/13
+ */
+public class GrRemoveExplicitTypeDeclarationIntention extends Intention {
+  @Override
+  protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
+    PsiElement parent = element.getParent();
+
+    if (parent instanceof GrVariable) {
+      ((GrVariable)parent).setType(null);
+    }
+    else if (parent instanceof GrVariableDeclaration) {
+      ((GrVariableDeclaration)parent).setType(null);
+    }
+    else if (parent instanceof GrMethod) {
+      ((GrMethod)parent).setReturnType(null);
+    }
+  }
+
+  @NotNull
+  @Override
+  protected PsiElementPredicate getElementPredicate() {
+    return new PsiElementPredicate() {
+      @Override
+      public boolean satisfiedBy(PsiElement element) {
+        PsiElement parent = element.getParent();
+        if (element instanceof GrTypeElement || element instanceof GrModifierList) {
+          return parent instanceof GrVariableDeclaration && ((GrVariableDeclaration)parent).getTypeElementGroovy() != null ||
+                 parent instanceof GrMethod && ((GrMethod)parent).getReturnTypeElementGroovy() != null;
+        }
+
+        if (parent instanceof GrNamedElement && ((GrNamedElement)parent).getNameIdentifierGroovy().equals(element)) {
+          if (parent instanceof GrVariable) {
+            return ((GrVariable)parent).getTypeElementGroovy() != null;
+          }
+
+          if (parent instanceof GrMethod) {
+            return ((GrMethod)parent).getReturnTypeElementGroovy() != null;
+          }
+        }
+
+        return false;
+      }
+    };
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java
index a145b17..642b646 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java
@@ -26,6 +26,7 @@
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
 import org.jetbrains.plugins.groovy.intentions.base.Intention;
 import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
@@ -81,6 +82,9 @@
     if (methods.size() == 1) {
       final Pair<PsiMethod, GrOpenBlock> pair = methods.get(0);
       appendClosureTextByMethod(pair.getFirst(), buffer, pair.getSecond(), newExpr);
+      if (!GroovyConfigUtils.getInstance().isVersionAtLeast(psiElement, GroovyConfigUtils.GROOVY2_2)) {
+        buffer.append(" as ").append(iface.getQualifiedName());
+      }
     }
     else {
       buffer.append("[");
@@ -97,8 +101,9 @@
         buffer.append('\n');
       }
       buffer.append("]");
+      buffer.append(" as ").append(iface.getQualifiedName());
     }
-    buffer.append(" as ").append(iface.getQualifiedName());
+
     createAndAdjustNewExpression(project, newExpr, buffer);
   }
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java
index e362cba..06b53a4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java
@@ -255,6 +255,26 @@
     visitElement(typeDefinition);
   }
 
+  public void visitClassDefinition(GrClassDefinition classDefinition) {
+    visitTypeDefinition(classDefinition);
+  }
+
+  public void visitEnumDefinition(GrEnumTypeDefinition enumDefinition) {
+    visitTypeDefinition(enumDefinition);
+  }
+
+  public void visitInterfaceDefinition(GrInterfaceDefinition interfaceDefinition) {
+    visitTypeDefinition(interfaceDefinition);
+  }
+
+  public void visitAnonymousClassDefinition(GrAnonymousClassDefinition anonymousClassDefinition) {
+    visitTypeDefinition(anonymousClassDefinition);
+  }
+
+  public void visitAnnotationTypeDefinition(GrAnnotationTypeDefinition annotationTypeDefinition) {
+    visitTypeDefinition(annotationTypeDefinition);
+  }
+
   public void visitExtendsClause(GrExtendsClause extendsClause) {
     visitElement(extendsClause);
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
index 28dfd6d..b9a3a27 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
@@ -96,7 +96,9 @@
     final GrTypeElement typeElement = getTypeElementGroovy();
     if (type == null) {
       if (typeElement == null) return;
-      getModifierList().setModifierProperty(GrModifier.DEF, true);
+      if (getModifierList().getModifiers().length == 0) {
+        getModifierList().setModifierProperty(GrModifier.DEF, true);
+      }
       typeElement.delete();
       return;
     }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
index 74df206..4331046b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
@@ -16,10 +16,12 @@
 
 package org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks;
 
+import com.intellij.extapi.psi.ASTDelegatePsiElement;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.util.Key;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.ResolveState;
+import com.intellij.psi.impl.CheckUtil;
 import com.intellij.psi.impl.source.tree.Factory;
 import com.intellij.psi.impl.source.tree.LazyParseablePsiElement;
 import com.intellij.psi.impl.source.tree.LeafElement;
@@ -60,6 +62,17 @@
   }
 
   @Override
+  public void delete() throws IncorrectOperationException {
+    if (getParent() instanceof ASTDelegatePsiElement) {
+      CheckUtil.checkWritable(this);
+      ((ASTDelegatePsiElement)getParent()).deleteChildInternal(getNode());
+    }
+    else {
+      getParent().deleteChildRange(this, this);
+    }
+  }
+
+  @Override
   public void removeElements(PsiElement[] elements) throws IncorrectOperationException {
     GroovyPsiElementImpl.removeElements(this, elements);
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnnotationTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnnotationTypeDefinitionImpl.java
index 47d849f..16d52d0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnnotationTypeDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnnotationTypeDefinitionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,10 +19,11 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.psi.PsiClassType;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnnotationTypeDefinition;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.stubs.GrTypeDefinitionStub;
-import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
 
 /**
  * @author Dmitry.Krasilschikov
@@ -61,4 +62,9 @@
   private PsiClassType createAnnotationType() {
     return TypesUtil.createTypeByFQClassName("java.lang.annotation.Annotation", this);
   }
+
+  @Override
+  public void accept(GroovyElementVisitor visitor) {
+    visitor.visitAnnotationTypeDefinition(this);
+  }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
index 495603b..aa7876a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -26,6 +26,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
@@ -250,4 +251,10 @@
   public PsiIdentifier getNameIdentifier() {
     return null;
   }
+
+  @Override
+  public void accept(GroovyElementVisitor visitor) {
+    visitor.visitAnonymousClassDefinition(this);
+  }
+
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrClassDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrClassDefinitionImpl.java
index cafc779..2e0b3d9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrClassDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrClassDefinitionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
 import com.intellij.lang.ASTNode;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrClassDefinition;
 import org.jetbrains.plugins.groovy.lang.psi.stubs.GrTypeDefinitionStub;
 
@@ -39,4 +40,9 @@
   public String toString() {
     return "Class definition";
   }
+
+  @Override
+  public void accept(GroovyElementVisitor visitor) {
+    visitor.visitClassDefinition(this);
+  }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java
index 42308ec..56f4ffd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -31,6 +31,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumDefinitionBody;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition;
@@ -175,4 +176,9 @@
     if (enumDefinitionBody != null) return enumDefinitionBody.getEnumConstantList();
     return null;
   }
+
+  @Override
+  public void accept(GroovyElementVisitor visitor) {
+    visitor.visitEnumDefinition(this);
+  }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrInterfaceDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrInterfaceDefinitionImpl.java
index d4fa5a8..d093bab 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrInterfaceDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrInterfaceDefinitionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,11 +17,11 @@
 package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef;
 
 import com.intellij.lang.ASTNode;
-import com.intellij.psi.stubs.IStubElementType;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrInterfaceDefinition;
 import org.jetbrains.plugins.groovy.lang.psi.stubs.GrTypeDefinitionStub;
-import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
 
 /**
  * @author Dmitry.Krasilschikov
@@ -44,4 +44,9 @@
   public boolean isInterface() {
     return true;
   }
+
+  @Override
+  public void accept(GroovyElementVisitor visitor) {
+    visitor.visitInterfaceDefinition(this);
+  }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
index 74443e4..2f757a8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
@@ -55,6 +55,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
+import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.noncode.MixinMemberContributor;
 import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
 import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
@@ -226,7 +227,7 @@
 
           final DelegatingScopeProcessor delegate = new MixinMemberContributor.MixinProcessor(processor, subjectType, qualifier);
           for (GrMethod method : methods) {
-            delegate.execute(method, ResolveState.initial());
+            ResolveUtil.processElement(delegate, method, state);
           }
         }
       }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/LocalVarAnalyzer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/LocalVarAnalyzer.java
index c130ec2..edb9c90 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/LocalVarAnalyzer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/LocalVarAnalyzer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
index bed8605..83713e9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
@@ -77,7 +77,7 @@
 /**
  * @author Maxim.Medvedev
  */
-public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSettings> implements RefactoringActionHandler {
+public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSettings, Scope extends PsiElement> implements RefactoringActionHandler {
   public static final Function<GrExpression, String> GR_EXPRESSION_RENDERER = new Function<GrExpression, String>() {
     @Override
     public String fun(@NotNull GrExpression expr) {
@@ -124,7 +124,7 @@
   protected abstract String getHelpID();
 
   @NotNull
-  protected abstract PsiElement findScope(GrExpression expression, GrVariable variable, StringPartInfo stringPart);
+  protected abstract Scope[] findPossibleScopes(GrExpression expression, GrVariable variable, StringPartInfo stringPart, Editor editor);
 
   protected abstract void checkExpression(@NotNull GrExpression selectedExpr) throws GrRefactoringError;
 
@@ -276,14 +276,41 @@
     // Does nothing
   }
 
-  @NotNull
-  public GrIntroduceContext getContext(@NotNull Project project,
-                                       @NotNull Editor editor,
-                                       @Nullable GrExpression expression,
-                                       @Nullable GrVariable variable,
-                                       @Nullable StringPartInfo stringPart) {
-    final PsiElement scope = findScope(expression, variable, stringPart);
+  public void getContextAndInvoke(@NotNull final Project project,
+                                  @NotNull final Editor editor,
+                                  @Nullable final GrExpression expression,
+                                  @Nullable final GrVariable variable,
+                                  @Nullable final StringPartInfo stringPart) {
+    final Scope[] scopes = findPossibleScopes(expression, variable, stringPart, editor);
 
+    Pass<Scope> callback = new Pass<Scope>() {
+      @Override
+      public void pass(Scope scope) {
+        GrIntroduceContext context = getContext(project, editor, expression, variable, stringPart, scope);
+        invokeImpl(project, context, editor);
+      }
+    };
+
+    if (scopes.length == 0) {
+      CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( getRefactoringName() + "is not available in current scope"),
+                                          getRefactoringName(), getHelpID());
+    }
+    else if (scopes.length == 1) {
+      callback.pass(scopes[0]);
+    }
+    else {
+      showScopeChooser(scopes, callback, editor);
+    }
+  }
+
+  protected abstract void showScopeChooser(Scope[] scopes, Pass<Scope> callback, Editor editor);
+
+  public GrIntroduceContext getContext(@NotNull Project project,
+                                        @NotNull Editor editor,
+                                        @Nullable GrExpression expression,
+                                        @Nullable GrVariable variable,
+                                        @Nullable StringPartInfo stringPart,
+                                        @NotNull PsiElement scope) {
     if (variable != null) {
       final List<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
       ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
@@ -309,42 +336,8 @@
     }
   }
 
-  @NotNull
-  protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
-    final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(PsiUtil.skipParentheses(expression, false), scope);
-    if (occurrences == null || occurrences.length == 0) {
-      throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found"));
-    }
-    return occurrences;
-  }
-
-  private boolean invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, int startOffset, int endOffset) {
+  private boolean invokeImpl(final Project project, final GrIntroduceContext context, final Editor editor) {
     try {
-      PsiDocumentManager.getInstance(project).commitAllDocuments();
-      if (!(file instanceof GroovyFileBase)) {
-        throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files"));
-      }
-      if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) {
-        throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found"));
-      }
-
-      GrExpression selectedExpr = findExpression(file, startOffset, endOffset);
-      final GrVariable variable = findVariable(file, startOffset, endOffset);
-      final StringPartInfo stringPart = StringPartInfo.findStringPart(file, startOffset, endOffset);
-      if (variable != null) {
-        checkVariable(variable);
-      }
-      else if (selectedExpr != null) {
-        checkExpression(selectedExpr);
-      }
-      else if (stringPart != null) {
-        checkStringLiteral(stringPart);
-      }
-      else {
-        throw new GrRefactoringError(null);
-      }
-
-      final GrIntroduceContext context = getContext(project, editor, selectedExpr, variable, stringPart);
       if (!CommonRefactoringUtil.checkReadOnlyStatus(project, context.getOccurrences())) {
         return false;
       }
@@ -370,15 +363,21 @@
               RangeMarker stringPartRangeMarker = createRange(document, context.getStringPart());
               RangeMarker varRangeMarker = createRange(document, context.getVar());
 
-              GrVariable var = ApplicationManager.getApplication().runWriteAction(new Computable<GrVariable>() {
-                @Override
-                public GrVariable compute() {
-                  return runRefactoring(context, settings);
-                }
-              });
+              SmartPsiElementPointer<GrVariable> pointer =
+                ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
+                  @Override
+                  public SmartPsiElementPointer<GrVariable> compute() {
+                    GrVariable var = runRefactoring(context, settings);
+                    return var != null
+                           ? SmartPointerManager.getInstance(context.getProject()).createSmartPsiElementPointer(var)
+                           : null;
+                  }
+                });
+              GrVariable var = pointer != null ? pointer.getElement() : null;
 
               if (isInplace && var != null) {
-                GrInplaceIntroducer introducer = getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker);
+                GrInplaceIntroducer introducer =
+                  getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker);
                 PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
                 introducer.performInplaceRefactoring(introducer.suggestNames(context));
               }
@@ -411,11 +410,53 @@
       return true;
     }
     catch (GrRefactoringError e) {
-      CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
+      CommonRefactoringUtil
+        .showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
       return false;
     }
   }
 
+  @NotNull
+  protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
+    final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(skipParentheses(expression, false), scope);
+    if (occurrences == null || occurrences.length == 0) {
+      throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found"));
+    }
+    return occurrences;
+  }
+
+  private void invoke(@NotNull final Project project,
+                      @NotNull final Editor editor,
+                      @NotNull PsiFile file,
+                      int startOffset,
+                      int endOffset) {
+    PsiDocumentManager.getInstance(project).commitAllDocuments();
+    if (!(file instanceof GroovyFileBase)) {
+      throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files"));
+    }
+    if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) {
+      throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found"));
+    }
+
+    GrExpression selectedExpr = findExpression(file, startOffset, endOffset);
+    final GrVariable variable = findVariable(file, startOffset, endOffset);
+    final StringPartInfo stringPart = StringPartInfo.findStringPart(file, startOffset, endOffset);
+    if (variable != null) {
+      checkVariable(variable);
+    }
+    else if (selectedExpr != null) {
+      checkExpression(selectedExpr);
+    }
+    else if (stringPart != null) {
+      checkStringLiteral(stringPart);
+    }
+    else {
+      throw new GrRefactoringError(null);
+    }
+
+    getContextAndInvoke(project, editor, selectedExpr, variable, stringPart);
+  }
+
   private static RangeMarker createRange(Document document, StringPartInfo part) {
     if (part == null) {
       return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java
index 357fa87..05bd556 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java
@@ -15,7 +15,9 @@
  */
 package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
 
+import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.util.Pass;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.HelpID;
@@ -41,7 +43,7 @@
 /**
  * @author Maxim.Medvedev
  */
-public class GrIntroduceConstantHandler extends GrIntroduceHandlerBase<GrIntroduceConstantSettings> {
+public class GrIntroduceConstantHandler extends GrIntroduceHandlerBase<GrIntroduceConstantSettings, PsiElement> {
   public static final String REFACTORING_NAME = "Introduce Constant";
 
   @NotNull
@@ -58,9 +60,9 @@
 
   @NotNull
   @Override
-  protected PsiElement findScope(GrExpression expression, GrVariable variable, StringPartInfo stringPart) {
+  public PsiElement[] findPossibleScopes(GrExpression expression, GrVariable variable, StringPartInfo stringPart, Editor editor) {
     final PsiElement place = getCurrentPlace(expression, variable, stringPart);
-    return place.getContainingFile();
+    return new PsiFile[]{place.getContainingFile()};
   }
 
   @Override
@@ -135,6 +137,11 @@
   }
 
   @Override
+  protected void showScopeChooser(PsiElement[] scopes, Pass<PsiElement> callback, Editor editor) {
+    //todo do nothing right now
+  }
+
+  @Override
   protected boolean isInplace(GrIntroduceContext context) {
     return false;
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form
index 3ad6c01..96f32e5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form
@@ -21,6 +21,7 @@
               <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>
+              <labelFor value="58f26"/>
               <text value="&amp;Initialize in:"/>
             </properties>
           </component>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java
index 1081b61..27878e9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java
@@ -16,17 +16,21 @@
 package org.jetbrains.plugins.groovy.refactoring.introduce.field;
 
 import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.codeInsight.navigation.NavigationUtil;
+import com.intellij.ide.util.PsiClassListCellRenderer;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.util.Pass;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiModifier;
 import com.intellij.psi.PsiType;
+import com.intellij.psi.search.PsiElementProcessor;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.HelpID;
 import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
 import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
-import com.intellij.util.ObjectUtils;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -51,7 +55,7 @@
 /**
  * @author Maxim.Medvedev
  */
-public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase<GrIntroduceFieldSettings> {
+public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase<GrIntroduceFieldSettings, PsiClass> {
 
   @NotNull
   @Override
@@ -67,9 +71,23 @@
 
   @NotNull
   @Override
-  protected PsiClass findScope(GrExpression expression, GrVariable variable, StringPartInfo partInfo) {
+  protected PsiClass[] findPossibleScopes(GrExpression expression,
+                                            GrVariable variable,
+                                            StringPartInfo partInfo,
+                                            Editor editor) {
     PsiElement place = getCurrentPlace(expression, variable, partInfo);
-    return ObjectUtils.assertNotNull(PsiUtil.getContextClass(place));
+    PsiClass aClass = PsiUtil.getContextClass(place);
+    if (aClass instanceof GroovyScriptClass) {
+      return new PsiClass[]{aClass};
+    }
+    else {
+      List<PsiClass> result = ContainerUtil.newArrayList(aClass);
+      while (aClass != null) {
+        aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class);
+        ContainerUtil.addIfNotNull(result, aClass);
+      }
+      return result.toArray(new PsiClass[result.size()]);
+    }
   }
 
   @Override
@@ -233,6 +251,19 @@
     };
   }
 
+  @Override
+  protected void showScopeChooser(PsiClass[] scopes, final Pass<PsiClass> callback, Editor editor) {
+    PsiElementProcessor<PsiClass> processor = new PsiElementProcessor<PsiClass>() {
+      @Override
+      public boolean execute(@NotNull PsiClass element) {
+        callback.pass(element);
+        return false;
+      }
+    };
+
+    NavigationUtil.getPsiElementPopup(scopes, new PsiClassListCellRenderer(), "Choose class to introduce field", processor).showInBestPositionFor(editor);
+  }
+
   @NotNull
   @Override
   protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java
index ff941be..3e3f688 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java
@@ -75,11 +75,12 @@
 
     int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression);
     final PsiElement[] replaced = processOccurrences();
-    GrStatement anchor = getAnchor(replaced);
+    PsiElement replacedExpression = replaced[expressionIndex];
+    GrStatement anchor = getAnchor(replaced, replacedExpression);
 
     RefactoringUtil.highlightAllOccurrences(myContext.getProject(), replaced, myContext.getEditor());
 
-    return insertVariableDefinition(declaration, anchor, replaced[expressionIndex]);
+    return insertVariableDefinition(declaration, anchor, replacedExpression);
   }
 
   private void refreshPositionMarker(PsiElement e) {
@@ -206,8 +207,8 @@
   }
 
   @NotNull
-  private GrStatement getAnchor(PsiElement[] replaced) {
-    PsiElement anchor = GrIntroduceHandlerBase.findAnchor(replaced, myContext.getScope());
+  private GrStatement getAnchor(PsiElement[] replaced, PsiElement replacedExpression) {
+    PsiElement anchor = GrIntroduceHandlerBase.findAnchor(replaced, GroovyRefactoringUtil.getEnclosingContainer(replacedExpression));
     if (!(anchor instanceof GrStatement)) {
       StringBuilder error = new StringBuilder("scope:");
       error.append(myContext.getScope());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java
index 5ce7a09..c27df06 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java
@@ -16,7 +16,9 @@
 
 package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
 
+import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.util.Pass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiModifier;
 import com.intellij.psi.PsiType;
@@ -25,8 +27,9 @@
 import com.intellij.refactoring.util.CanonicalTypes;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
+import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
@@ -46,19 +49,20 @@
 /**
  * @author ilyas
  */
-public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyIntroduceVariableSettings> {
+public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyIntroduceVariableSettings, GrControlFlowOwner> {
   public static final String DUMMY_NAME = "________________xxx_________________";
   protected static final String REFACTORING_NAME = GroovyRefactoringBundle.message("introduce.variable.title");
   private RangeMarker myPosition = null;
 
   @NotNull
   @Override
-  protected PsiElement findScope(GrExpression selectedExpr, GrVariable variable, StringPartInfo stringPartInfo) {
+  protected GrControlFlowOwner[] findPossibleScopes(GrExpression selectedExpr,
+                                                    GrVariable variable,
+                                                    StringPartInfo stringPartInfo,
+                                                    Editor editor) {
     // Get container element
-    final PsiElement scope = stringPartInfo != null
-                             ? GroovyRefactoringUtil.getEnclosingContainer(stringPartInfo.getLiteral())
-                             : GroovyRefactoringUtil.getEnclosingContainer(selectedExpr);
-    if (scope == null || !(scope instanceof GroovyPsiElement)) {
+    final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(stringPartInfo != null ? stringPartInfo.getLiteral() : selectedExpr);
+    if (scope == null) {
       throw new GrRefactoringError(
         GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME));
     }
@@ -66,7 +70,7 @@
       throw new GrRefactoringError(
         GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME));
     }
-    return scope;
+    return new GrControlFlowOwner[]{scope};
   }
 
   protected void checkExpression(@NotNull GrExpression selectedExpr) {
@@ -187,6 +191,11 @@
     };
   }
 
+  @Override
+  protected void showScopeChooser(GrControlFlowOwner[] scopes, Pass<GrControlFlowOwner> callback, Editor editor) {
+    //todo do nothing right now
+  }
+
   @NotNull
   private static GrVariableDeclaration generateDeclaration(@NotNull GrIntroduceContext context,
                                                            @NotNull GroovyIntroduceVariableSettings settings) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.java
index 3cdabe3..acac929 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.java
@@ -51,12 +51,14 @@
   @Override
   protected boolean isTestClass(PsiClass clazz, boolean canBePotential) {
     return clazz.getLanguage() == GroovyFileType.GROOVY_LANGUAGE &&
-           JUnitUtil.isTestClass(clazz) &&
+           //JUnitUtil.isTestClass(clazz) &&
            InheritanceUtil.isInheritor(clazz, GroovyCommonClassNames.GROOVY_UTIL_TEST_CASE);
   }
 
   @Override
   protected PsiMethod findSetUpMethod(@NotNull PsiClass clazz) {
+    if (!isTestClass(clazz, false)) return null;
+
     for (PsiMethod method : clazz.getMethods()) {
       if (method.getName().equals("setUp")) return method;
     }
@@ -65,6 +67,8 @@
 
   @Override
   protected PsiMethod findTearDownMethod(@NotNull PsiClass clazz) {
+    if (!isTestClass(clazz, false)) return null;
+
     for (PsiMethod method : clazz.getMethods()) {
       if (method.getName().equals("tearDown")) return method;
     }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyUnwrapTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyUnwrapTest.groovy
index 867c343..a699922 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyUnwrapTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyUnwrapTest.groovy
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang
 
 import com.intellij.codeInsight.unwrap.UnwrapHandler
@@ -51,13 +66,11 @@
   }
 
   public void testBraces() throws Exception {
-    assertUnwrapped("""
+    assertUnwrapped("""\
 <caret>{
   def x = 1
 }
-""", """
-def x = 1
-""");
+""", "def x = 1");
   }
 
   public void testUnwrapParameterUnderArgumentList() throws Exception {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyResolveTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyResolveTestCase.groovy
index 6407c31..c481df1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyResolveTestCase.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyResolveTestCase.groovy
@@ -95,7 +95,7 @@
     final ref = configureByText(text)
     assertNotNull(ref)
     final resolved = ref.resolve()
-    assertInstanceOf(resolved, type)
+    if (type != null) assertInstanceOf(resolved, type)
     return resolved
   }
 
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
index 8dc6697..f6ee5f0 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
@@ -1431,6 +1431,30 @@
 ''', PsiMethod)
   }
 
+  void testRuntimeMixin22() {
+    assertNull resolveByText('''\
+class ReentrantLock {}
+
+ReentrantLock.metaClass.withLock = { nestedCode -> }
+
+new ReentrantLock().withLock {
+    fo<caret>o(3)
+}
+''')
+  }
+
+  void testRuntimeMixin23() {
+    assertNotNull resolveByText('''\
+class ReentrantLock {}
+
+ReentrantLock.metaClass.withLock = { nestedCode -> }
+
+new ReentrantLock().withLock {
+    withL<caret>ock(2)
+}
+''')
+  }
+
   void testRunnableVsCallable() {
     final PsiMethod method = resolveByText('''\
 import java.util.concurrent.Callable
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java
index f51e02a..77bc4a1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/IntroduceConstantTest.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiModifier;
 import com.intellij.psi.PsiType;
 import com.intellij.psi.impl.source.PostprocessReformattingAspect;
@@ -86,7 +87,8 @@
     final GrExpression expression = findExpression();
     final GrVariable variable = findVariable();
     final StringPartInfo stringPart = findStringPart();
-    final GrIntroduceContext context = handler.getContext(getProject(), editor, expression, variable, stringPart);
+    PsiElement[] scopes = handler.findPossibleScopes(expression, variable, stringPart, editor);
+    final GrIntroduceContext context = handler.getContext(getProject(), editor, expression, variable, stringPart, scopes[0]);
 
     PsiClass targetClass;
     if (targetClassName == null) {
diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/f2.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/f2.test
index 7e89dbf..f1a15b4 100644
--- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/f2.test
+++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/f2.test
@@ -4,5 +4,5 @@
 -----
 def preved = boo
 for (i in 1..preved<caret>){
-    def foo = boo
+    def foo = preved
 }
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop7.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop7.test
index ca3771e..e8869c6 100644
--- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop7.test
+++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop7.test
@@ -4,5 +4,5 @@
 -----
 def preved = true
 while (preved<caret>) {
-    true
+    preved
 }
\ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java
index 371fc70..9c68605 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java
@@ -221,10 +221,11 @@
           // The original file exists so this is a duplication of the file.
           // Don't create the before ContentRevision or IDEA will think
           // this was a rename.
+          //todo: fix this unexpected status behavior (sometimes added  status instead of copied, and copied instead of renamed )
           processChange(
             null,
             HgCurrentContentRevision.create(afterFile, currentNumber),
-            HgChangeProvider.COPIED,
+            FileStatus.ADDED,
             builder,
             vcsKey
           );
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
index 60d7a43..37488f3 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
@@ -8,6 +8,7 @@
 import com.intellij.xml.XmlAttributeDescriptor;
 import com.intellij.xml.XmlElementDescriptor;
 import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
 import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
@@ -209,9 +210,8 @@
   }
 
   @Override
-  public PsiReference[] getValueReferences(XmlAttributeValue value) {
-    String s = value.getValue();
-    return s != null && !s.startsWith("${") ? super.getValueReferences(value) : PsiReference.EMPTY_ARRAY;
+  public PsiReference[] getValueReferences(XmlElement element, @NotNull String text) {
+    return !text.startsWith("${") ? super.getValueReferences(element, text) : PsiReference.EMPTY_ARRAY;
   }
 
   @Override
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java
index 2bebb05..21828ec 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -63,6 +63,8 @@
   @Override
   @Nullable
   protected PsiMethod findSetUpMethod(@NotNull PsiClass clazz) {
+    if (!JUnitUtil.isJUnit3TestClass(clazz)) return null;
+
     for (PsiMethod each : clazz.getMethods()) {
       if (each.getName().equals("setUp")) return each;
     }
@@ -72,6 +74,8 @@
   @Override
   @Nullable
   protected PsiMethod findTearDownMethod(@NotNull PsiClass clazz) {
+    if (!JUnitUtil.isJUnit3TestClass(clazz)) return null;
+
     for (PsiMethod each : clazz.getMethods()) {
       if (each.getName().equals("tearDown")) return each;
     }
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
index 569d4b1..422e567 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -492,7 +492,7 @@
         final String fqName = myPattern.iterator().next();
         return (fqName.contains("*") ? fqName : StringUtil.getShortName(fqName)) + (size > 1 ? " and " + (size - 1) + " more" : "");
       }
-      final String className = JavaExecutionUtil.getPresentableClassName(getMainClassName(), configurationModule);
+      final String className = JavaExecutionUtil.getPresentableClassName(getMainClassName());
       if (TEST_METHOD.equals(TEST_OBJECT)) {
         return className + '.' + getMethodName();
       }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencySystemPathConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencySystemPathConverter.java
index ae91be9..2641d41 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencySystemPathConverter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencySystemPathConverter.java
@@ -15,20 +15,18 @@
  */
 package org.jetbrains.idea.maven.dom.converters;
 
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
-import com.intellij.psi.xml.XmlElement;
 import com.intellij.util.xml.ConvertContext;
 import com.intellij.util.xml.CustomReferenceConverter;
 import com.intellij.util.xml.GenericDomValue;
 import com.intellij.util.xml.ResolvingConverter;
-import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.dom.references.MavenPathReferenceConverter;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -54,63 +52,12 @@
 
   @NotNull
   public PsiReference[] createReferences(final GenericDomValue genericDomValue, final PsiElement element, final ConvertContext context) {
-    XmlElement xmlElement = genericDomValue.getXmlElement();
-
-    if (xmlElement != null && xmlElement.getText().contains("${")) return PsiReference.EMPTY_ARRAY;
-
-    return createReferences(element, true);
-  }
-
-  @NotNull
-  public static PsiReference[] createReferences(@NotNull final PsiElement psiElement, final boolean soft) {
-    FileReferenceSet set = new MyFileReferenceSet(psiElement, soft);
-
-    return set.getAllReferences();
-  }
-
-  private static class MyFileReferenceSet extends FileReferenceSet {
-    private final boolean mySoft;
-
-    public MyFileReferenceSet(PsiElement psiElement, boolean soft) {
-      super(psiElement);
-      mySoft = soft;
-    }
-
-    @Override
-    public boolean isAbsolutePathReference() {
-      return true;
-    }
-
-    @Override
-    protected boolean isSoft() {
-      return mySoft;
-    }
-
-    @NotNull
-    @Override
-    public Collection<PsiFileSystemItem> getDefaultContexts() {
-      Collection<PsiFileSystemItem> systemItemCollection = super.getDefaultContexts();
-      if (isAbsolutePathReference()) {
-        VirtualFile vFile = LocalFileSystem.getInstance().getRoot();
-
-        if (ApplicationManager.getApplication().isUnitTestMode()) {
-          assert vFile != null : ""; //
-        }
-
-        if (vFile != null) {
-          final PsiDirectory directory = getElement().getManager().findDirectory(vFile);
-
-          if (ApplicationManager.getApplication().isUnitTestMode()) {
-            assert directory != null : "for element: " + getElement().getText(); //
-          }
-
-          if (directory != null) {
-            systemItemCollection = new THashSet<PsiFileSystemItem>(systemItemCollection);
-            systemItemCollection.add(directory);
-          }
-        }
+    return MavenPathReferenceConverter.createReferences(genericDomValue, element, new Condition<PsiFileSystemItem>() {
+      @Override
+      public boolean value(PsiFileSystemItem item) {
+        return (item instanceof PsiDirectory) || item.getName().endsWith(".jar");
       }
-      return systemItemCollection;
-    }
+    }, true);
   }
 }
+
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java
index c4f864a..d7a4ca4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java
@@ -18,10 +18,10 @@
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.UrlPsiReference;
 import com.intellij.util.xml.ConvertContext;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.maven.dom.references.MavenUrlPsiReference;
 
 public class MavenUrlConverter extends MavenReferenceConverter<String> {
   @Override
@@ -35,6 +35,6 @@
   }
 
   protected PsiReference createReference(PsiElement element, String text, TextRange range) {
-    return new MavenUrlPsiReference(element, text, range);
+    return new UrlPsiReference(element);
   }
 }
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java
index 4b08baf..46fa023 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java
@@ -18,11 +18,10 @@
 import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupElementBuilder;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.ElementManipulators;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.UrlPsiReference;
 import com.intellij.util.xml.ConvertContext;
 import com.intellij.util.xml.GenericDomValue;
 import com.intellij.util.xml.ResolvingConverter;
@@ -31,7 +30,6 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.dom.converters.MavenUrlConverter;
 import org.jetbrains.idea.maven.dom.model.MavenDomRepositoryBase;
-import org.jetbrains.idea.maven.dom.references.MavenUrlPsiReference;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -77,9 +75,7 @@
     @NotNull
     @Override
     public PsiReference[] createReferences(GenericDomValue value, final PsiElement element, final ConvertContext context) {
-      String text = value.getStringValue();
-      TextRange range = ElementManipulators.getValueTextRange(element);
-      return new PsiReference[]{new MavenUrlPsiReference(element, text, range) {
+      return new PsiReference[]{new UrlPsiReference(element) {
 
         @NotNull
         @Override
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPathReferenceConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPathReferenceConverter.java
index 56672d7..b136cf4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPathReferenceConverter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPathReferenceConverter.java
@@ -23,6 +23,7 @@
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
+import com.intellij.util.Function;
 import com.intellij.util.xml.ConvertContext;
 import com.intellij.util.xml.DomElement;
 import com.intellij.util.xml.DomUtil;
@@ -33,6 +34,7 @@
 import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
 
 import java.util.Collection;
+import java.util.Collections;
 
 /**
  * @author Sergey Evdokimov
@@ -52,6 +54,12 @@
   public static PsiReference[] createReferences(final DomElement genericDomValue,
                                                 PsiElement element,
                                                 @NotNull final Condition<PsiFileSystemItem> fileFilter) {
+    return createReferences(genericDomValue, element, fileFilter, false);
+  }
+
+  public static PsiReference[] createReferences(final DomElement genericDomValue,
+                                                PsiElement element,
+                                                @NotNull final Condition<PsiFileSystemItem> fileFilter, boolean isAbsolutePath) {
     ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(element);
     TextRange range = manipulator.getRangeInElement(element);
     String text = range.substring(element.getText());
@@ -88,7 +96,19 @@
             String resolvedText = model == null ? text : MavenPropertyResolver.resolve(text, model);
 
             if (resolvedText.equals(text)) {
-              super.innerResolveInContext(resolvedText, context, result, caseSensitive);
+              if (getIndex() == 0 && resolvedText.length() == 2 && resolvedText.charAt(1) == ':') {
+                // it's root on windows, e.g. "C:"
+                VirtualFile file = LocalFileSystem.getInstance().findFileByPath(resolvedText + '/');
+                if (file != null) {
+                  PsiDirectory psiDirectory = context.getManager().findDirectory(file);
+                  if (psiDirectory != null) {
+                    result.add(new PsiElementResolveResult(psiDirectory));
+                  }
+                }
+              }
+              else {
+                super.innerResolveInContext(resolvedText, context, result, caseSensitive);
+              }
             }
             else {
               VirtualFile contextFile = context.getVirtualFile();
@@ -117,6 +137,33 @@
       }
     };
 
+    if (isAbsolutePath) {
+      set.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, new Function<PsiFile, Collection<PsiFileSystemItem>>() {
+        @Override
+        public Collection<PsiFileSystemItem> fun(PsiFile file) {
+          VirtualFile virtualFile = file.getVirtualFile();
+
+          if (virtualFile == null) {
+            return FileReferenceSet.ABSOLUTE_TOP_LEVEL.fun(file);
+          }
+
+          while (true) {
+            VirtualFile parent = virtualFile.getParent();
+            if (parent == null) break;
+            virtualFile = parent;
+          }
+
+          PsiDirectory root = file.getManager().findDirectory(virtualFile);
+
+          if (root == null) {
+            return FileReferenceSet.ABSOLUTE_TOP_LEVEL.fun(file);
+          }
+
+          return Collections.<PsiFileSystemItem>singletonList(root);
+        }
+      });
+    }
+
     return set.getAllReferences();
   }
 
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 31380d2..69cd93e 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
@@ -298,7 +298,7 @@
           return false;
         }
 
-        manager.addManagedFiles(pomFiles);
+        manager.addManagedFilesOrUnignore(pomFiles);
 
         return true;
       }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java
index defe2bf..047fc82 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java
@@ -1,10 +1,10 @@
 package org.jetbrains.idea.maven.plugins.api;
 
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SingletonInstancesCache;
 import org.jdom.Element;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.maven.model.MavenPlugin;
-import org.jetbrains.plugins.groovy.util.ClassInstanceCache;
 
 import java.util.Collection;
 import java.util.List;
@@ -54,7 +54,8 @@
       }
 
       if (descriptor.propertyGenerator != null) {
-        MavenPropertiesGenerator generator = ClassInstanceCache.getInstance(descriptor.propertyGenerator, descriptor.getLoaderForClass());
+        MavenPropertiesGenerator generator = SingletonInstancesCache
+          .getInstance(descriptor.propertyGenerator, descriptor.getLoaderForClass());
         generator.generate(modelProperties, goal, plugin, cfgElement);
       }
     }
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 5564984..678f811 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
@@ -484,6 +484,11 @@
     addManagedFilesWithProfiles(files, Collections.<String>emptyList());
   }
 
+  public void addManagedFilesOrUnignore(@NotNull List<VirtualFile> files) {
+    removeIgnoredFilesPaths(MavenUtil.collectPaths(files));
+    addManagedFiles(files);
+  }
+
   public void removeManagedFiles(@NotNull List<VirtualFile> files) {
     myWatcher.removeManagedFiles(files);
   }
@@ -629,6 +634,11 @@
     myProjectsTree.setIgnoredFilesPaths(paths);
   }
 
+  public void removeIgnoredFilesPaths(final Collection<String> paths) {
+    if (!isInitialized()) return;
+    myProjectsTree.removeIgnoredFilesPaths(paths);
+  }
+
   public boolean getIgnoredState(@NotNull MavenProject project) {
     if (!isInitialized()) return false;
     return myProjectsTree.getIgnoredState(project);
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 721908c..81eb778 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
@@ -112,7 +112,16 @@
       @Override
       public void moduleRemoved(Project project, Module module) {
         MavenProject mavenProject = myManager.findProject(module);
-        if (mavenProject != null) myManager.setIgnoredState(Collections.singletonList(mavenProject), true);
+        if (mavenProject != null && !myManager.isIgnored(mavenProject)) {
+          VirtualFile file = mavenProject.getFile();
+
+          if (myManager.isManagedFile(file) && myManager.getModules(mavenProject).isEmpty()) {
+            myManager.removeManagedFiles(Collections.singletonList(file));
+          }
+          else {
+            myManager.setIgnoredState(Collections.singletonList(mavenProject), true);
+          }
+        }
       }
 
       @Override
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 3a39929..a11d9cb 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
@@ -57,7 +57,7 @@
   private final Lock myStructureWriteLock = myStructureLock.writeLock();
 
   // TODO replace with sets
-  private volatile List<String> myManagedFilesPaths = new ArrayList<String>();
+  private volatile Set<String> myManagedFilesPaths = new LinkedHashSet<String>();
   private volatile List<String> myIgnoredFilesPaths = new ArrayList<String>();
   private volatile List<String> myIgnoredFilesPatterns = new ArrayList<String>();
   private volatile Pattern myIgnoredFilesPatternsCache;
@@ -91,7 +91,7 @@
     try {
       try {
         if (!STORAGE_VERSION.equals(in.readUTF())) return null;
-        result.myManagedFilesPaths = readCollection(in, new ArrayList<String>());
+        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>());
@@ -190,7 +190,7 @@
 
   public void resetManagedFilesPathsAndProfiles(List<String> paths, Collection<String> profiles) {
     synchronized (myStateLock) {
-      myManagedFilesPaths = new ArrayList<String>(paths);
+      myManagedFilesPaths = new LinkedHashSet<String>(paths);
     }
     setExplicitProfiles(profiles);
   }
@@ -243,6 +243,14 @@
     });
   }
 
+  public void removeIgnoredFilesPaths(final Collection<String> paths) {
+    doChangeIgnoreStatus(new Runnable() {
+      public void run() {
+        myIgnoredFilesPaths.removeAll(paths);
+      }
+    });
+  }
+
   public boolean getIgnoredState(MavenProject project) {
     synchronized (myStateLock) {
       return myIgnoredFilesPaths.contains(project.getPath());
@@ -672,10 +680,12 @@
   }
 
   public boolean isManagedFile(String path) {
-    for (String each : getManagedFilesPaths()) {
-      if (FileUtil.pathsEqual(each, path)) return true;
+    synchronized (myStateLock) {
+      for (String each : myManagedFilesPaths) {
+        if (FileUtil.pathsEqual(each, path)) return true;
+      }
+      return false;
     }
-    return false;
   }
 
   public boolean isPotentialProject(String path) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddFileAsMavenProjectAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddFileAsMavenProjectAction.java
index a7d6863..c2980a0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddFileAsMavenProjectAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddFileAsMavenProjectAction.java
@@ -31,7 +31,7 @@
   public void actionPerformed(AnActionEvent e) {
     final DataContext context = e.getDataContext();
     MavenProjectsManager manager = MavenActionUtil.getProjectsManager(context);
-    manager.addManagedFiles(Collections.singletonList(getSelectedFile(context)));
+    manager.addManagedFilesOrUnignore(Collections.singletonList(getSelectedFile(context)));
   }
 
   @Override
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddManagedFilesAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddManagedFilesAction.java
index f4b12b8..4ebf81b1 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddManagedFilesAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/AddManagedFilesAction.java
@@ -50,6 +50,6 @@
     VirtualFile[] files = FileChooser.chooseFiles(singlePomSelection, project, fileToSelect);
     if (files.length == 0) return;
 
-    manager.addManagedFiles(Arrays.asList(files));
+    manager.addManagedFilesOrUnignore(Arrays.asList(files));
   }
 }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java
index 01ea1fe..ec8b82c 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java
@@ -66,7 +66,7 @@
 
         VirtualFile existingPom = root.findChild(MavenConstants.POM_XML);
         if (existingPom != null) {
-          MavenProjectsManager.getInstance(module.getProject()).addManagedFiles(Collections.singletonList(existingPom));
+          MavenProjectsManager.getInstance(module.getProject()).addManagedFilesOrUnignore(Collections.singletonList(existingPom));
         }
         else {
           prepareProjectStructure(model, root);
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 f951597..7494bab 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
@@ -117,7 +117,7 @@
 
     if (myAggregatorProject == null) {
       MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
-      manager.addManagedFiles(Collections.singletonList(pom));
+      manager.addManagedFilesOrUnignore(Collections.singletonList(pom));
     }
 
     if (myArchetype == null) {
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 a516632..53a486f 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
@@ -126,6 +126,9 @@
     }
 
     MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
+
+    manager.setIgnoredState(getParameters().mySelectedProjects, false);
+
     manager.addManagedFilesWithProfiles(MavenUtil.collectFiles(getParameters().mySelectedProjects), selectedProfiles);
     manager.waitForReadingCompletion();
 
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
index 6185881..2b257d9 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
@@ -31,6 +31,7 @@
 import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
 import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -661,6 +662,30 @@
     checkHighlighting();
   }
 
+  public void testCompletionSystemScopeDependenciesWithProperties() throws Throwable {
+    String libPath = myIndicesFixture.getRepositoryHelper().getTestDataPath("local1/junit/junit/4.0/junit-4.0.jar");
+
+    createProjectPom("<groupId>test</groupId>" +
+                     "<artifactId>project</artifactId>" +
+                     "<version>1</version>" +
+
+                     "<properties>" +
+                     "  <depDir>" + new File(libPath).getParent() + "</depDir>" +
+                     "</properties>" +
+
+                     "<dependencies>" +
+                     "  <dependency>" +
+                     "    <groupId>xxx</groupId>" +
+                     "    <artifactId>xxx</artifactId>" +
+                     "    <version>xxx</version>" +
+                     "    <scope>system</scope>" +
+                     "    <systemPath>${depDir}/<caret></systemPath>" +
+                     "  </dependency>" +
+                     "</dependencies>");
+
+    assertCompletionVariants(myProjectPom, "junit-4.0.jar");
+  }
+
   public void testResolvingSystemScopeDependenciesFromSystemPath() throws Throwable {
     String libPath = myIndicesFixture.getRepositoryHelper().getTestDataPath("local1/junit/junit/4.0/junit-4.0.jar");
 
diff --git a/plugins/svn4idea/bindSvn/bindSvn.iml b/plugins/svn4idea/bindSvn/bindSvn.iml
deleted file mode 100644
index 846587c..0000000
--- a/plugins/svn4idea/bindSvn/bindSvn.iml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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="platform-api" />
-    <orderEntry type="module" module-name="vcs-api" />
-    <orderEntry type="module-library">
-      <library>
-        <CLASSES>
-          <root url="jar://$MODULE_DIR$/lib/javahl.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES>
-          <root url="jar://$MODULE_DIR$/lib/javahlsrc.zip!/src" />
-        </SOURCES>
-      </library>
-    </orderEntry>
-  </component>
-</module>
-
diff --git a/plugins/svn4idea/bindSvn/lib/javahl.jar b/plugins/svn4idea/bindSvn/lib/javahl.jar
deleted file mode 100644
index a0c5370..0000000
--- a/plugins/svn4idea/bindSvn/lib/javahl.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/svn4idea/bindSvn/lib/javahlsrc.zip b/plugins/svn4idea/bindSvn/lib/javahlsrc.zip
deleted file mode 100644
index 9c50118..0000000
--- a/plugins/svn4idea/bindSvn/lib/javahlsrc.zip
+++ /dev/null
Binary files differ
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java
deleted file mode 100644
index c155b78..0000000
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java
+++ /dev/null
@@ -1,925 +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 org.jetbrains.idea.svn;
-
-import org.tigris.subversion.javahl.*;
-
-import java.io.OutputStream;
-import java.util.Map;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/5/13
- * Time: 3:08 PM
- */
-public class SvnBindClient implements SVNClientInterface {
-  private final String myExecutablePath;
-  private CommitEventHandler myHandler;
-  private AuthenticationCallback myAuthenticationCallback;
-
-  public SvnBindClient(String path) {
-    myExecutablePath = path;
-  }
-
-  @Override
-  public void dispose() {
-  }
-
-  @Override
-  public Version getVersion() {
-    // todo real version
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getAdminDirectoryName() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public boolean isAdminDirectory(String name) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getLastPath() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Status singleStatus(String path, boolean onServer) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Status[] status(String path, boolean descend, boolean onServer, boolean getAll) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore, boolean ignoreExternals)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void status(String path,
-                     int depth,
-                     boolean onServer,
-                     boolean getAll,
-                     boolean noIgnore,
-                     boolean ignoreExternals,
-                     String[] changelists,
-                     StatusCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public DirEntry[] list(String url, Revision revision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public DirEntry[] list(String url, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void list(String url,
-                   Revision revision,
-                   Revision pegRevision,
-                   int depth,
-                   int direntFields,
-                   boolean fetchLocks,
-                   ListCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void username(String username) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void password(String password) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setPrompt(PromptUserPassword prompt) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy, boolean discoverPath)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public LogMessage[] logMessages(String path,
-                                  Revision revisionStart,
-                                  Revision revisionEnd,
-                                  boolean stopOnCopy,
-                                  boolean discoverPath,
-                                  long limit) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void logMessages(String path,
-                          Revision pegRevision,
-                          Revision revisionStart,
-                          Revision revisionEnd,
-                          boolean stopOnCopy,
-                          boolean discoverPath,
-                          boolean includeMergedRevisions,
-                          String[] revProps,
-                          long limit,
-                          LogMessageCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void logMessages(String path,
-                          Revision pegRevision,
-                          RevisionRange[] ranges,
-                          boolean stopOnCopy,
-                          boolean discoverPath,
-                          boolean includeMergedRevisions,
-                          String[] revProps,
-                          long limit,
-                          LogMessageCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long checkout(String moduleName, String destPath, Revision revision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long checkout(String moduleName,
-                       String destPath,
-                       Revision revision,
-                       Revision pegRevision,
-                       boolean recurse,
-                       boolean ignoreExternals) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long checkout(String moduleName,
-                       String destPath,
-                       Revision revision,
-                       Revision pegRevision,
-                       int depth,
-                       boolean ignoreExternals,
-                       boolean allowUnverObstructions) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void notification(Notify notify) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void notification2(Notify2 notify) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setConflictResolver(ConflictResolverCallback listener) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setProgressListener(ProgressListener listener) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void commitMessageHandler(CommitMessage messageHandler) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void remove(String[] path, String message, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void remove(String[] path, String message, boolean force, boolean keepLocal, Map revpropTable) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void revert(String path, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void revert(String path, int depth, String[] changelists) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void add(String path, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void add(String path, boolean recurse, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void add(String path, int depth, boolean force, boolean noIgnores, boolean addParents) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long update(String path, Revision revision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long[] update(String[] path, Revision revision, boolean recurse, boolean ignoreExternals) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long update(String path,
-                     Revision revision,
-                     int depth,
-                     boolean depthIsSticky,
-                     boolean ignoreExternals,
-                     boolean allowUnverObstructions) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long[] update(String[] path,
-                       Revision revision,
-                       int depth,
-                       boolean depthIsSticky,
-                       boolean ignoreExternals,
-                       boolean allowUnverObstructions) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long commit(String[] path, String message, boolean recurse) throws ClientException {
-    return commit(path, message, recurse? 3 : 0, false, false, null, null);
-  }
-
-  @Override
-  public long commit(String[] path, String message, boolean recurse, boolean noUnlock) throws ClientException {
-    return commit(path, message, recurse? 3 : 0, noUnlock, false, null, null);
-  }
-
-  @Override
-  public long commit(String[] path,
-                     String message,
-                     int depth,
-                     boolean noUnlock,
-                     boolean keepChangelist,
-                     String[] changelists,
-                     Map revpropTable) throws ClientException {
-    final long commit = new SvnCommitRunner(myExecutablePath, myHandler, myAuthenticationCallback).
-        commit(path, message, depth, noUnlock, keepChangelist, changelists, revpropTable);
-    if (commit < 0) {
-      throw new BindClientException("Wrong committed revision number: " + commit, null, -1);
-    }
-    return commit;
-  }
-
-  @Override
-  public void copy(CopySource[] sources,
-                   String destPath,
-                   String message,
-                   boolean copyAsChild,
-                   boolean makeParents,
-                   boolean ignoreExternals,
-                   Map revpropTable) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void copy(CopySource[] sources, String destPath, String message, boolean copyAsChild, boolean makeParents, Map revpropTable)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void copy(String srcPath, String destPath, String message, Revision revision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void move(String[] srcPaths,
-                   String destPath,
-                   String message,
-                   boolean force,
-                   boolean moveAsChild,
-                   boolean makeParents,
-                   Map revpropTable) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void move(String srcPath, String destPath, String message, Revision ignored, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void move(String srcPath, String destPath, String message, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void mkdir(String[] path, String message, boolean makeParents, Map revpropTable) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void mkdir(String[] path, String message) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void cleanup(String path) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void resolve(String path, int depth, int conflictResult) throws SubversionException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void resolved(String path, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long doExport(String srcPath, String destPath, Revision revision, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long doExport(String srcPath,
-                       String destPath,
-                       Revision revision,
-                       Revision pegRevision,
-                       boolean force,
-                       boolean ignoreExternals,
-                       boolean recurse,
-                       String nativeEOL) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long doExport(String srcPath,
-                       String destPath,
-                       Revision revision,
-                       Revision pegRevision,
-                       boolean force,
-                       boolean ignoreExternals,
-                       int depth,
-                       String nativeEOL) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long doSwitch(String path, String url, Revision revision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public long doSwitch(String path,
-                       String url,
-                       Revision revision,
-                       Revision pegRevision,
-                       int depth,
-                       boolean depthIsSticky,
-                       boolean ignoreExternals,
-                       boolean allowUnverObstructions) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void doImport(String path, String url, String message, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void doImport(String path,
-                       String url,
-                       String message,
-                       int depth,
-                       boolean noIgnore,
-                       boolean ignoreUnknownNodeTypes,
-                       Map revpropTable) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String[] suggestMergeSources(String path, Revision pegRevision) throws SubversionException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void merge(String path1, Revision revision1, String path2, Revision revision2, String localPath, boolean force, boolean recurse)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void merge(String path1,
-                    Revision revision1,
-                    String path2,
-                    Revision revision2,
-                    String localPath,
-                    boolean force,
-                    boolean recurse,
-                    boolean ignoreAncestry,
-                    boolean dryRun) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void merge(String path1,
-                    Revision revision1,
-                    String path2,
-                    Revision revision2,
-                    String localPath,
-                    boolean force,
-                    int depth,
-                    boolean ignoreAncestry,
-                    boolean dryRun,
-                    boolean recordOnly) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void merge(String path,
-                    Revision pegRevision,
-                    Revision revision1,
-                    Revision revision2,
-                    String localPath,
-                    boolean force,
-                    boolean recurse,
-                    boolean ignoreAncestry,
-                    boolean dryRun) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void merge(String path,
-                    Revision pegRevision,
-                    RevisionRange[] revisions,
-                    String localPath,
-                    boolean force,
-                    int depth,
-                    boolean ignoreAncestry,
-                    boolean dryRun,
-                    boolean recordOnly) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void mergeReintegrate(String path, Revision pegRevision, String localPath, boolean dryRun) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Mergeinfo getMergeinfo(String path, Revision pegRevision) throws SubversionException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void getMergeinfoLog(int kind,
-                              String pathOrUrl,
-                              Revision pegRevision,
-                              String mergeSourceUrl,
-                              Revision srcPegRevision,
-                              boolean discoverChangedPaths,
-                              int depth,
-                              String[] revProps,
-                              LogMessageCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void getMergeinfoLog(int kind,
-                              String pathOrUrl,
-                              Revision pegRevision,
-                              String mergeSourceUrl,
-                              Revision srcPegRevision,
-                              boolean discoverChangedPaths,
-                              String[] revProps,
-                              LogMessageCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target1, Revision revision1, String target2, Revision revision2, String outFileName, boolean recurse)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target1,
-                   Revision revision1,
-                   String target2,
-                   Revision revision2,
-                   String outFileName,
-                   boolean recurse,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target1,
-                   Revision revision1,
-                   String target2,
-                   Revision revision2,
-                   String relativeToDir,
-                   String outFileName,
-                   int depth,
-                   String[] changelists,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force,
-                   boolean copiesAsAdds) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target1,
-                   Revision revision1,
-                   String target2,
-                   Revision revision2,
-                   String relativeToDir,
-                   String outFileName,
-                   int depth,
-                   String[] changelists,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target,
-                   Revision pegRevision,
-                   Revision startRevision,
-                   Revision endRevision,
-                   String outFileName,
-                   boolean recurse,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target,
-                   Revision pegRevision,
-                   Revision startRevision,
-                   Revision endRevision,
-                   String relativeToDir,
-                   String outFileName,
-                   int depth,
-                   String[] changelists,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force,
-                   boolean copiesAsAdds) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diff(String target,
-                   Revision pegRevision,
-                   Revision startRevision,
-                   Revision endRevision,
-                   String relativeToDir,
-                   String outFileName,
-                   int depth,
-                   String[] changelists,
-                   boolean ignoreAncestry,
-                   boolean noDiffDeleted,
-                   boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diffSummarize(String target1,
-                            Revision revision1,
-                            String target2,
-                            Revision revision2,
-                            int depth,
-                            String[] changelists,
-                            boolean ignoreAncestry,
-                            DiffSummaryReceiver receiver) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void diffSummarize(String target,
-                            Revision pegRevision,
-                            Revision startRevision,
-                            Revision endRevision,
-                            int depth,
-                            String[] changelists,
-                            boolean ignoreAncestry,
-                            DiffSummaryReceiver receiver) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData[] properties(String path) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData[] properties(String path, Revision revision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData[] properties(String path, Revision revision, Revision pegRevision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void properties(String path, Revision revision, Revision pegRevision, int depth, String[] changelists, ProplistCallback callback)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertySet(String path, String name, String value, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertySet(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertySet(String path, String name, byte[] value, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertySet(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertySet(String path, String name, String value, int depth, String[] changelists, boolean force, Map revpropTable)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyRemove(String path, String name, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyRemove(String path, String name, int depth, String[] changelists) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyCreate(String path, String name, String value, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyCreate(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyCreate(String path, String name, byte[] value, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyCreate(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void propertyCreate(String path, String name, String value, int depth, String[] changelists, boolean force)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData revProperty(String path, String name, Revision rev) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData[] revProperties(String path, Revision rev) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setRevProperty(String path, String name, Revision rev, String value, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setRevProperty(String path, String name, Revision rev, String value, String originalValue, boolean force)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData propertyGet(String path, String name) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData propertyGet(String path, String name, Revision revision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public PropertyData propertyGet(String path, String name, Revision revision, Revision pegRevision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public byte[] fileContent(String path, Revision revision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public byte[] fileContent(String path, Revision revision, Revision pegRevision) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void streamFileContent(String path, Revision revision, Revision pegRevision, int bufferSize, OutputStream stream)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void relocate(String from, String to, String path, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public byte[] blame(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void blame(String path, Revision revisionStart, Revision revisionEnd, BlameCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void blame(String path, Revision pegRevision, Revision revisionStart, Revision revisionEnd, BlameCallback callback)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void blame(String path,
-                    Revision pegRevision,
-                    Revision revisionStart,
-                    Revision revisionEnd,
-                    boolean ignoreMimeType,
-                    boolean includeMergedRevisions,
-                    BlameCallback2 callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void blame(String path,
-                    Revision pegRevision,
-                    Revision revisionStart,
-                    Revision revisionEnd,
-                    boolean ignoreMimeType,
-                    boolean includeMergedRevisions,
-                    BlameCallback3 callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setConfigDirectory(String configDir) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getConfigDirectory() throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void cancelOperation() throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Info info(String path) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void addToChangelist(String[] paths, String changelist, int depth, String[] changelists) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void removeFromChangelists(String[] paths, int depth, String[] changelists) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void getChangelists(String rootPath, String[] changelists, int depth, ChangelistCallback callback) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void lock(String[] path, String comment, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void unlock(String[] path, boolean force) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Info2[] info2(String pathOrUrl, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void info2(String pathOrUrl, Revision revision, Revision pegRevision, int depth, String[] changelists, InfoCallback callback)
-    throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getVersionInfo(String path, String trailUrl, boolean lastChanged) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void upgrade(String path) throws ClientException {
-    throw new UnsupportedOperationException();
-  }
-
-  public void setHandler(CommitEventHandler handler) {
-    myHandler = handler;
-  }
-
-  public void setAuthenticationCallback(AuthenticationCallback authenticationCallback) {
-    myAuthenticationCallback = authenticationCallback;
-  }
-}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java
deleted file mode 100644
index f4e0f4c..0000000
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java
+++ /dev/null
@@ -1,121 +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 org.jetbrains.idea.svn.status;
-
-import org.apache.subversion.javahl.types.Lock;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Date;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/21/12
- * Time: 2:33 PM
- */
-public class LockWrapper {
-  private String myPath;
-  private String myID;
-  private String myOwner;
-  private String myComment;
-  private Date myCreationDate;
-  private Date myExpirationDate;
-
-  public LockWrapper(String path, String ID, String owner, String comment, Date creationDate, Date expirationDate) {
-    myPath = path;
-    myID = ID;
-    myOwner = owner;
-    myComment = comment;
-    myCreationDate = creationDate;
-    myExpirationDate = expirationDate;
-  }
-
-  public LockWrapper() {
-  }
-
-  public String getPath() {
-    return myPath;
-  }
-
-  public void setPath(String path) {
-    myPath = path;
-  }
-
-  public String getID() {
-    return myID;
-  }
-
-  public void setID(String ID) {
-    myID = ID;
-  }
-
-  public String getOwner() {
-    return myOwner;
-  }
-
-  public void setOwner(String owner) {
-    myOwner = owner;
-  }
-
-  public String getComment() {
-    return myComment;
-  }
-
-  public void setComment(String comment) {
-    myComment = comment;
-  }
-
-  public Date getCreationDate() {
-    return myCreationDate;
-  }
-
-  public void setCreationDate(Date creationDate) {
-    myCreationDate = creationDate;
-  }
-
-  public Date getExpirationDate() {
-    return myExpirationDate;
-  }
-
-  public void setExpirationDate(Date expirationDate) {
-    myExpirationDate = expirationDate;
-  }
-
-  public org.tigris.subversion.javahl.Lock create() {
-    final Date creation = getCreationDate();
-    final Date expiration = getExpirationDate();
-    final Lock newLock = new Lock(getOwner(), getPath(), getID(), getComment(), creation == null ? 0 : creation.getTime(),
-                               expiration == null ? 0 : expiration.getTime());
-    try {
-      final Constructor<org.tigris.subversion.javahl.Lock> constructor = org.tigris.subversion.javahl.Lock.class.getConstructor(Lock.class);
-      constructor.setAccessible(true);
-      return constructor.newInstance(newLock);
-    }
-    catch (NoSuchMethodException e) {
-      throw new RuntimeException(e);
-    }
-    catch (InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-    catch (InstantiationException e) {
-      throw new RuntimeException(e);
-    }
-    catch (IllegalAccessException e) {
-      throw new RuntimeException(e);
-    }
-  }
-}
diff --git a/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java b/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java
deleted file mode 100644
index f8acc17..0000000
--- a/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java
+++ /dev/null
@@ -1,47 +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 org.tigris.subversion.javahl;
-
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/25/13
- * Time: 6:29 PM
- */
-public class BindClientException extends ClientException {
-  private Throwable myCause;
-
-  public BindClientException(String message, String source, int aprError) {
-    super(message, source, aprError);
-  }
-
-  public BindClientException(org.apache.subversion.javahl.ClientException ex) {
-    super(ex);
-  }
-
-  public static BindClientException create(@NotNull final Throwable t, final int code) {
-    final BindClientException exception = new BindClientException(t.getMessage(), null, code);
-    exception.myCause = t;
-    return exception;
-  }
-
-  @Override
-  public Throwable getCause() {
-    return myCause;
-  }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/ForNestedRootChecker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/ForNestedRootChecker.java
index 4559a3e..6a62276 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/ForNestedRootChecker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/ForNestedRootChecker.java
@@ -49,11 +49,9 @@
 
   private static class UrlConstructor {
     final SvnVcs myVcs;
-    final SVNWCClient myClient;
 
     private UrlConstructor(final SvnVcs vcs) {
       myVcs = vcs;
-      myClient = myVcs.createWCClient();
     }
 
     @Nullable
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
index 6cd0df2..5ca7f9e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
@@ -123,52 +123,31 @@
 
   @Nullable
   private WorkingCopy calculateRoot(final VirtualFile root) {
+    File workingCopyRoot = SvnUtil.getWorkingCopyRootNew(new File(root.getPath()));
     WorkingCopy workingCopy = null;
-    final File ioFile = new File(root.getPath());
-    File workingCopyRoot = null;
-    try {
-      workingCopyRoot = SVNWCUtil.getWorkingCopyRoot(ioFile, true);
-      if (workingCopyRoot != null) {
-        // ok to use low-level 1.6 API, 1.7 is checked below
-        SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
-        try {
-          wcAccess.probeOpen(workingCopyRoot, false, 0);
-          SVNEntry entry = wcAccess.getVersionedEntry(workingCopyRoot, false);
-          final SVNURL url = entry.getSVNURL();
-          if (url != null) {
-            workingCopy = new WorkingCopy(workingCopyRoot, url, false);
-          }
-        } finally {
-          wcAccess.close();
-        }
+
+    if (workingCopyRoot != null) {
+      final SVNInfo svnInfo = myVcs.getInfo(workingCopyRoot);
+
+      if (svnInfo != null && svnInfo.getURL() != null) {
+        workingCopy = new WorkingCopy(workingCopyRoot, svnInfo.getURL(), true);
       }
     }
-    catch (SVNException e) {
-      //
-    }
-    if (workingCopy == null) {
-      workingCopyRoot = SvnUtil.getWcCopyRootIf17(ioFile, null);
-      if (workingCopyRoot != null) {
-        final SVNInfo svnInfo;
-        try {
-          svnInfo = SvnVcs.getInstance(myProject).createWCClient().doInfo(workingCopyRoot, SVNRevision.UNDEFINED);
-          workingCopy = new WorkingCopy(workingCopyRoot, svnInfo.getURL(), true);
-        }
-        catch (SVNException e) {
-          //
-        }
-      }
-    }
+
+    return registerWorkingCopy(root, workingCopy);
+  }
+
+  private WorkingCopy registerWorkingCopy(@NotNull VirtualFile root, @Nullable WorkingCopy resolvedWorkingCopy) {
     synchronized (myLock) {
-      if (workingCopy == null) {
+      if (resolvedWorkingCopy == null) {
         myRootMapping.remove(root);
         myUnversioned.add(root);
       } else {
         myUnversioned.remove(root);
-        myRootMapping.put(root, workingCopy);
+        myRootMapping.put(root, resolvedWorkingCopy);
       }
     }
-    return workingCopy;
+    return resolvedWorkingCopy;
   }
 
   public void clear() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java
index b4fd104..29e8742 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java
@@ -36,6 +36,7 @@
  * Date: 10/19/12
  * Time: 12:09 PM
  */
+// TODO: Such locking functionality is not required anymore. Likely to be removed (together with SvnProxies).
 public abstract class SvnAbstractWriteOperationLocks {
   private final long myTimeout;
   private final static Map<String, Lock> myLockMap = new HashMap<String, Lock>();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
index 8a94f00..4efcce6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
@@ -350,7 +350,9 @@
     }
     SvnInteractiveAuthenticationProvider.clearCallState();
     try {
+      // start svnkit authentication cycle
       SvnVcs.getInstance(project).createWCClient(manager).doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
+      //SvnVcs.getInstance(project).getInfo(url, SVNRevision.HEAD, manager);
     } catch (SVNAuthenticationException e) {
       log(e);
       return false;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
index c306386..61a5bb2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
@@ -537,6 +537,7 @@
 dialog.show.svn.map.table.version15.text=1.5
 dialog.show.svn.map.table.version16.text=1.6
 dialog.show.svn.map.table.version17.text=1.7
+dialog.show.svn.map.table.version18.text=1.8
 action.change.wcopy.format.task.title=Convert working copy format
 action.change.wcopy.format.task.progress.text=Converting working copy at {0} format from {1} to {2}
 action.change.wcopy.format.after.change.settings=Selected working copy format ({0}) is older than upgrade mode selected in Project Settings ({1}).\
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
index dc8cbb1..b28ebd5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
@@ -85,7 +85,7 @@
       statusReceiver.addListener(context);
       statusReceiver.addListener(nestedCopiesBuilder);
 
-      final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs.getProject(), statusReceiver.getMulticaster(), partner);
+      final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs, statusReceiver.getMulticaster(), partner);
 
       for (FilePath path : zipper.getRecursiveDirs()) {
         walker.go(path, SVNDepth.INFINITY);
@@ -180,7 +180,7 @@
   public void getChanges(final FilePath path, final boolean recursive, final ChangelistBuilder builder) throws SVNException {
     final SvnChangeProviderContext context = new SvnChangeProviderContext(myVcs, builder, null);
     final StatusWalkerPartnerImpl partner = new StatusWalkerPartnerImpl(myVcs, ProgressManager.getInstance().getProgressIndicator());
-    final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs.getProject(), context, partner);
+    final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs, context, partner);
     walker.go(path, recursive ? SVNDepth.INFINITY : SVNDepth.IMMEDIATES);
     processCopiedAndDeleted(context, null);
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
index 40c34d3..9689dce 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
@@ -259,23 +259,15 @@
   
   public void addModifiedNotSavedChange(final VirtualFile file) throws SVNException {
     final FilePath filePath = new FilePathImpl(file);
-    final SVNInfo svnInfo;
-    try {
-      svnInfo = myVcs.createWCClient().doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
+    final SVNInfo svnInfo = myVcs.getInfo(file);
+
+    if (svnInfo != null) {
+      final SVNStatus svnStatus = new SVNStatus();
+      svnStatus.setRevision(svnInfo.getRevision());
+      myChangelistBuilder.processChangeInList(
+        createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, svnInfo.getRevision()), CurrentContentRevision.create(filePath),
+                     FileStatus.MODIFIED, svnStatus), (String)null, SvnVcs.getKey());
     }
-    catch (SVNException e) {
-      final SVNErrorCode errorCode = e.getErrorMessage().getErrorCode();
-      if (SVNErrorCode.WC_PATH_NOT_FOUND.equals(errorCode) ||
-          SVNErrorCode.UNVERSIONED_RESOURCE.equals(errorCode) || SVNErrorCode.WC_NOT_WORKING_COPY.equals(errorCode)) {
-        return;
-      }
-      throw e;
-    }
-    final SVNStatus svnStatus = new SVNStatus();
-    svnStatus.setRevision(svnInfo.getRevision());
-    myChangelistBuilder.processChangeInList(createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, svnInfo.getRevision()),
-                                             CurrentContentRevision.create(filePath), FileStatus.MODIFIED, svnStatus), (String) null,
-                                            SvnVcs.getKey());
   }
 
   private void checkSwitched(final FilePath filePath, final ChangelistBuilder builder, final SVNStatus status,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangelistListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangelistListener.java
index ee326a4..51d5dc4 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangelistListener.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangelistListener.java
@@ -176,11 +176,9 @@
   }
 
   @Nullable
-  public static String getCurrentMapping(final Project project, final File file) {
-    final SvnVcs vcs = SvnVcs.getInstance(project);
-    final SVNStatusClient statusClient = vcs.createStatusClient();
+  public static String getCurrentMapping(final SvnVcs vcs, final File file) {
     try {
-      final SVNStatus status = statusClient.doStatus(file, false);
+      final SVNStatus status = vcs.getFactory(file).createStatusClient().doStatus(file, false);
       return status == null ? null : status.getChangelistName();
     }
     catch (SVNException e) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form
index e4f0e7c..55f7512 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form
@@ -18,7 +18,7 @@
         <properties/>
         <border type="none"/>
         <children>
-          <grid id="2ae3a" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+          <grid id="2ae3a" layout-manager="GridLayoutManager" row-count="5" 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>
               <tabbedpane title="General"/>
@@ -29,7 +29,7 @@
               <grid id="a4729" 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>
-                  <grid row="3" column="0" row-span="1" col-span="3" 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="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <border type="none"/>
@@ -87,7 +87,7 @@
               </grid>
               <component id="df054" class="javax.swing.JCheckBox" binding="myUseDefaultCheckBox">
                 <constraints>
-                  <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties>
                   <text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="checkbox.configure.use.system.default.configuration.directory"/>
@@ -96,7 +96,7 @@
               <grid id="137aa" 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="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <border type="none"/>
@@ -123,36 +123,29 @@
               </grid>
               <hspacer id="e8f24">
                 <constraints>
-                  <grid row="5" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                  <grid row="4" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
                 </constraints>
               </hspacer>
               <vspacer id="aa6b2">
                 <constraints>
-                  <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
                 </constraints>
               </vspacer>
-              <component id="300b5" 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 value="Subversion 1.7 Acceleration"/>
-                </properties>
-              </component>
               <grid id="12735" 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="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties/>
                 <border type="none"/>
                 <children>
                   <component id="3ecd1" class="com.intellij.ui.components.JBCheckBox" binding="myWithCommandLineClient">
                     <constraints>
-                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" 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"/>
                     </constraints>
                     <properties>
-                      <text value="with command line client:"/>
+                      <margin top="2" left="3" bottom="2" right="3"/>
+                      <text value="Use command line client:"/>
                     </properties>
                   </component>
                   <component id="44a8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myCommandLineClient">
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
index 38c099b..cff64be 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
@@ -31,6 +31,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc.SVNStatus;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.File;
 import java.io.IOException;
@@ -113,7 +114,8 @@
     if (lock.exists()) {
       throw new VcsException("Can not access file base revision contents: administrative area is locked");
     }
-    return SvnUtil.getFileContents(myVcs, file.getPath(), false, myUseBaseRevision ? SVNRevision.BASE : myRevision, SVNRevision.UNDEFINED);
+    return SvnUtil.getFileContents(myVcs, SvnTarget.fromFile(file), myUseBaseRevision ? SVNRevision.BASE : myRevision,
+                                   SVNRevision.UNDEFINED);
   }
 
   @NotNull
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
index 2a8a00a..813d41c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.actions.VcsContextFactory;
 import com.intellij.openapi.vcs.changes.ContentRevision;
 import com.intellij.openapi.vcs.diff.DiffMixin;
@@ -26,8 +27,10 @@
 import com.intellij.openapi.vcs.history.VcsRevisionDescriptionImpl;
 import com.intellij.openapi.vcs.history.VcsRevisionNumber;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
 import org.jetbrains.idea.svn.history.LatestExistentSearcher;
 import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNPropertyValue;
 import org.tmatesoft.svn.core.SVNURL;
 import org.tmatesoft.svn.core.wc.*;
 
@@ -43,19 +46,12 @@
   }
 
   public VcsRevisionNumber getCurrentRevision(VirtualFile file) {
-    final SVNWCClient client = myVcs.createWCClient();
-    try {
-      final SVNInfo svnInfo = client.doInfo(new File(file.getPresentableUrl()), SVNRevision.UNDEFINED);
-      if (svnInfo == null) return null;
-      if (SVNRevision.UNDEFINED.equals(svnInfo.getCommittedRevision()) && svnInfo.getCopyFromRevision() != null) {
-        return new SvnRevisionNumber(svnInfo.getCopyFromRevision());
-      }
-      return new SvnRevisionNumber(svnInfo.getRevision());
+    final SVNInfo svnInfo = myVcs.getInfo(new File(file.getPresentableUrl()));
+    if (svnInfo == null) return null;
+    if (SVNRevision.UNDEFINED.equals(svnInfo.getCommittedRevision()) && svnInfo.getCopyFromRevision() != null) {
+      return new SvnRevisionNumber(svnInfo.getCopyFromRevision());
     }
-    catch (SVNException e) {
-      LOG.debug(e);    // most likely the file is unversioned
-      return null;
-    }
+    return new SvnRevisionNumber(svnInfo.getRevision());
   }
 
   @Override
@@ -65,53 +61,36 @@
   }
 
   private VcsRevisionDescription getCurrentRevisionDescription(File path) {
-    final SVNWCClient client = myVcs.createWCClient();
-    try {
-      final SVNInfo svnInfo = client.doInfo(path, SVNRevision.UNDEFINED);
-      
-      if (svnInfo.getCommittedRevision().equals(SVNRevision.UNDEFINED) && ! svnInfo.getCopyFromRevision().equals(SVNRevision.UNDEFINED) &&
+    final SVNInfo svnInfo = myVcs.getInfo(path);
+    if (svnInfo == null) {
+      return null;
+    }
+
+    if (svnInfo.getCommittedRevision().equals(SVNRevision.UNDEFINED) && !svnInfo.getCopyFromRevision().equals(SVNRevision.UNDEFINED) &&
         svnInfo.getCopyFromURL() != null) {
-        SVNURL copyUrl = svnInfo.getCopyFromURL();
-        String localPath = myVcs.getSvnFileUrlMapping().getLocalPath(copyUrl.toString());
-        if (localPath != null) {
-          return getCurrentRevisionDescription(new File(localPath));
-        }
+      SVNURL copyUrl = svnInfo.getCopyFromURL();
+      String localPath = myVcs.getSvnFileUrlMapping().getLocalPath(copyUrl.toString());
+      if (localPath != null) {
+        return getCurrentRevisionDescription(new File(localPath));
       }
-      final String message = getProperties(client, path);
+    }
+
+    try {
+      final String message = getCommitMessage(path);
       return new VcsRevisionDescriptionImpl(new SvnRevisionNumber(svnInfo.getCommittedRevision()), svnInfo.getCommittedDate(),
                                             svnInfo.getAuthor(), message);
     }
-    catch (SVNException e) {
+    catch (VcsException e) {
       LOG.debug(e);    // most likely the file is unversioned
       return null;
     }
   }
 
-  private String getProperties(SVNWCClient client, File path) throws SVNException {
-    final String[] message = new String[1];
-    client.doGetRevisionProperty(path, null, SVNRevision.BASE, new ISVNPropertyHandler() {
-      @Override
-      public void handleProperty(File path, SVNPropertyData property) throws SVNException {
-        handle(property);
-      }
+  private String getCommitMessage(File path) throws VcsException {
+    SVNPropertyData property =
+      myVcs.getFactory(path).createPropertyClient().getProperty(path, COMMIT_MESSAGE, true, null, SVNRevision.BASE);
 
-      @Override
-      public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
-        handle(property);
-      }
-
-      @Override
-      public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
-        handle(property);
-      }
-
-      private void handle(SVNPropertyData data) {
-        if (COMMIT_MESSAGE.equals(data.getName())) {
-          message[0] = data.getValue().getString();
-        }
-      }
-    });
-    return message[0];
+    return property != null ? SVNPropertyValue.getPropertyAsString(property.getValue()) : null;
   }
 
   private static ItemLatestState defaultResult() {
@@ -135,18 +114,45 @@
         return SvnContentRevision.createBaseRevision(myVcs, filePath, svnRevision);
       }
     }
+
     // not clear why we need it, with remote check..
-    final SVNStatusClient client = myVcs.createStatusClient();
-    try {
-      final SVNStatus svnStatus = client.doStatus(new File(selectedFile.getPresentableUrl()), false, false);
-      if (svnRevision.equals(svnStatus.getRevision())) {
+    SVNStatus svnStatus = getFileStatus(new File(selectedFile.getPresentableUrl()), false);
+    if (svnStatus != null && svnRevision.equals(svnStatus.getRevision())) {
         return SvnContentRevision.createBaseRevision(myVcs, filePath, svnRevision);
-      }
+    }
+    return SvnContentRevision.createRemote(myVcs, filePath, svnRevision);
+  }
+
+  private SVNStatus getFileStatus(File file, boolean remote) {
+    WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file);
+
+    return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? getStatusCommandLine(file, remote) : getStatusWithSvnKit(file, remote);
+  }
+
+  private SVNStatus getStatusWithSvnKit(File file, boolean remote) {
+    SVNStatus result = null;
+
+    try {
+      result = myVcs.createStatusClient().doStatus(file, remote, false);
     }
     catch (SVNException e) {
       LOG.debug(e);    // most likely the file is unversioned
     }
-    return SvnContentRevision.createRemote(myVcs, filePath, svnRevision);
+
+    return result;
+  }
+
+  private SVNStatus getStatusCommandLine(File file, boolean remote) {
+    SVNStatus result = null;
+
+    try {
+      result = new SvnCommandLineStatusClient(myVcs.getProject()).doStatus(file, remote, false);
+    }
+    catch (SVNException e) {
+      LOG.debug(e);
+    }
+
+    return result;
   }
 
   public ItemLatestState getLastRevision(FilePath filePath) {
@@ -159,36 +165,29 @@
   }
 
   private ItemLatestState getLastRevision(final File file) {
-    final SVNStatusClient client = myVcs.createStatusClient();
-    try {
-      final SVNStatus svnStatus = client.doStatus(file, true);
-      if (svnStatus == null || itemExists(svnStatus) && SVNRevision.UNDEFINED.equals(svnStatus.getRemoteRevision())) {
-        // IDEADEV-21785 (no idea why this can happen)
-        final SVNInfo info = myVcs.createWCClient().doInfo(file, SVNRevision.HEAD);
-        if (info == null || info.getURL() == null) {
-          LOG.info("No SVN status returned for " + file.getPath());
-          return defaultResult();
-        }
-        return createResult(info.getCommittedRevision(), true, false);
+    final SVNStatus svnStatus = getFileStatus(file, true);
+    if (svnStatus == null || itemExists(svnStatus) && SVNRevision.UNDEFINED.equals(svnStatus.getRemoteRevision())) {
+      // IDEADEV-21785 (no idea why this can happen)
+      final SVNInfo info = myVcs.getInfo(file, SVNRevision.HEAD);
+      if (info == null || info.getURL() == null) {
+        LOG.info("No SVN status returned for " + file.getPath());
+        return defaultResult();
       }
-      final boolean exists = itemExists(svnStatus);
-      if (! exists) {
-        // get really latest revision
-        final LatestExistentSearcher searcher = new LatestExistentSearcher(myVcs, svnStatus.getURL());
-        final long revision = searcher.getDeletionRevision();
+      return createResult(info.getCommittedRevision(), true, false);
+    }
+    final boolean exists = itemExists(svnStatus);
+    if (! exists) {
+      // get really latest revision
+      final LatestExistentSearcher searcher = new LatestExistentSearcher(myVcs, svnStatus.getURL());
+      final long revision = searcher.getDeletionRevision();
 
-        return createResult(SVNRevision.create(revision), exists, false);
-      }
-      final SVNRevision remoteRevision = svnStatus.getRemoteRevision();
-      if (remoteRevision != null) {
-        return createResult(remoteRevision, exists, false);
-      }
-      return createResult(svnStatus.getRevision(), exists, false);
+      return createResult(SVNRevision.create(revision), exists, false);
     }
-    catch (SVNException e) {
-      LOG.debug(e);    // most likely the file is unversioned
-      return defaultResult();
+    final SVNRevision remoteRevision = svnStatus.getRemoteRevision();
+    if (remoteRevision != null) {
+      return createResult(remoteRevision, exists, false);
     }
+    return createResult(svnStatus.getRevision(), exists, false);
   }
 
   private boolean itemExists(SVNStatus svnStatus) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
index 062c412..da1adc6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
@@ -44,10 +44,7 @@
 import com.intellij.vcsUtil.ActionWithTempFile;
 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.SVNNodeKind;
+import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
 import org.tmatesoft.svn.core.wc.*;
 
@@ -160,10 +157,10 @@
   }
 
   private class UUIDHelper {
-    private final SVNWCClient myWcClient;
+    private final SvnVcs myVcs;
 
     private UUIDHelper(final SvnVcs vcs) {
-      myWcClient = vcs.createWCClient();
+      myVcs = vcs;
     }
 
     /**
@@ -175,7 +172,7 @@
         final SVNInfo info1 = new RepeatSvnActionThroughBusy() {
           @Override
           protected void executeImpl() throws SVNException {
-            myT = myWcClient.doInfo(new File(dir.getPath()), SVNRevision.UNDEFINED);
+            myT = myVcs.getInfo(new File(dir.getPath()));
           }
         }.compute();
         if (info1 == null || info1.getRepositoryUUID() == null) {
@@ -244,10 +241,11 @@
     long srcTime = src.lastModified();
     try {
       final boolean isUndo = isUndo(vcs);
-      final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs.getProject(), src);
+      final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs, src);
 
-      final boolean is17 = SvnUtil.is17CopyPart(src);
-      if (is17) {
+      WorkingCopyFormat format = vcs.getWorkingCopyFormat(src);
+      final boolean is17OrLater = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format);
+      if (is17OrLater) {
         SVNStatus srcStatus = getFileStatus(vcs, src);
         final File toDir = dst.getParentFile();
         SVNStatus dstStatus = getFileStatus(vcs, toDir);
@@ -283,29 +281,18 @@
     ourStatusesForUndoMove.add(SVNStatusType.STATUS_ADDED);
   }
 
-  private boolean for17move(SvnVcs vcs, final File src, final File dst, boolean undo, SVNStatus srcStatus) throws SVNException {
+  private boolean for17move(final SvnVcs vcs, final File src, final File dst, boolean undo, SVNStatus srcStatus) throws SVNException {
     if (srcStatus != null && srcStatus.getCopyFromURL() == null) {
       undo = false;
     }
     if (undo) {
       myUndoingMove = true;
-      final SVNWCClient wcClient = vcs.createWCClient();
-      new RepeatSvnActionThroughBusy() {
-        @Override
-        protected void executeImpl() throws SVNException {
-          wcClient.doRevert(dst, true);
-        }
-      }.execute();
+      createRevertAction(vcs, dst, true).execute();
       copyUnversionedMembersOfDirectory(src, dst);
       if (srcStatus == null || SvnVcs.svnStatusIsUnversioned(srcStatus)) {
         FileUtil.delete(src);
       } else {
-        new RepeatSvnActionThroughBusy() {
-          @Override
-          protected void executeImpl() throws SVNException {
-            wcClient.doRevert(src, true);
-          }
-        }.execute();
+        createRevertAction(vcs, src, true).execute();
       }
       restoreFromUndoStorage(dst);
     } else {
@@ -317,15 +304,9 @@
           copyFileOrDir(src, dst);
         }
         catch (IOException e) {
-          throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+          throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
         }
-        final SVNWCClient wcClient = vcs.createWCClient();
-        new RepeatSvnActionThroughBusy() {
-          @Override
-          protected void executeImpl() throws SVNException {
-            wcClient.doDelete(src, true, false);
-          }
-        }.execute();
+        createDeleteAction(vcs, src, true).execute();
         return false;
       }
       moveFileWithSvn(vcs, src, dst);
@@ -333,13 +314,16 @@
     return false;
   }
 
-  public static void moveFileWithSvn(SvnVcs vcs, File src, final File dst) throws SVNException {
-    final SVNCopyClient copyClient = vcs.createCopyClient();
-    final SVNCopySource svnCopySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.WORKING, src);
+  public static void moveFileWithSvn(final SvnVcs vcs, final File src, final File dst) throws SVNException {
     new RepeatSvnActionThroughBusy() {
       @Override
       protected void executeImpl() throws SVNException {
-        copyClient.doCopy(new SVNCopySource[]{svnCopySource}, dst, true, false, true);
+        try {
+          vcs.getFactory(src).createCopyMoveClient().copy(src, dst, false, true);
+        }
+        catch (VcsException e) {
+          wrapAndThrow(e);
+        }
       }
     }.execute();
   }
@@ -357,7 +341,7 @@
               copyFileOrDir(src, dst);
             }
             catch (IOException e) {
-              exc[0] = new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+              exc[0] = new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
               return false;
             }
           }
@@ -464,7 +448,7 @@
    * deleted: do nothing, return true (strange)
    */
   public boolean delete(VirtualFile file) throws IOException {
-    SvnVcs vcs = getVCS(file);
+    final SvnVcs vcs = getVCS(file);
     if (vcs != null && SvnUtil.isAdminDirectory(file)) {
       return true;
     }
@@ -476,12 +460,8 @@
     if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
       return false;
     }
-    try {
-      if (SVNWCUtil.isWorkingCopyRoot(ioFile)) {
-        return false;
-      }
-    } catch (SVNException e) {
-        //
+    if (SvnUtil.isWorkingCopyRoot(ioFile)) {
+      return false;
     }
 
     SVNStatus status = getFileStatus(vcs, ioFile);
@@ -507,13 +487,7 @@
         }
         if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
           try {
-            final SVNWCClient wcClient = vcs.createWCClient();
-            new RepeatSvnActionThroughBusy() {
-              @Override
-              protected void executeImpl() throws SVNException {
-                wcClient.doRevert(ioFile, false);
-              }
-            }.execute();
+            createRevertAction(vcs, ioFile, false).execute();
           }
           catch (SVNException e) {
             // ignore
@@ -529,6 +503,41 @@
     }
   }
 
+  @NotNull
+  private RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean recursive) {
+    return new RepeatSvnActionThroughBusy() {
+      @Override
+      protected void executeImpl() throws SVNException {
+        try {
+          vcs.getFactory(file).createRevertClient().revert(new File[]{file}, SVNDepth.fromRecurse(recursive), null);
+        }
+        catch (VcsException e) {
+          wrapAndThrow(e);
+        }
+      }
+    };
+  }
+
+  @NotNull
+  private RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) {
+    return new RepeatSvnActionThroughBusy() {
+      @Override
+      protected void executeImpl() throws SVNException {
+        try {
+          vcs.getFactory(file).createDeleteClient().delete(file, force);
+        }
+        catch (VcsException e) {
+          wrapAndThrow(e);
+        }
+      }
+    };
+  }
+
+  private static void wrapAndThrow(VcsException e) throws SVNException {
+    // TODO: probably we should wrap into new exception only if e.getCause is not SVNException
+    throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL, e), e);
+  }
+
   private boolean isAboveSourceOfCopyOrMove(final Project p, File ioFile) {
     for (MovedFileInfo file : myMovedFiles) {
       if (FileUtil.isAncestor(ioFile, file.mySrc, false)) return true;
@@ -583,7 +592,6 @@
     if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) {
       return false;
     }
-    final SVNWCClient wcClient = vcs.createWCClient();
     final File targetFile = new File(ioDir, name);
     SVNStatus status = getFileStatus(vcs, targetFile);
 
@@ -603,12 +611,7 @@
       }
       try {
         if (isUndo(vcs)) {
-          new RepeatSvnActionThroughBusy() {
-            @Override
-            protected void executeImpl() throws SVNException {
-              wcClient.doRevert(targetFile, false);
-            }
-          }.execute();
+          createRevertAction(vcs, targetFile, false).execute();
           return true;
         }
         myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
@@ -759,8 +762,6 @@
     return new Runnable() {
       @Override
       public void run() {
-        final SVNWCClient wcClient = vcs.createWCClient();
-        final SVNCopyClient copyClient = vcs.createCopyClient();
         for(VirtualFile file: filesToProcess) {
           final File ioFile = new File(file.getPath());
           try {
@@ -771,11 +772,15 @@
                   protected void executeInternal() throws VcsException {
                     try {
                       // not recursive
-                      final SVNCopySource[] copySource = {new SVNCopySource(SVNRevision.WORKING, SVNRevision.WORKING, copyFrom)};
                       new RepeatSvnActionThroughBusy() {
                         @Override
                         protected void executeImpl() throws SVNException {
-                          copyClient.doCopy(copySource, ioFile, false, true, true);
+                          try {
+                            vcs.getFactory(copyFrom).createCopyMoveClient().copy(copyFrom, ioFile, true, false);
+                          }
+                          catch (VcsException e) {
+                            wrapAndThrow(e);
+                          }
                         }
                       }.execute();
                     }
@@ -793,7 +798,12 @@
               new RepeatSvnActionThroughBusy() {
                 @Override
                 protected void executeImpl() throws SVNException {
-                  wcClient.doAdd(ioFile, true, false, false, true);
+                  try {
+                    vcs.getFactory(ioFile).createAddClient().add(ioFile, null, false, false, true, null);
+                  }
+                  catch (VcsException e) {
+                    wrapAndThrow(e);
+                  }
                 }
               }.execute();
             }
@@ -915,17 +925,11 @@
                                         final List<VcsException> exceptions) {
     return new Runnable() {
       public void run() {
-        final SVNWCClient wcClient = vcs.createWCClient();
         for(FilePath file: filesToProcess) {
           VirtualFile vFile = file.getVirtualFile();  // for deleted directories
           final File ioFile = new File(file.getPath());
           try {
-            new RepeatSvnActionThroughBusy() {
-              @Override
-              protected void executeImpl() throws SVNException {
-                wcClient.doDelete(ioFile, true, false);
-              }
-            }.execute();
+            createDeleteAction(vcs, ioFile, true).execute();
             if (vFile != null && vFile.isValid() && vFile.isDirectory()) {
               vFile.refresh(true, true);
               VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(vFile);
@@ -978,18 +982,15 @@
   private void fillDeletedFiles(Project project, List<Pair<FilePath, WorkingCopyFormat>> deletedFiles, Collection<FilePath> deleteAnyway)
     throws SVNException {
     final SvnVcs vcs = SvnVcs.getInstance(project);
-    final SVNStatusClient sc = vcs.createStatusClient();
     final Collection<File> files = myDeletedFiles.remove(project);
     for (final File file : files) {
-      boolean isAdded = false;
-      final SVNStatus status;
-        status = new RepeatSvnActionThroughBusy() {
-          @Override
-          protected void executeImpl() throws SVNException {
-            myT = sc.doStatus(file, false);
-          }
-        }.compute();
-        isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
+      final SVNStatus status = new RepeatSvnActionThroughBusy() {
+        @Override
+        protected void executeImpl() throws SVNException {
+          myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
+        }
+      }.compute();
+      boolean isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
       final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
       if (isAdded) {
         deleteAnyway.add(filePath);
@@ -1034,18 +1035,12 @@
   }
 
   @Nullable
-  private static SVNStatus getFileStatus(SvnVcs vcs, File file) {
-    SVNStatusClient stClient = vcs.createStatusClient();
-    return getFileStatus(file, stClient);
-  }
-
-  @Nullable
-  private static SVNStatus getFileStatus(final File file, final SVNStatusClient stClient) {
+  private static SVNStatus getFileStatus(@NotNull final SvnVcs vcs, @NotNull final File file) {
     try {
       return new RepeatSvnActionThroughBusy() {
         @Override
         protected void executeImpl() throws SVNException {
-          myT = stClient.doStatus(file, false);
+          myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
         }
       }.compute();
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
index 46545c4..68e7c07 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
@@ -312,8 +312,8 @@
             LOG.info("Error: cannot find repository URL for versioned folder: " + foundRoot.getFile().getPath());
           } else {
             myRepositoryRoots.register(repoRoot);
-            myTopRoots.add(new RootUrlInfo(repoRoot, foundRoot.getInfo().getURL(),
-                                       SvnFormatSelector.getWorkingCopyFormat(new File(foundRoot.getFile().getPath())), foundRoot.getFile(), vcsRoot));
+            myTopRoots.add(new RootUrlInfo(repoRoot, foundRoot.getInfo().getURL(), SvnFormatSelector.findRootAndGetFormat(
+              new File(foundRoot.getFile().getPath())), foundRoot.getFile(), vcsRoot));
           }
         }
       }
@@ -541,8 +541,9 @@
       final SVNInfo svnInfo = vcs.getInfo(copyRoot);
       if ((svnInfo == null) || (svnInfo.getRepositoryRootURL() == null)) continue;
 
-      final RootUrlInfo info = new RootUrlInfo(svnInfo.getRepositoryRootURL(), svnInfo.getURL(),
-                                               SvnFormatSelector.getWorkingCopyFormat(svnInfo.getFile()), copyRoot, vcsRoot);
+      final RootUrlInfo info =
+        new RootUrlInfo(svnInfo.getRepositoryRootURL(), svnInfo.getURL(), SvnFormatSelector.findRootAndGetFormat(svnInfo.getFile()),
+                        copyRoot, vcsRoot);
       mapping.add(info);
     }
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
index 94d21db..77783bad 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
@@ -16,6 +16,7 @@
 package org.jetbrains.idea.svn;
 
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
 import com.intellij.util.WaitForProgressToShow;
@@ -37,6 +38,9 @@
 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;
@@ -145,7 +149,19 @@
     return newMode[0];
   }
 
+  public static WorkingCopyFormat findRootAndGetFormat(final File path) {
+    File root = SvnUtil.getWorkingCopyRootNew(path);
+
+    return root != null ? getWorkingCopyFormat(root) : WorkingCopyFormat.UNKNOWN;
+  }
+
   public static WorkingCopyFormat getWorkingCopyFormat(final File path) {
+    WorkingCopyFormat format = SvnUtil.getFormat(path);
+
+    return WorkingCopyFormat.UNKNOWN.equals(format) ? detectWithSvnKit(path) : format;
+  }
+
+  private static WorkingCopyFormat detectWithSvnKit(File path) {
     try {
       final SvnWcGeneration svnWcGeneration = SvnOperationFactory.detectWcGeneration(path, true);
       if (SvnWcGeneration.V17.equals(svnWcGeneration)) return WorkingCopyFormat.ONE_DOT_SEVEN;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java
index 97b87ef..fcac396 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java
@@ -29,6 +29,7 @@
  * Date: 10/19/12
  * Time: 4:22 PM
  */
+// TODO: Likely to be removed (together with SvnAbstractWriteOperationLocks).
 public class SvnProxies {
   private final SvnAbstractWriteOperationLocks myLocks;
   private final AtomicReference<LearningProxy<SVNChangelistClientI, SVNException>> myChangelist;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
index 4a49dc1..8b51819 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
@@ -47,13 +47,15 @@
 public class SvnRecursiveStatusWalker {
   private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnRecursiveStatusWalker");
   private final StatusWalkerPartner myPartner;
+  private final SvnVcs myVcs;
   private final Project myProject;
   private final StatusReceiver myReceiver;
   private final LinkedList<MyItem> myQueue;
   private final MyHandler myHandler;
 
-  public SvnRecursiveStatusWalker(final Project project, final StatusReceiver receiver, final StatusWalkerPartner partner) {
-    myProject = project;
+  public SvnRecursiveStatusWalker(final SvnVcs vcs, final StatusReceiver receiver, final StatusWalkerPartner partner) {
+    myVcs = vcs;
+    myProject = vcs.getProject();
     myReceiver = receiver;
     myPartner = partner;
     myQueue = new LinkedList<MyItem>();
@@ -61,7 +63,7 @@
   }
 
   public void go(final FilePath rootPath, final SVNDepth depth) throws SVNException {
-    final MyItem root = new MyItem(myProject, rootPath, depth, myPartner.createStatusClient(), false);
+    final MyItem root = new MyItem(myVcs, rootPath, depth, myPartner.createStatusClient(), false);
     myQueue.add(root);
 
     while (! myQueue.isEmpty()) {
@@ -83,7 +85,7 @@
         }
       } else {
         try {
-          final SVNStatus status = item.getClient().doStatus(ioFile, false, false);
+          final SVNStatus status = item.getClient(ioFile).doStatus(ioFile, false, false);
           myReceiver.process(path, status);
         } catch (SVNException e) {
           handleStatusException(item, path, e);
@@ -115,18 +117,20 @@
     private final Project myProject;
     private final FilePath myPath;
     private final SVNDepth myDepth;
-    private final SVNStatusClient myClient;
     private final SvnStatusClientI mySvnClient;
+    private final SvnStatusClientI myCommandLineClient;
     private final boolean myIsInnerCopyRoot;
     private final SvnConfiguration myConfiguration17;
+    private final SvnVcs myVcs;
 
-    private MyItem(Project project, FilePath path, SVNDepth depth, SVNStatusClient client, boolean isInnerCopyRoot) {
-      myProject = project;
+    private MyItem(SvnVcs vcs, FilePath path, SVNDepth depth, SVNStatusClient client, boolean isInnerCopyRoot) {
+      myVcs = vcs;
+      myProject = vcs.getProject();
       myConfiguration17 = SvnConfiguration.getInstance(myProject);
       myPath = path;
       myDepth = depth;
-      myClient = client;
       mySvnClient = new SvnkitSvnStatusClient(client);
+      myCommandLineClient = new SvnCommandLineStatusClient(myProject);
       myIsInnerCopyRoot = isInnerCopyRoot;
     }
 
@@ -138,20 +142,20 @@
       return myDepth;
     }
 
-    public SvnStatusClientI getClient() {
-      return mySvnClient;
-    }
-    
     public SvnStatusClientI getClient(final File file) {
-      if (! SVNDepth.INFINITY.equals(myDepth)) {
-        return mySvnClient;
+      WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file);
+
+      if (format == WorkingCopyFormat.ONE_DOT_EIGHT) {
+        return myCommandLineClient;
       }
+
       // check format
       if (CheckJavaHL.isPresent() && SvnConfiguration.UseAcceleration.javaHL.equals(myConfiguration17.myUseAcceleration) &&
           Svn17Detector.is17(myProject, file)) {
         return new JavaHLSvnStatusClient(myProject);
-      } else if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration17.myUseAcceleration) && Svn17Detector.is17(myProject, file)) {
-        return new SvnCommandLineStatusClient(myProject);
+      } else if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration17.myUseAcceleration)) {
+        // apply command line disregarding working copy format
+        return myCommandLineClient;
       }
       return mySvnClient;
     }
@@ -186,7 +190,7 @@
           return true;
         }
         if (file.isDirectory() && new File(file, SVNFileUtil.getAdminDirectoryName()).exists()) {
-          final MyItem childItem = new MyItem(myProject, path, newDepth, myPartner.createStatusClient(), true);
+          final MyItem childItem = new MyItem(myVcs, path, newDepth, myPartner.createStatusClient(), true);
           myQueue.add(childItem);
         } else if (vf != null) {
           myReceiver.processUnversioned(vf);
@@ -228,12 +232,13 @@
     }
 
     public void checkIfCopyRootWasReported(@Nullable final SVNStatus ioFileStatus, final File ioFile) {
-      if (! myMetCurrentItem && FileUtil.filesEqual(ioFile, myCurrentItem.getPath().getIOFile())) {
+      File itemFile = myCurrentItem.getPath().getIOFile();
+      if (! myMetCurrentItem && FileUtil.filesEqual(ioFile, itemFile)) {
         myMetCurrentItem = true;
         SVNStatus statusInner;
         try {
           statusInner = ioFileStatus != null ? ioFileStatus :
-            myCurrentItem.getClient().doStatus(myCurrentItem.getPath().getIOFile(), false);
+            myCurrentItem.getClient(itemFile).doStatus(itemFile, false);
         }
         catch (SVNException e) {
           LOG.info(e);
@@ -294,7 +299,7 @@
             //myReceiver.processUnversioned(vFile);
             //processRecursively(vFile, myCurrentItem.getDepth());
           } else {
-            final MyItem childItem = new MyItem(myProject, new FilePathImpl(vFile), SVNDepth.INFINITY,
+            final MyItem childItem = new MyItem(myVcs, new FilePathImpl(vFile), SVNDepth.INFINITY,
                                                 myPartner.createStatusClient(), true);
             myQueue.add(childItem);
           }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java
index 853e995..efea2f9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java
@@ -25,6 +25,7 @@
  * Date: 10/23/12
  * Time: 2:31 PM
  */
+// TODO: Used only in SvnLockingTest which is not required anymore. Likely to be removed.
 public class SvnTestWriteOperationLocks extends SvnAbstractWriteOperationLocks {
   private final WorkingCopy myWorkingCopy;
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index 0c049ac..7cd6bdd9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -30,21 +30,19 @@
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.Change;
 import com.intellij.openapi.vcs.changes.ChangesUtil;
-import com.intellij.openapi.vcs.impl.ContentRevisionCache;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtilCore;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.*;
 import com.intellij.openapi.wm.impl.status.StatusBarUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.containers.MultiMap;
-import com.intellij.vcsUtil.VcsUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.ClientFactory;
 import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
 import org.jetbrains.idea.svn.dialogs.LockDialog;
+import org.tmatesoft.sqljet.core.SqlJetException;
+import org.tmatesoft.sqljet.core.table.SqlJetDb;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
 import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
@@ -53,14 +51,14 @@
 import org.tmatesoft.svn.core.io.SVNRepository;
 import org.tmatesoft.svn.core.wc.*;
 import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
 import java.util.*;
 
 public class SvnUtil {
+  // TODO: ASP.NET hack behavior should be supported - http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt
+  // TODO: Remember this when moving out SVNKit classes.
   @NonNls public static final String SVN_ADMIN_DIR_NAME = SVNFileUtil.getAdminDirectoryName();
   @NonNls public static final String ENTRIES_FILE_NAME = "entries";
   @NonNls public static final String WC_DB_FILE_NAME = "wc.db";
@@ -71,13 +69,9 @@
   private SvnUtil() { }
 
   public static boolean isSvnVersioned(final Project project, File parent) {
-    try {
-      final SVNInfo info = SvnVcs.getInstance(project).createWCClient().doInfo(parent, SVNRevision.UNDEFINED);
-      return info != null;
-    }
-    catch (SVNException e) {
-      return false;
-    }
+    final SVNInfo info = SvnVcs.getInstance(project).getInfo(parent);
+
+    return info != null;
   }
 
   public static Collection<VirtualFile> crawlWCRoots(final Project project, File path, SvnWCRootCrawler callback, ProgressIndicator progress) {
@@ -123,15 +117,8 @@
 
   @Nullable
   public static String getExactLocation(final SvnVcs vcs, File path) {
-    try {
-      SVNWCClient wcClient = vcs.createWCClient();
-      SVNInfo info = wcClient.doInfo(path, SVNRevision.UNDEFINED);
-      if (info != null && info.getURL() != null) {
-        return info.getURL().toString();
-      }
-    }
-    catch (SVNException ignored) { }
-    return null;
+    SVNInfo info = vcs.getInfo(path);
+    return info != null && info.getURL() != null ? info.getURL().toString() : null;
   }
 
   public static Map<String, File> getLocationInfoForModule(final SvnVcs vcs, File path, ProgressIndicator progress) {
@@ -288,7 +275,9 @@
   }
 
   public static String formatRepresentation(final WorkingCopyFormat format) {
-    if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
+    if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) {
+      return SvnBundle.message("dialog.show.svn.map.table.version18.text");
+    } else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
       return SvnBundle.message("dialog.show.svn.map.table.version17.text");
     } else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
       return SvnBundle.message("dialog.show.svn.map.table.version16.text");
@@ -352,6 +341,54 @@
     return result;
   }
 
+  /**
+   * Gets working copy internal format. Works for 1.7 and 1.8.
+   *
+   * @param path
+   * @return
+   */
+  public static WorkingCopyFormat getFormat(final File path) {
+    int format = 0;
+    File dbFile = resolveDatabase(path);
+
+    if (dbFile != null) {
+      SqlJetDb db = null;
+      try {
+        db = SqlJetDb.open(dbFile, false);
+        format = db.getOptions().getUserVersion();
+      }
+      catch (SqlJetException e) {
+        LOG.error(e);
+      } finally {
+        if (db != null) {
+          try {
+            db.close();
+          }
+          catch (SqlJetException e) {
+            LOG.error(e);
+          }
+        }
+      }
+    }
+
+    return WorkingCopyFormat.getInstance(format);
+  }
+
+  private static File resolveDatabase(final File path) {
+    File dbFile = getWcDb(path);
+    File result = null;
+
+    try {
+      if (dbFile.exists() && dbFile.isFile()) {
+        result = dbFile;
+      }
+    } catch (SecurityException e) {
+      LOG.error("Failed to access working copy database", e);
+    }
+
+    return result;
+  }
+
   private static class LocationsCrawler implements SvnWCRootCrawler {
     private final SvnVcs myVcs;
     private final Map<String, File> myLocations;
@@ -371,15 +408,9 @@
         oldText = progress.getText();
         progress.setText(SvnBundle.message("progress.text.discovering.location", root.getAbsolutePath()));
       }
-      try {
-        SVNWCClient wcClient = myVcs.createWCClient();
-        SVNInfo info = wcClient.doInfo(root, SVNRevision.UNDEFINED);
-        if (info != null && info.getURL() != null) {
-          myLocations.put(info.getURL().toString(), info.getFile());
-        }
-      }
-      catch (SVNException e) {
-        //
+      SVNInfo info = myVcs.getInfo(root);
+      if (info != null && info.getURL() != null) {
+        myLocations.put(info.getURL().toString(), info.getFile());
       }
       if (progress != null) {
         progress.setText(oldText);
@@ -389,20 +420,15 @@
 
   @Nullable
   public static String getRepositoryUUID(final SvnVcs vcs, final File file) {
-    final SVNWCClient client = vcs.createWCClient();
-    try {
-      final SVNInfo info = client.doInfo(file, SVNRevision.UNDEFINED);
-      return (info == null) ? null : info.getRepositoryUUID();
-    } catch (SVNException e) {
-      return null;
-    }
+    final SVNInfo info = vcs.getInfo(file);
+    return info != null ? info.getRepositoryUUID() : null;
   }
 
   @Nullable
   public static String getRepositoryUUID(final SvnVcs vcs, final SVNURL url) {
-    final SVNWCClient client = vcs.createWCClient();
     try {
-      final SVNInfo info = client.doInfo(url, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
+      final SVNInfo info = vcs.getInfo(url, SVNRevision.UNDEFINED);
+
       return (info == null) ? null : info.getRepositoryUUID();
     } catch (SVNException e) {
       return null;
@@ -411,19 +437,14 @@
 
   @Nullable
   public static SVNURL getRepositoryRoot(final SvnVcs vcs, final File file) {
-    final SVNWCClient client = vcs.createWCClient();
-    try {
-      final SVNInfo info = client.doInfo(file, SVNRevision.UNDEFINED);
-      return (info == null) ? null : info.getRepositoryRootURL();
-    } catch (SVNException e) {
-      return null;
-    }
+    final SVNInfo info = vcs.getInfo(file);
+    return info != null ? info.getRepositoryRootURL() : null;
   }
 
   @Nullable
   public static SVNURL getRepositoryRoot(final SvnVcs vcs, final String url) {
     try {
-      return getRepositoryRoot(vcs, SVNURL.parseURIEncoded(url), true);
+      return getRepositoryRoot(vcs, SVNURL.parseURIEncoded(url));
     }
     catch (SVNException e) {
       return null;
@@ -431,18 +452,14 @@
   }
 
   @Nullable
-  public static SVNURL getRepositoryRoot(final SvnVcs vcs, final SVNURL url, boolean allowRemote) throws SVNException {
-    final SVNWCClient client = vcs.createWCClient();
-    SVNInfo info = client.doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
+  public static SVNURL getRepositoryRoot(final SvnVcs vcs, final SVNURL url) throws SVNException {
+    SVNInfo info = vcs.getInfo(url, SVNRevision.HEAD);
+
     return (info == null) ? null : info.getRepositoryRootURL();
   }
 
   public static boolean isWorkingCopyRoot(final File file) {
-    try {
-      return SVNWCUtil.isWorkingCopyRoot(file);
-    } catch (SVNException e) {
-      return false;
-    }
+    return FileUtil.filesEqual(file, getWorkingCopyRootNew(file));
   }
 
   @Nullable
@@ -548,17 +565,9 @@
   }
 
   public static SVNDepth getDepth(final SvnVcs vcs, final File file) {
-    final SVNWCClient client = vcs.createWCClient();
-    try {
-      final SVNInfo svnInfo = client.doInfo(file, SVNRevision.UNDEFINED);
-      if (svnInfo != null) {
-        return svnInfo.getDepth();
-      }
-    }
-    catch (SVNException e) {
-      //
-    }
-    return SVNDepth.UNKNOWN;
+    SVNInfo info = vcs.getInfo(file);
+
+    return info != null && info.getDepth() != null ? info.getDepth() : SVNDepth.UNKNOWN;
   }
 
   public static boolean seemsLikeVersionedDir(final VirtualFile file) {
@@ -590,21 +599,17 @@
   }
 
   public static SVNURL getCommittedURL(final SvnVcs vcs, final File file) {
-    final File root = getWorkingCopyRoot(file);
-    if (root == null) return null;
-    return getUrl(vcs, root);
+    final File root = getWorkingCopyRootNew(file);
+
+    return root == null ? null : getUrl(vcs, root);
   }
 
   @Nullable
   public static SVNURL getUrl(final SvnVcs vcs, final File file) {
-    try {
-      final SVNInfo info = vcs.createWCClient().doInfo(file, SVNRevision.UNDEFINED);
-      return info == null ? null : info.getURL(); // todo for moved items?
-    }
-    catch (SVNException e) {
-      LOG.debug(e);
-      return null;
-    }
+    // todo for moved items?
+    final SVNInfo info = vcs.getInfo(file);
+
+    return info == null ? null : info.getURL();
   }
 
   public static boolean doesRepositorySupportMergeInfo(final SvnVcs vcs, final SVNURL url) {
@@ -648,17 +653,9 @@
 
   @Nullable
   public static File getWcCopyRootIf17(final File file, @Nullable final File upperBound) {
-    File current = file;
-    boolean wcDbFound = false;
-    while (current != null) {
-      File wcDb;
-      if ((wcDb = getWcDb(current)).exists() && ! wcDb.isDirectory()) {
-        wcDbFound = true;
-        break;
-      }
-      current = current.getParentFile();
-    }
-    if (! wcDbFound) return null;
+    File current = getParentWithDb(file);
+    if (current == null) return null;
+
     while (current != null) {
       try {
         final SvnWcGeneration svnWcGeneration = SvnOperationFactory.detectWcGeneration(current, false);
@@ -674,6 +671,40 @@
     return null;
   }
 
+  /**
+   * Utility method that deals also with 1.8 working copies.
+   * TODO: Should be renamed when all parts updated for 1.8.
+   *
+   * @param file
+   * @return
+   */
+  @Nullable
+  public static File getWorkingCopyRootNew(final File file) {
+    File current = getParentWithDb(file);
+    if (current == null) return getWorkingCopyRoot(file);
+
+    WorkingCopyFormat format = getFormat(current);
+
+    return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)
+           ? current
+           : getWorkingCopyRoot(file);
+  }
+
+  private static File getParentWithDb(File file) {
+    File current = file;
+    boolean wcDbFound = false;
+    while (current != null) {
+      File wcDb;
+      if ((wcDb = getWcDb(current)).exists() && ! wcDb.isDirectory()) {
+        wcDbFound = true;
+        break;
+      }
+      current = current.getParentFile();
+    }
+    if (! wcDbFound) return null;
+    return current;
+  }
+
   public static boolean is17CopyPart(final File file) {
     try {
       return SvnWcGeneration.V17.equals(SvnOperationFactory.detectWcGeneration(file, true));
@@ -703,44 +734,24 @@
     return result;
   }
 
-  public static byte[] getFileContents(final SvnVcs vcs, final String path, final boolean isUrl, final SVNRevision revision,
-                                       final SVNRevision pegRevision)
+  public static byte[] getFileContents(@NotNull final SvnVcs vcs,
+                                       @NotNull final SvnTarget target,
+                                       @Nullable final SVNRevision revision,
+                                       @Nullable final SVNRevision pegRevision)
     throws VcsException {
-    final int maxSize = VcsUtil.getMaxVcsLoadedFileSize();
-    ByteArrayOutputStream buffer = new ByteArrayOutputStream() {
-      @Override
-      public synchronized void write(int b) {
-        if (size() > maxSize) throw new FileTooBigRuntimeException();
-        super.write(b);
-      }
+    ClientFactory factory = target.isFile() ? vcs.getFactory(target.getFile()) : vcs.getFactory();
 
-      @Override
-      public synchronized void write(byte[] b, int off, int len) {
-        if (size() > maxSize) throw new FileTooBigRuntimeException();
-        super.write(b, off, len);
-      }
-
-      @Override
-      public synchronized void writeTo(OutputStream out) throws IOException {
-        if (size() > maxSize) throw new FileTooBigRuntimeException();
-        super.writeTo(out);
-      }
-    };
-    SVNWCClient wcClient = vcs.createWCClient();
-    try {
-      if (isUrl) {
-        wcClient.doGetFileContents(SVNURL.parseURIEncoded(path), pegRevision, revision, true, buffer);
-      } else {
-        wcClient.doGetFileContents(new File(path), pegRevision, revision, true, buffer);
-      }
-      ContentRevisionCache.checkContentsSize(path, buffer.size());
-    } catch (FileTooBigRuntimeException e) {
-      ContentRevisionCache.checkContentsSize(path, buffer.size());
-    } catch (SVNException e) {
-      throw new VcsException(e);
-    }
-    return buffer.toByteArray();
+    return factory.createContentClient().getContent(target, revision, pegRevision);
   }
 
-  private static class FileTooBigRuntimeException extends RuntimeException {}
+  public static SVNURL parseUrl(@NotNull String url) {
+    try {
+      return SVNURL.parseURIEncoded(url);
+    }
+    catch (SVNException e) {
+      IllegalArgumentException runtimeException = new IllegalArgumentException();
+      runtimeException.initCause(e);
+      throw runtimeException;
+    }
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index 748fc86..1a5a0f8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -13,8 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 package org.jetbrains.idea.svn;
 
 import com.intellij.ide.FrameStateListener;
@@ -68,8 +66,12 @@
 import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction;
 import org.jetbrains.idea.svn.actions.SvnMergeProvider;
 import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider;
+import org.jetbrains.idea.svn.api.ClientFactory;
+import org.jetbrains.idea.svn.api.CmdClientFactory;
+import org.jetbrains.idea.svn.api.SvnKitClientFactory;
 import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
 import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
+import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient;
 import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker;
 import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator;
 import org.jetbrains.idea.svn.dialogs.WCInfo;
@@ -79,6 +81,7 @@
 import org.jetbrains.idea.svn.history.SvnHistoryProvider;
 import org.jetbrains.idea.svn.lowLevel.PrimitivePool;
 import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser;
+import org.jetbrains.idea.svn.portable.SvnWcClientI;
 import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
 import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
 import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
@@ -195,9 +198,10 @@
   };
   private SvnCheckoutProvider myCheckoutProvider;
 
-  public void checkCommandLineVersion() {
-    myChecker.checkExecutableAndNotifyIfNeeded();
-  }
+  private ClientFactory cmdClientFactory;
+  private ClientFactory svnKitClientFactory;
+
+  private final boolean myLogExceptions;
 
   static {
     System.setProperty("svnkit.log.native.calls", "true");
@@ -235,8 +239,8 @@
 
   public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) {
     super(project, VCS_NAME);
+
     myLoadedBranchesStorage = storage;
-    LOG.debug("ct");
     myRootsToWorkingCopies = new RootsToWorkingCopies(this);
     myConfiguration = svnConfiguration;
     myAuthNotifier = new SvnAuthenticationNotifier(this);
@@ -284,6 +288,9 @@
     // remove used some time before old notification group ids
     correctNotificationIds();
     myChecker = new SvnExecutableChecker(myProject);
+
+    Application app = ApplicationManager.getApplication();
+    myLogExceptions = app != null && (app.isInternal() || app.isUnitTestMode());
   }
 
   private void correctNotificationIds() {
@@ -348,6 +355,10 @@
     });
   }
 
+  public void checkCommandLineVersion() {
+    myChecker.checkExecutableAndNotifyIfNeeded();
+  }
+
   public void invokeRefreshSvnRoots() {
     if (REFRESH_LOG.isDebugEnabled()) {
       REFRESH_LOG.debug("refresh: ", new Throwable());
@@ -481,6 +492,9 @@
       myChecker.checkExecutableAndNotifyIfNeeded();
     }
 
+    cmdClientFactory = new CmdClientFactory(this);
+    svnKitClientFactory = new SvnKitClientFactory(this);
+
     // do one time after project loaded
     StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
       @Override
@@ -911,24 +925,127 @@
     return new File(file, pathToDirProps);
   }
 
+  /**
+   * Provides info either with command line or SvnKit based on project settings.
+   * Call this method only if failed to detect working copy format by any other means.
+   *
+   * @param file
+   * @return
+   */
+  private SVNInfo runInfoCommand(@NotNull final File file) {
+    SVNInfo result = null;
+
+    try {
+      result = SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration)
+               ? getInfoCommandLine(file, SVNRevision.UNDEFINED)
+               : getInfoSvnKit(file);
+    }
+    catch (SVNException e) {
+      handleInfoException(e);
+    }
+
+    return result;
+  }
+
+  public SVNInfo getInfo(@NotNull SVNURL url,
+                         SVNRevision pegRevision,
+                         SVNRevision revision,
+                         ISVNAuthenticationManager manager) throws SVNException {
+    if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration)) {
+      return createInfoClient().doInfo(url, pegRevision, revision);
+    } else {
+      return (manager != null ? createWCClient(manager) : createWCClient()).doInfo(url, pegRevision, revision);
+    }
+  }
+
+  public SVNInfo getInfo(@NotNull SVNURL url, SVNRevision revision) throws SVNException {
+    return getInfo(url, SVNRevision.UNDEFINED, revision, null);
+  }
+
   @Nullable
-  public SVNInfo getInfo(final VirtualFile file) {
+  public SVNInfo getInfo(@NotNull final VirtualFile file) {
     final File ioFile = new File(file.getPath());
     return getInfo(ioFile);
   }
 
-  public SVNInfo getInfo(File ioFile) {
+  @Nullable
+  public SVNInfo getInfo(@NotNull String path) {
+    return getInfo(new File(path));
+  }
+
+  @Nullable
+  public SVNInfo getInfo(@NotNull File ioFile) {
+    WorkingCopyFormat format = getWorkingCopyFormat(ioFile);
+    SVNInfo result = null;
+
     try {
-      SVNWCClient wcClient = createWCClient();
-      SVNInfo info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED);
-      if (info == null || info.getRepositoryRootURL() == null) {
-        info = wcClient.doInfo(ioFile, SVNRevision.HEAD);
-      }
-      return info;
+      result = format == WorkingCopyFormat.ONE_DOT_EIGHT ? getInfoCommandLine(ioFile, SVNRevision.UNDEFINED) : runInfoCommand(ioFile);
     }
     catch (SVNException e) {
-      return null;
+      handleInfoException(e);
     }
+
+    return result;
+  }
+
+  @Nullable
+  public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) {
+    WorkingCopyFormat format = getWorkingCopyFormat(ioFile);
+    SVNInfo result = null;
+
+    try {
+      result = format == WorkingCopyFormat.ONE_DOT_EIGHT ? getInfoCommandLine(ioFile, revision) : getInfoSvnKit(ioFile, revision);
+    }
+    catch (SVNException e) {
+      handleInfoException(e);
+    }
+
+    return result;
+  }
+
+  private void handleInfoException(SVNException e) {
+    final SVNErrorCode errorCode = e.getErrorMessage().getErrorCode();
+    if (!myLogExceptions ||
+        SVNErrorCode.WC_PATH_NOT_FOUND.equals(errorCode) ||
+        SVNErrorCode.UNVERSIONED_RESOURCE.equals(errorCode) ||
+        SVNErrorCode.WC_NOT_WORKING_COPY.equals(errorCode)) {
+      LOG.debug(e);
+    }
+    else {
+      LOG.error(e);
+    }
+  }
+
+  private SVNInfo getInfoSvnKit(@NotNull File ioFile) throws SVNException {
+    SVNInfo info = getInfoSvnKit(ioFile, SVNRevision.UNDEFINED);
+    if (info == null || info.getRepositoryRootURL() == null) {
+      info = getInfoSvnKit(ioFile, SVNRevision.HEAD);
+    }
+    return info;
+  }
+
+  private SVNInfo getInfoSvnKit(@NotNull File ioFile, SVNRevision revision) throws SVNException {
+    return createWCClient().doInfo(ioFile, revision);
+  }
+
+  private SVNInfo getInfoCommandLine(@NotNull File ioFile, SVNRevision revision) throws SVNException {
+    SvnCommandLineInfoClient client = new SvnCommandLineInfoClient(myProject);
+    return client.doInfo(ioFile, revision);
+  }
+
+  private SvnWcClientI createInfoClient() {
+    return new SvnCommandLineInfoClient(myProject);
+  }
+
+  public WorkingCopyFormat getWorkingCopyFormat(@NotNull File ioFile) {
+    RootUrlInfo rootInfo = getSvnFileUrlMapping().getWcRootForFilePath(ioFile);
+    WorkingCopyFormat format = rootInfo != null ? rootInfo.getFormat() : WorkingCopyFormat.UNKNOWN;
+
+    if (WorkingCopyFormat.UNKNOWN.equals(format)) {
+      format = SvnFormatSelector.findRootAndGetFormat(ioFile);
+    }
+
+    return format;
   }
 
   public void refreshSSLProperty() {
@@ -1245,4 +1362,27 @@
     }
     return myCheckoutProvider;
   }
+
+  /**
+   * Try to avoid usages of this method (for now) as it could not correctly for all cases
+   * detect svn 1.8 working copy format to guarantee command line client.
+   *
+   * For instance, when working copies of several formats are presented in project
+   * (though it seems to be rather unlikely case).
+   *
+   * @return
+   */
+  public ClientFactory getFactory() {
+    // check working copy format of project directory
+    WorkingCopyFormat format = getWorkingCopyFormat(new File(getProject().getBaseDir().getPath()));
+
+    return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ||
+           myConfiguration.myUseAcceleration.equals(SvnConfiguration.UseAcceleration.commandLine) ? cmdClientFactory : svnKitClientFactory;
+  }
+
+  public ClientFactory getFactory(@NotNull File file) {
+    WorkingCopyFormat format = getWorkingCopyFormat(file);
+
+    return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? cmdClientFactory : getFactory();
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
index 36e0b08..ca97edb 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
@@ -30,6 +30,7 @@
  * Date: 10/23/12
  * Time: 2:29 PM
  */
+// TODO: Such locking functionality is not required anymore. Likely to be removed.
 public class SvnWriteOperationLocks extends SvnAbstractWriteOperationLocks {
   private final RootsToWorkingCopies myRootsToWorkingCopies;
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java
index d40f947..c007541 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java
@@ -15,19 +15,22 @@
  */
 package org.jetbrains.idea.svn;
 
-import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
-
 /**
  * since not all constants are available from svnkit & constants are fixed
  */
 public enum WorkingCopyFormat {
+
   ONE_DOT_THREE(4, false, false, false, SvnBundle.message("dialog.show.svn.map.table.version13.text")),
   ONE_DOT_FOUR(8, false, false, false, SvnBundle.message("dialog.show.svn.map.table.version14.text")),
   ONE_DOT_FIVE(9, true, true, false, SvnBundle.message("dialog.show.svn.map.table.version15.text")),
   ONE_DOT_SIX(10, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version16.text")),
   ONE_DOT_SEVEN(12, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version17.text")),
+  ONE_DOT_EIGHT(12, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version18.text")),
   UNKNOWN(0, false, false, false, "unknown");
 
+  public static final int INTERNAL_FORMAT_17 = 29;
+  public static final int INTERNAL_FORMAT_18 = 31;
+
   private final int myFormat;
   private final boolean myChangelistSupport;
   private final boolean myMergeInfoSupport;
@@ -60,10 +63,11 @@
 
   public static WorkingCopyFormat getInstance(final int value) {
     // somewhy 1.7 wc format can also be 29
-    if (ISVNWCDb.WC_FORMAT_17 == value) {
+    if (INTERNAL_FORMAT_17 == value) {
       return ONE_DOT_SEVEN;
-    }
-    if (ONE_DOT_FIVE.getFormat() == value) {
+    } else if (INTERNAL_FORMAT_18 == value) {
+      return ONE_DOT_EIGHT;
+    } else if (ONE_DOT_FIVE.getFormat() == value) {
       return ONE_DOT_FIVE;
     } else if (ONE_DOT_FOUR.getFormat() == value) {
       return ONE_DOT_FOUR;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AddAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AddAction.java
index 06c255b..7558a48 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AddAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AddAction.java
@@ -30,8 +30,6 @@
 import org.jetbrains.idea.svn.SvnStatusUtil;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
 
 import java.util.*;
 
@@ -68,8 +66,6 @@
           ProjectLevelVcsManager manager = ProjectLevelVcsManager.getInstance(project);
           manager.startBackgroundVcsOperation();
           try {
-
-            SVNWCClient wcClient = activeVcs.createWCClient();
             final Set<VirtualFile> additionallyDirty = new HashSet<VirtualFile>();
             final FileStatusManager fileStatusManager = FileStatusManager.getInstance(project);
             for (VirtualFile item : items) {
@@ -84,13 +80,13 @@
                 }
               }
             }
-            Collection<SVNException> exceptions =
-              SvnCheckinEnvironment.scheduleUnversionedFilesForAddition(wcClient, Arrays.asList(items), true);
+            Collection<VcsException> exceptions =
+              SvnCheckinEnvironment.scheduleUnversionedFilesForAddition(activeVcs, Arrays.asList(items), true);
             additionallyDirty.addAll(Arrays.asList(items));
             markDirty(project, additionallyDirty);
             if (!exceptions.isEmpty()) {
               final Collection<String> messages = new ArrayList<String>(exceptions.size());
-              for (SVNException exception : exceptions) {
+              for (VcsException exception : exceptions) {
                 messages.add(exception.getMessage());
               }
               throw new VcsException(messages);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java
index 87b3697..d65c6d3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java
@@ -19,6 +19,7 @@
 
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.vcs.AbstractVcs;
@@ -32,8 +33,9 @@
 import org.jetbrains.idea.svn.SvnBundle;
 import org.jetbrains.idea.svn.SvnStatusUtil;
 import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.conflict.ConflictClient;
 import org.jetbrains.idea.svn.dialogs.SelectFilesDialog;
-import org.tmatesoft.svn.core.SVNDepth;
+import org.jetbrains.idea.svn.portable.SvnStatusClientI;
 import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.wc.*;
 
@@ -42,6 +44,8 @@
 import java.util.TreeSet;
 
 public class MarkResolvedAction extends BasicAction {
+  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.actions.MarkResolvedAction");
+
   protected String getActionName(AbstractVcs vcs) {
     return SvnBundle.message("action.name.mark.resolved");
   }
@@ -88,15 +92,13 @@
     }
     pathsArray = dialog.getSelectedPaths();
     try {
-      SVNWCClient wcClient = vcs.createWCClient();
       for (String path : pathsArray) {
         File ioFile = new File(path);
-        wcClient.doResolve(ioFile, SVNDepth.EMPTY, SVNConflictChoice.MERGED);
+        ConflictClient client = vcs.getFactory(ioFile).createConflictClient();
+
+        client.resolve(ioFile, true);
       }
     }
-    catch (SVNException e) {
-      throw new VcsException(e);
-    }
     finally {
       for (VirtualFile file : files) {
         VcsDirtyScopeManager.getInstance(project).fileDirty(file);
@@ -115,10 +117,12 @@
 
   private static Collection<String> collectResolvablePaths(final SvnVcs vcs, VirtualFile[] files) {
     final Collection<String> target = new TreeSet<String>();
-    SVNStatusClient stClient = vcs.createStatusClient();
     for (VirtualFile file : files) {
       try {
-        stClient.doStatus(new File(file.getPath()), true, false, false, false, new ISVNStatusHandler() {
+        File path = new File(file.getPath());
+        SvnStatusClientI client = vcs.getFactory(path).createStatusClient();
+
+        client.doStatus(path, true, false, false, false, new ISVNStatusHandler() {
           public void handleStatus(SVNStatus status) {
             if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED ||
                 status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
@@ -128,7 +132,7 @@
         });
       }
       catch (SVNException e) {
-        //
+        LOG.warn(e);
       }
     }
     return target;
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 4c582d0..3130dc9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
@@ -27,12 +27,13 @@
 import com.intellij.vcsUtil.VcsUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.svn.SvnRevisionNumber;
+import org.jetbrains.idea.svn.SvnUtil;
 import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
+import org.jetbrains.idea.svn.properties.PropertyClient;
 import org.tmatesoft.svn.core.SVNProperty;
 import org.tmatesoft.svn.core.SVNPropertyValue;
 import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -57,38 +58,34 @@
     final MergeData data = new MergeData();
     VcsRunnable runnable = new VcsRunnable() {
       public void run() throws VcsException {
-        SvnVcs vcs = SvnVcs.getInstance(myProject);
         File oldFile = null;
         File newFile = null;
         File workingFile = null;
-        SVNWCClient client;
         boolean mergeCase = false;
-        try {
-          client = vcs.createWCClient();
-          SVNInfo info = client.doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
-          if (info != null) {
-            oldFile = info.getConflictOldFile();
-            newFile = info.getConflictNewFile();
-            workingFile = info.getConflictWrkFile();
-            mergeCase = workingFile == null || workingFile.getName().contains("working");
-            // for debug
-            if (workingFile == null) {
-              LOG.info("Null working file when merging text conflict for " + file.getPath() + " old file: " + oldFile + " new file: " + newFile);
-            }
-            if (mergeCase) {
-              // this is merge case
-              oldFile = info.getConflictNewFile();
-              newFile = info.getConflictOldFile();
-              workingFile = info.getConflictWrkFile();
-            }
-            data.LAST_REVISION_NUMBER = new SvnRevisionNumber(info.getRevision());
+        SvnVcs vcs = SvnVcs.getInstance(myProject);
+        SVNInfo info = vcs.getInfo(file);
+
+        if (info != null) {
+          oldFile = info.getConflictOldFile();
+          newFile = info.getConflictNewFile();
+          workingFile = info.getConflictWrkFile();
+          mergeCase = workingFile == null || workingFile.getName().contains("working");
+          // for debug
+          if (workingFile == null) {
+            LOG.info("Null working file when merging text conflict for " + file.getPath() + " old file: " + oldFile + " new file: " + newFile);
           }
-        }
-        catch (SVNException e) {
-          throw new VcsException(e);
+          if (mergeCase) {
+            // this is merge case
+            oldFile = info.getConflictNewFile();
+            newFile = info.getConflictOldFile();
+            workingFile = info.getConflictWrkFile();
+          }
+          data.LAST_REVISION_NUMBER = new SvnRevisionNumber(info.getRevision());
+        } else {
+          throw new VcsException("Could not get info for " + file.getPath());
         }
         if (oldFile == null || newFile == null || workingFile == null) {
-          ByteArrayOutputStream bos = getBaseRevisionContents(client, file);
+          ByteArrayOutputStream bos = getBaseRevisionContents(vcs, file);
           data.ORIGINAL = bos.toByteArray();
           data.LAST = bos.toByteArray();
           data.CURRENT = readFile(new File(file.getPath()));
@@ -99,7 +96,7 @@
           data.CURRENT = readFile(workingFile);
         }
         if (mergeCase) {
-          final ByteArrayOutputStream contents = getBaseRevisionContents(vcs.createWCClient(), file);
+          final ByteArrayOutputStream contents = getBaseRevisionContents(vcs, file);
           if (! Arrays.equals(contents.toByteArray(), data.ORIGINAL)) {
             // swap base and server: another order of merge arguments
             byte[] original = data.ORIGINAL;
@@ -114,13 +111,17 @@
     return data;
   }
 
-  private ByteArrayOutputStream getBaseRevisionContents(SVNWCClient client, VirtualFile file) {
+  private ByteArrayOutputStream getBaseRevisionContents(@NotNull SvnVcs vcs, @NotNull VirtualFile file) {
     ByteArrayOutputStream bos = new ByteArrayOutputStream();
     try {
-      client.doGetFileContents(new File(file.getPath()), SVNRevision.UNDEFINED, SVNRevision.BASE, true, bos);
+      byte[] contents = SvnUtil.getFileContents(vcs, SvnTarget.fromFile(new File(file.getPath())), SVNRevision.BASE, SVNRevision.UNDEFINED);
+      bos.write(contents);
     }
-    catch (SVNException e) {
-      //
+    catch (VcsException e) {
+      LOG.warn(e);
+    }
+    catch (IOException e) {
+      LOG.warn(e);
     }
     return bos;
   }
@@ -135,13 +136,14 @@
   }
 
   public void conflictResolvedForFile(VirtualFile file) {
+    // TODO: Add possibility to resolve content conflicts separately from property conflicts.
     SvnVcs vcs = SvnVcs.getInstance(myProject);
+    File path = new File(file.getPath());
     try {
-      SVNWCClient client = vcs.createWCClient();
-      client.doResolve(new File(file.getPath()), SVNDepth.EMPTY, true, false, SVNConflictChoice.MERGED);
+      vcs.getFactory(path).createConflictClient().resolve(path, false);
     }
-    catch (SVNException e) {
-      //
+    catch (VcsException e) {
+      LOG.warn(e);
     }
     // the .mine/.r## files have been deleted
     final VirtualFile parent = file.getParent();
@@ -152,17 +154,20 @@
 
   public boolean isBinary(@NotNull final VirtualFile file) {
     SvnVcs vcs = SvnVcs.getInstance(myProject);
+
     try {
-      SVNWCClient client = vcs.createWCClient();
       File ioFile = new File(file.getPath());
-      SVNPropertyData svnPropertyData = client.doGetProperty(ioFile, SVNProperty.MIME_TYPE, SVNRevision.UNDEFINED, SVNRevision.WORKING);
+      PropertyClient client = vcs.getFactory(ioFile).createPropertyClient();
+
+      SVNPropertyData svnPropertyData = client.getProperty(ioFile, SVNProperty.MIME_TYPE, false, SVNRevision.UNDEFINED, SVNRevision.WORKING);
       if (svnPropertyData != null && SVNProperty.isBinaryMimeType(SVNPropertyValue.getPropertyAsString(svnPropertyData.getValue()))) {
         return true;
       }
     }
-    catch (SVNException e) {
-      //
+    catch (VcsException e) {
+      LOG.warn(e);
     }
+
     return false;
   }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/AddClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/AddClient.java
new file mode 100644
index 0000000..718a56d
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/AddClient.java
@@ -0,0 +1,23 @@
+package org.jetbrains.idea.svn.add;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface AddClient extends SvnClient {
+
+  void add(@NotNull File file,
+           @Nullable SVNDepth depth,
+           boolean makeParents,
+           boolean includeIgnored,
+           boolean force,
+           @Nullable ISVNEventHandler handler) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java
new file mode 100644
index 0000000..c786671
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java
@@ -0,0 +1,69 @@
+package org.jetbrains.idea.svn.add;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.containers.Convertor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.api.FileStatusResultParser;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNEvent;
+import org.tmatesoft.svn.core.wc.SVNStatusType;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdAddClient extends BaseSvnClient implements AddClient {
+
+  private static final String STATUS = "\\s*(\\w)\\s*";
+  private static final String OPTIONAL_FILE_TYPE = "(\\(.*\\))?";
+  private static final String PATH = "\\s*(.*?)\\s*";
+  private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + OPTIONAL_FILE_TYPE + PATH);
+
+  @Override
+  public void add(@NotNull File file,
+                  @Nullable SVNDepth depth,
+                  boolean makeParents,
+                  boolean includeIgnored,
+                  boolean force,
+                  @Nullable ISVNEventHandler handler) throws VcsException {
+    List<String> parameters = prepareParameters(file, depth, makeParents, includeIgnored, force);
+
+    // TODO: handler should be called in parallel with command execution, but this will be in other thread
+    // TODO: check if that is ok for current handler implementation
+    // TODO: add possibility to invoke "handler.checkCancelled" - process should be killed
+    CommandUtil.execute(myVcs, SvnCommandName.add, parameters, new FileStatusResultParser(CHANGED_PATH, handler, new AddStatusConvertor()));
+  }
+
+  private static List<String> prepareParameters(File file, SVNDepth depth, boolean makeParents, boolean includeIgnored, boolean force) {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, file);
+    CommandUtil.put(parameters, depth);
+    CommandUtil.put(parameters, makeParents, "--parents");
+    CommandUtil.put(parameters, includeIgnored, "--no-ignore");
+    CommandUtil.put(parameters, force, "--force");
+
+    return parameters;
+  }
+
+  private static class AddStatusConvertor implements Convertor<Matcher, SVNEvent> {
+    @Override
+    public SVNEvent convert(Matcher o) {
+      SVNStatusType contentStatus = CommandUtil.getStatusType(o.group(1));
+      String path = o.group(3);
+
+      return new SVNEvent(new File(path), null, null, 0, contentStatus, null, null, null, null, null, null, null,
+                          null, null, null);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java
new file mode 100644
index 0000000..d6250c7
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java
@@ -0,0 +1,39 @@
+package org.jetbrains.idea.svn.add;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNWCClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitAddClient extends BaseSvnClient implements AddClient {
+
+  @Override
+  public void add(@NotNull File file,
+                  @Nullable SVNDepth depth,
+                  boolean makeParents,
+                  boolean includeIgnored,
+                  boolean force,
+                  @Nullable ISVNEventHandler handler) throws VcsException {
+    try {
+      SVNWCClient client = myVcs.createWCClient();
+
+      client.setEventHandler(handler);
+      client.doAdd(file, force,
+                   false, // directory should already be created
+                   makeParents, // not used but will be passed as makeParents value
+                   SVNDepth.recurseFromDepth(depth));
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/AnnotateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/AnnotateClient.java
new file mode 100644
index 0000000..df30cfd
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/AnnotateClient.java
@@ -0,0 +1,24 @@
+package org.jetbrains.idea.svn.annotate;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;
+import org.tmatesoft.svn.core.wc.SVNDiffOptions;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface AnnotateClient extends SvnClient {
+
+  void annotate(@NotNull SvnTarget target,
+                @NotNull SVNRevision startRevision,
+                @NotNull SVNRevision endRevision,
+                @Nullable SVNRevision pegRevision,
+                boolean includeMergedRevisions,
+                @Nullable SVNDiffOptions diffOptions,
+                @Nullable ISVNAnnotateHandler handler) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java
new file mode 100644
index 0000000..d29d40ec
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java
@@ -0,0 +1,126 @@
+package org.jetbrains.idea.svn.annotate;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommand;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;
+import org.tmatesoft.svn.core.wc.SVNDiffOptions;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdAnnotateClient extends BaseSvnClient implements AnnotateClient {
+
+  @Override
+  public void annotate(@NotNull SvnTarget target,
+                       @NotNull SVNRevision startRevision,
+                       @NotNull SVNRevision endRevision,
+                       @Nullable SVNRevision pegRevision,
+                       boolean includeMergedRevisions,
+                       @Nullable SVNDiffOptions diffOptions,
+                       @Nullable final ISVNAnnotateHandler handler) throws VcsException {
+    // TODO: after merge remove setting includeMergedRevisions to false and update parsing
+    includeMergedRevisions = false;
+
+    List<String> parameters = new ArrayList<String>();
+    CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
+    parameters.add("--revision");
+    parameters.add(startRevision + ":" + endRevision);
+    CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
+    CommandUtil.put(parameters, diffOptions);
+    parameters.add("--xml");
+
+    SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.blame, parameters, null);
+
+    parseOutput(command.getOutput(), handler);
+  }
+
+  public void parseOutput(@NotNull String output, @Nullable ISVNAnnotateHandler handler) throws VcsException {
+    try {
+      JAXBContext context = JAXBContext.newInstance(BlameInfo.class);
+      Unmarshaller unmarshaller = context.createUnmarshaller();
+      BlameInfo info = (BlameInfo)unmarshaller.unmarshal(new StringReader(output));
+
+      if (handler != null && info != null && info.target != null && info.target.lineEntries != null) {
+        for (LineEntry entry : info.target.lineEntries) {
+          invokeHandler(handler, entry);
+        }
+      }
+    }
+    catch (JAXBException e) {
+      throw new VcsException(e);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+
+  private static void invokeHandler(ISVNAnnotateHandler handler, LineEntry entry) throws SVNException {
+    // line numbers in our api start from 0 - not from 1 like in svn output
+    handler.handleLine(entry.date(), entry.revision(), entry.author(), null, null, 0, null, null, entry.lineNumber - 1);
+  }
+
+  @XmlRootElement(name = "blame")
+  public static class BlameInfo {
+
+    @XmlElement(name = "target")
+    public TargetEntry target;
+  }
+
+  public static class TargetEntry {
+
+    @XmlElement(name = "entry")
+    List<LineEntry> lineEntries;
+  }
+
+  public static class LineEntry {
+
+    @XmlAttribute(name = "line-number")
+    public int lineNumber;
+
+    @XmlElement(name = "commit")
+    public CommitEntry commit;
+
+    public long revision() {
+      return commit != null ? commit.revision : 0;
+    }
+
+    public String author() {
+      return commit != null ? commit.author : null;
+    }
+
+    public Date date() {
+      return commit != null ? commit.date : null;
+    }
+  }
+
+  public static class CommitEntry {
+
+    @XmlAttribute(name = "revision")
+    public long revision;
+
+    @XmlElement(name = "author")
+    public String author;
+
+    @XmlElement(name = "date")
+    public Date date;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
index d0885c8..88adf25 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
@@ -32,14 +32,16 @@
 import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
 import com.intellij.openapi.vfs.CharsetToolkit;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.history.HistoryClient;
 import org.jetbrains.idea.svn.history.SvnChangeList;
 import org.jetbrains.idea.svn.history.SvnFileRevision;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -89,9 +91,8 @@
 
           final String contents;
           if (loadExternally) {
-            final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-            myVcs.createWCClient().doGetFileContents(ioFile, SVNRevision.UNDEFINED, SVNRevision.BASE, true, buffer);
-            contents = LoadTextUtil.getTextByBinaryPresentation(buffer.toByteArray(), file, false, false).toString();
+            byte[] data = SvnUtil.getFileContents(myVcs, SvnTarget.fromFile(ioFile), SVNRevision.BASE, SVNRevision.UNDEFINED);
+            contents = LoadTextUtil.getTextByBinaryPresentation(data, file, false, false).toString();
           } else {
             final byte[] bytes = VcsHistoryUtil.loadRevisionContent(revision);
             contents = LoadTextUtil.getTextByBinaryPresentation(bytes, file, false, false).toString();
@@ -99,16 +100,13 @@
 
           final SvnFileAnnotation result = new SvnFileAnnotation(myVcs, file, contents, lastChangedRevision);
 
-          SVNWCClient wcClient = myVcs.createWCClient();
-          info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED);
+          info = myVcs.getInfo(ioFile);
           if (info == null) {
               exception[0] = new VcsException(new SVNException(SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "File ''{0}'' is not under version control", ioFile)));
               return;
           }
           final String url = info.getURL() == null ? null : info.getURL().toString();
 
-          SVNLogClient client = myVcs.createLogClient();
-          setLogClientOptions(client);
           SVNRevision endRevision = ((SvnFileRevision) revision).getRevision();
           if (SVNRevision.WORKING.equals(endRevision)) {
             endRevision = info.getRevision();
@@ -122,14 +120,20 @@
 
           final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE &&
                                              SvnUtil.checkRepositoryVersion15(myVcs, url);
-          final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
+          final MySteppedLogGetter logGetter = new MySteppedLogGetter(
+            myVcs, ioFile, progress,
+            myVcs.getFactory(ioFile).createHistoryClient(), endRevision, result,
+            url, calculateMergeinfo, file.getCharset());
 
-          final MySteppedLogGetter logGetter = new MySteppedLogGetter(myVcs, ioFile, progress, client, endRevision, result, url, calculateMergeinfo, file.getCharset());
           logGetter.go();
           final LinkedList<SVNRevision> rp = logGetter.getRevisionPoints();
 
+          // TODO: only 2 elements will be in rp and for loop will be executed only once - probably rewrite with Pair
+          AnnotateClient annotateClient = myVcs.getFactory(ioFile).createAnnotateClient();
           for (int i = 0; i < rp.size() - 1; i++) {
-            client.doAnnotate(ioFile, svnRevision, rp.get(i + 1), rp.get(i), true, calculateMergeinfo, annotateHandler, null);
+            annotateClient.annotate(SvnTarget.fromFile(ioFile), rp.get(i + 1), rp.get(i), ((SvnFileRevision)revision).getPegRevision(),
+                                    calculateMergeinfo,
+                                    getLogClientOptions(myVcs), annotateHandler);
           }
 
           if (rp.get(1).getNumber() > 0) {
@@ -137,31 +141,15 @@
           }
           annotation[0] = result;
         }
-        catch (SVNException e) {
-          if (SVNErrorCode.FS_NOT_FOUND.equals(e.getErrorMessage().getErrorCode())) {
-            final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> provider = myVcs.getCommittedChangesProvider();
-            try {
-              final Pair<SvnChangeList, FilePath> pair = provider.getOneList(file, revision.getRevisionNumber());
-              if (pair != null && info != null && pair.getSecond() != null && ! Comparing.equal(pair.getSecond().getIOFile(), ioFile)) {
-                annotation[0] = annotateNonExisting(pair, revision, info, file.getCharset(), file);
-                return;
-              }
-            }
-            catch (VcsException e1) {
-              exception[0] = e1;
-            }
-            catch (SVNException e1) {
-              exception[0] = new VcsException(e);
-            }
-            catch (IOException e1) {
-              exception[0] = new VcsException(e);
-            }
-          }
-          exception[0] = new VcsException(e);
-        } catch (IOException e) {
+        catch (IOException e) {
           exception[0] = new VcsException(e);
         } catch (VcsException e) {
-          exception[0] = e;
+          if (e.getCause() instanceof SVNException) {
+            handleSvnException(ioFile, info, (SVNException)e.getCause(), file, revision, annotation, exception);
+          }
+          else {
+            exception[0] = e;
+          }
         }
       }
     };
@@ -177,6 +165,35 @@
     return annotation[0];
   }
 
+  private void handleSvnException(File ioFile,
+                                  SVNInfo info,
+                                  SVNException e,
+                                  VirtualFile file,
+                                  VcsFileRevision revision,
+                                  FileAnnotation[] annotation, VcsException[] exception) {
+    // TODO: Check how this scenario could be reproduced by user and what changes needs to be done for command line client
+    if (SVNErrorCode.FS_NOT_FOUND.equals(e.getErrorMessage().getErrorCode())) {
+      final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> provider = myVcs.getCommittedChangesProvider();
+      try {
+        final Pair<SvnChangeList, FilePath> pair = provider.getOneList(file, revision.getRevisionNumber());
+        if (pair != null && info != null && pair.getSecond() != null && ! Comparing.equal(pair.getSecond().getIOFile(), ioFile)) {
+          annotation[0] = annotateNonExisting(pair, revision, info, file.getCharset(), file);
+          return;
+        }
+      }
+      catch (VcsException e1) {
+        exception[0] = e1;
+      }
+      catch (SVNException e1) {
+        exception[0] = new VcsException(e);
+      }
+      catch (IOException e1) {
+        exception[0] = new VcsException(e);
+      }
+    }
+    exception[0] = new VcsException(e);
+  }
+
   public static File getCommonAncestor(final File file1, final File file2) throws IOException {
     if (FileUtil.filesEqual(file1, file2)) return file1;
     final File can1 = file1.getCanonicalFile();
@@ -214,8 +231,7 @@
     final String relativePath = FileUtil.getRelativePath(root.getPath(), wasFile.getPath(), File.separatorChar);
     if (relativePath == null) throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
 
-    SVNWCClient wcClient = myVcs.createWCClient();
-    SVNInfo wcRootInfo = wcClient.doInfo(root, SVNRevision.UNDEFINED);
+    SVNInfo wcRootInfo = myVcs.getInfo(root);
     if (wcRootInfo == null || wcRootInfo.getURL() == null) {
         throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
     }
@@ -225,21 +241,18 @@
       wasUrl = wasUrl.appendPath(string, true);
     }
 
-    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
     final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
-    myVcs.createWCClient().doGetFileContents(wasUrl, svnRevision, svnRevision, true, buffer);
-    final String contents = LoadTextUtil.getTextByBinaryPresentation(buffer.toByteArray(),
-                                                                     charset == null ? CharsetToolkit.UTF8_CHARSET : charset).toString();
-    SVNLogClient client = myVcs.createLogClient();
-    setLogClientOptions(client);
+    byte[] data = SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(wasUrl), svnRevision, svnRevision);
+    final String contents = LoadTextUtil.getTextByBinaryPresentation(data, charset == null ? CharsetToolkit.UTF8_CHARSET : charset).toString();
     final SvnRemoteFileAnnotation result = new SvnRemoteFileAnnotation(myVcs, contents, revision.getRevisionNumber(), pair.getFirst(),
                                                                        pair.getSecond().getPath(), current);
     final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(ProgressManager.getInstance().getProgressIndicator(), result);
 
     final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE &&
                                        SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString());
-    client.doAnnotate(wasUrl, svnRevision, SVNRevision.create(1), svnRevision, true, calculateMergeinfo, annotateHandler, null);
-
+    AnnotateClient client = myVcs.getFactory().createAnnotateClient();
+    client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo,
+                    getLogClientOptions(myVcs), annotateHandler);
     return result;
   }
 
@@ -370,14 +383,14 @@
     private final SvnVcs myVcs;
     private final File myIoFile;
     private final ProgressIndicator myProgress;
-    private final SVNLogClient myClient;
+    private final HistoryClient myClient;
     private final SVNRevision myEndRevision;
     private final boolean myCalculateMergeinfo;
     private final SvnFileAnnotation myResult;
     private final String myUrl;
     private final Charset myCharset;
 
-    private MySteppedLogGetter(final SvnVcs vcs, final File ioFile, final ProgressIndicator progress, final SVNLogClient client,
+    private MySteppedLogGetter(final SvnVcs vcs, final File ioFile, final ProgressIndicator progress, final HistoryClient client,
                                final SVNRevision endRevision,
                                final SvnFileAnnotation result,
                                final String url,
@@ -395,7 +408,7 @@
       myRevisionPoints = new LinkedList<SVNRevision>();
     }
 
-    public void go() throws SVNException {
+    public void go() throws VcsException {
       final int maxAnnotateRevisions = SvnConfiguration.getInstance(myVcs.getProject()).getMaxAnnotateRevisions();
       boolean longHistory = true;
       if (maxAnnotateRevisions == -1) {
@@ -437,8 +450,8 @@
       myRevisionPoints.add(SVNRevision.create(0));
     }
 
-    private void doLog(final boolean includeMerged, final SVNRevision truncateTo, final int max) throws SVNException {
-      myClient.doLog(new File[]{myIoFile}, myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
+    private void doLog(final boolean includeMerged, final SVNRevision truncateTo, final int max) throws VcsException {
+      myClient.doLog(myIoFile, myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
                      SVNRevision.UNDEFINED, false, false, includeMerged, max, null,
                      new ISVNLogEntryHandler() {
                        public void handleLogEntry(SVNLogEntry logEntry) {
@@ -464,9 +477,7 @@
     return true;
   }
 
-  private void setLogClientOptions(final SVNLogClient client) {
-    if (SvnConfiguration.getInstance(myVcs.getProject()).IGNORE_SPACES_IN_ANNOTATE) {
-      client.setDiffOptions(new SVNDiffOptions(true, true, true));
-    }
+  private static SVNDiffOptions getLogClientOptions(@NotNull SvnVcs vcs) {
+    return SvnConfiguration.getInstance(vcs.getProject()).IGNORE_SPACES_IN_ANNOTATE ? new SVNDiffOptions(true, true, true) : null;
   }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnKitAnnotateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnKitAnnotateClient.java
new file mode 100644
index 0000000..315178c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnKitAnnotateClient.java
@@ -0,0 +1,42 @@
+package org.jetbrains.idea.svn.annotate;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;
+import org.tmatesoft.svn.core.wc.SVNDiffOptions;
+import org.tmatesoft.svn.core.wc.SVNLogClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitAnnotateClient extends BaseSvnClient implements AnnotateClient {
+
+  @Override
+  public void annotate(@NotNull SvnTarget target,
+                       @NotNull SVNRevision startRevision,
+                       @NotNull SVNRevision endRevision,
+                       @Nullable SVNRevision pegRevision,
+                       boolean includeMergedRevisions,
+                       @Nullable SVNDiffOptions diffOptions,
+                       @Nullable ISVNAnnotateHandler handler) throws VcsException {
+    try {
+      SVNLogClient client = myVcs.createLogClient();
+
+      client.setDiffOptions(diffOptions);
+      if (target.isFile()) {
+        client.doAnnotate(target.getFile(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, handler, null);
+      }
+      else {
+        client.doAnnotate(target.getURL(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, handler, null);
+      }
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java
new file mode 100644
index 0000000..54401cf
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java
@@ -0,0 +1,22 @@
+package org.jetbrains.idea.svn.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public abstract class BaseSvnClient implements SvnClient {
+  protected SvnVcs myVcs;
+
+  @NotNull
+  @Override
+  public SvnVcs getVcs() {
+    return myVcs;
+  }
+
+  @Override
+  public void setVcs(@NotNull SvnVcs vcs) {
+    myVcs = vcs;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java
new file mode 100644
index 0000000..b851216
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java
@@ -0,0 +1,99 @@
+package org.jetbrains.idea.svn.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.add.AddClient;
+import org.jetbrains.idea.svn.annotate.AnnotateClient;
+import org.jetbrains.idea.svn.conflict.ConflictClient;
+import org.jetbrains.idea.svn.content.ContentClient;
+import org.jetbrains.idea.svn.copy.CopyMoveClient;
+import org.jetbrains.idea.svn.delete.DeleteClient;
+import org.jetbrains.idea.svn.history.HistoryClient;
+import org.jetbrains.idea.svn.portable.SvnStatusClientI;
+import org.jetbrains.idea.svn.properties.PropertyClient;
+import org.jetbrains.idea.svn.revert.RevertClient;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public abstract class ClientFactory {
+
+  @NotNull
+  protected SvnVcs myVcs;
+
+  protected AddClient addClient;
+  protected AnnotateClient annotateClient;
+  protected ContentClient contentClient;
+  protected HistoryClient historyClient;
+  protected RevertClient revertClient;
+  protected DeleteClient deleteClient;
+  protected SvnStatusClientI statusClient;
+  protected CopyMoveClient copyMoveClient;
+  protected ConflictClient conflictClient;
+  protected PropertyClient propertyClient;
+
+  protected ClientFactory(@NotNull SvnVcs vcs) {
+    myVcs = vcs;
+    setup();
+  }
+
+  protected abstract void setup();
+
+  @NotNull
+  public AddClient createAddClient() {
+    return prepare(addClient);
+  }
+
+  @NotNull
+  public AnnotateClient createAnnotateClient() {
+    return prepare(annotateClient);
+  }
+
+  @NotNull
+  public ContentClient createContentClient() {
+    return prepare(contentClient);
+  }
+
+  @NotNull
+  public HistoryClient createHistoryClient() {
+    return prepare(historyClient);
+  }
+
+  @NotNull
+  public RevertClient createRevertClient() {
+    return prepare(revertClient);
+  }
+
+  @NotNull
+  public SvnStatusClientI createStatusClient() {
+    // TODO: Update this in same like other clients - move to corresponding package, rename clients
+    return statusClient;
+  }
+
+  @NotNull
+  public DeleteClient createDeleteClient() {
+    return prepare(deleteClient);
+  }
+
+  @NotNull
+  public CopyMoveClient createCopyMoveClient() {
+    return prepare(copyMoveClient);
+  }
+
+  @NotNull
+  public ConflictClient createConflictClient() {
+    return prepare(conflictClient);
+  }
+
+  @NotNull
+  public PropertyClient createPropertyClient() {
+    return prepare(propertyClient);
+  }
+
+  @NotNull
+  protected <T extends SvnClient> T prepare(@NotNull T client) {
+    client.setVcs(myVcs);
+
+    return client;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java
new file mode 100644
index 0000000..ca4088b
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java
@@ -0,0 +1,38 @@
+package org.jetbrains.idea.svn.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.add.CmdAddClient;
+import org.jetbrains.idea.svn.annotate.CmdAnnotateClient;
+import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
+import org.jetbrains.idea.svn.conflict.CmdConflictClient;
+import org.jetbrains.idea.svn.content.CmdContentClient;
+import org.jetbrains.idea.svn.copy.CmdCopyMoveClient;
+import org.jetbrains.idea.svn.delete.CmdDeleteClient;
+import org.jetbrains.idea.svn.history.CmdHistoryClient;
+import org.jetbrains.idea.svn.properties.CmdPropertyClient;
+import org.jetbrains.idea.svn.revert.CmdRevertClient;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdClientFactory extends ClientFactory {
+
+  public CmdClientFactory(@NotNull SvnVcs vcs) {
+    super(vcs);
+  }
+
+  @Override
+  protected void setup() {
+    addClient = new CmdAddClient();
+    annotateClient = new CmdAnnotateClient();
+    contentClient = new CmdContentClient();
+    historyClient = new CmdHistoryClient();
+    revertClient = new CmdRevertClient();
+    deleteClient = new CmdDeleteClient();
+    copyMoveClient = new CmdCopyMoveClient();
+    conflictClient = new CmdConflictClient();
+    propertyClient = new CmdPropertyClient();
+    statusClient = new SvnCommandLineStatusClient(myVcs.getProject());
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/FileStatusResultParser.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/FileStatusResultParser.java
new file mode 100644
index 0000000..fc202c2
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/FileStatusResultParser.java
@@ -0,0 +1,68 @@
+package org.jetbrains.idea.svn.api;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.containers.Convertor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNEvent;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class FileStatusResultParser {
+
+  private static final double DEFAULT_PROGRESS = 0.0;
+
+  @NotNull
+  private Pattern myLinePattern;
+
+  @Nullable
+  private ISVNEventHandler handler;
+
+  @NotNull
+  private Convertor<Matcher, SVNEvent> myConvertor;
+
+  public FileStatusResultParser(@NotNull Pattern linePattern,
+                                @Nullable ISVNEventHandler handler,
+                                @NotNull Convertor<Matcher, SVNEvent> convertor) {
+    myLinePattern = linePattern;
+    this.handler = handler;
+    myConvertor = convertor;
+  }
+
+  public void parse(@NotNull String output) throws VcsException {
+    if (StringUtil.isEmpty(output)) {
+      return;
+    }
+
+    for (String line : StringUtil.splitByLines(output)) {
+      onLine(line);
+    }
+  }
+
+  public void onLine(@NotNull String line) throws VcsException {
+    Matcher matcher = myLinePattern.matcher(line);
+    if (matcher.matches()) {
+      process(matcher);
+    }
+    else {
+      throw new VcsException("unknown state on line " + line);
+    }
+  }
+
+  public void process(@NotNull Matcher matcher) throws VcsException {
+    if (handler != null) {
+      try {
+        handler.handleEvent(myConvertor.convert(matcher), DEFAULT_PROGRESS);
+      } catch (SVNException e) {
+        throw new VcsException(e);
+      }
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java
new file mode 100644
index 0000000..90124f1
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java
@@ -0,0 +1,15 @@
+package org.jetbrains.idea.svn.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface SvnClient {
+
+  @NotNull
+  SvnVcs getVcs();
+
+  void setVcs(@NotNull SvnVcs vcs);
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java
new file mode 100644
index 0000000..7e19518
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java
@@ -0,0 +1,38 @@
+package org.jetbrains.idea.svn.api;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.add.SvnKitAddClient;
+import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient;
+import org.jetbrains.idea.svn.conflict.SvnKitConflictClient;
+import org.jetbrains.idea.svn.content.SvnKitContentClient;
+import org.jetbrains.idea.svn.copy.SvnKitCopyMoveClient;
+import org.jetbrains.idea.svn.delete.SvnKitDeleteClient;
+import org.jetbrains.idea.svn.history.SvnKitHistoryClient;
+import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient;
+import org.jetbrains.idea.svn.properties.SvnKitPropertyClient;
+import org.jetbrains.idea.svn.revert.SvnKitRevertClient;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitClientFactory extends ClientFactory {
+
+  public SvnKitClientFactory(@NotNull SvnVcs vcs) {
+    super(vcs);
+  }
+
+  @Override
+  protected void setup() {
+    addClient = new SvnKitAddClient();
+    annotateClient = new SvnKitAnnotateClient();
+    contentClient = new SvnKitContentClient();
+    historyClient = new SvnKitHistoryClient();
+    revertClient = new SvnKitRevertClient();
+    deleteClient = new SvnKitDeleteClient();
+    copyMoveClient = new SvnKitCopyMoveClient();
+    conflictClient = new SvnKitConflictClient();
+    propertyClient = new SvnKitPropertyClient();
+    statusClient = new SvnkitSvnStatusClient(myVcs.createStatusClient());
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java
index 021568a..2b779fd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java
@@ -49,7 +49,7 @@
       final SvnVcs vcs = SvnVcs.getInstance(project);
 
       File rootFile = new File(vcsRoot.getPath());
-      final SVNInfo info = vcs.createWCClient().doInfo(rootFile, SVNRevision.UNDEFINED);
+      final SVNInfo info = vcs.getInfo(rootFile);
       if (info == null || info.getURL() == null) {
         LOG.info("Directory is not a working copy: " + vcsRoot.getPresentableUrl());
         return null;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
index 28e74e7..483bfda 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
@@ -223,9 +223,8 @@
     private BranchRootSearcher(final SvnVcs vcs, final VirtualFile root) throws SVNException {
       myRoot = root;
       myBranchesUnder = new HashMap<String, String>();
-      final SVNWCClient client = vcs.createWCClient();
-      final SVNInfo info = client.doInfo(new File(myRoot.getPath()), SVNRevision.UNDEFINED);
-      myRootUrl = info.getURL();
+      final SVNInfo info = vcs.getInfo(myRoot.getPath());
+      myRootUrl = info != null ? info.getURL() : null;
     }
 
     public boolean accept(final String url) throws SVNException {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java
index 3bd8256..5ac6b96 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java
@@ -16,8 +16,8 @@
 package org.jetbrains.idea.svn.checkin;
 
 import com.intellij.openapi.progress.ProgressIndicator;
-import org.jetbrains.idea.svn.CommitEventHandler;
-import org.jetbrains.idea.svn.CommitEventType;
+import org.jetbrains.idea.svn.commandLine.CommitEventHandler;
+import org.jetbrains.idea.svn.commandLine.CommitEventType;
 import org.jetbrains.idea.svn.SvnBundle;
 
 import java.io.File;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
index 995646f..f765595 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
@@ -28,6 +28,7 @@
 import com.intellij.util.proxy.CommonProxy;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.commandLine.AuthenticationCallback;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.auth.*;
 import org.tmatesoft.svn.core.internal.util.SVNBase64;
@@ -77,6 +78,20 @@
     return new CredentialsAuthenticator(myVcs).tryAuthenticate(realm, url, file, previousFailed, passwordRequest);
   }
 
+  @Nullable
+  @Override
+  public SVNAuthentication requestCredentials(@Nullable SVNURL url, String type) {
+    SVNAuthentication authentication =
+      url != null ? myVcs.getSvnConfiguration().getInteractiveManager(myVcs).getProvider().requestClientAuthentication(
+        type, url, url.toDecodedString(), null, null, true) : null;
+
+    if (authentication == null) {
+      LOG.warn("Could not get authentication. Type - " + type + ", Url - " + url);
+    }
+
+    return authentication;
+  }
+
   @Override
   public boolean acceptSSLServerCertificate(final File file, final String realm) {
     final File base = getExistingParent(file);
@@ -354,7 +369,9 @@
                                     }, new ThrowableRunnable<SVNException>() {
                                       @Override
                                       public void run() throws SVNException {
+                                        // NOTE: DO NOT replace this call - SSL authentication highly tied to SVNKit
                                         myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
+                                        //myVcs.getInfo(myUrl, SVNRevision.HEAD, active);
                                       }
                                     }
       );
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
index 433e406..c7d2d4b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
@@ -48,8 +48,8 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.commandLine.SvnBindClient;
 import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
-import org.tigris.subversion.javahl.ClientException;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.wc.*;
 
@@ -177,7 +177,7 @@
     if (committables.isEmpty()) {
       return;
     }
-    if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format) &&
+    if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format) &&
         SvnConfiguration.UseAcceleration.commandLine.equals(SvnConfiguration.getInstance(mySvnVcs.getProject()).myUseAcceleration) &&
         (SvnAuthenticationManager.HTTP.equals(url.getProtocol()) || SvnAuthenticationManager.HTTPS.equals(url.getProtocol()))) {
       doWithCommandLine(committables, comment, exception, feedback);
@@ -256,14 +256,25 @@
     });
     final IdeaSvnkitBasedAuthenticationCallback authenticationCallback = new IdeaSvnkitBasedAuthenticationCallback(mySvnVcs);
     try {
-      final SvnBindClient client = new SvnBindClient(SvnApplicationSettings.getInstance().getCommandLinePath());
+      final SvnBindClient client = new SvnBindClient(SvnApplicationSettings.getInstance().getCommandLinePath(), new Convertor<String[], SVNURL>() {
+        @Override
+        public SVNURL convert(String[] o) {
+          SVNInfo info = o.length > 0 ? mySvnVcs.getInfo(o[0]) : null;
+
+          if (info == null || info.getURL() == null) {
+            LOG.warn("Could not resolve repository url for commit. Paths - " + Arrays.toString(o));
+          }
+
+          return info != null ? info.getURL() : null;
+        }
+      });
       client.setAuthenticationCallback(authenticationCallback);
       client.setHandler(new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()));
       final long revision = client.commit(ArrayUtil.toStringArray(paths), comment, false, false);
       reportCommittedRevisions(feedback, String.valueOf(revision));
     }
-    catch (ClientException e) {
-      exception.add(new VcsException(e));
+    catch (VcsException e) {
+      exception.add(e);
     } finally {
       authenticationCallback.reset();
     }
@@ -348,25 +359,19 @@
   private List<File> getCommitables(List<File> paths) {
     final Adder adder = new Adder();
 
-    SVNStatusClient statusClient = mySvnVcs.createStatusClient();
     for (File path : paths) {
       File file = path.getAbsoluteFile();
       adder.add(file);
       if (file.getParentFile() != null) {
-        addParents(statusClient, file.getParentFile(), adder);
+        addParents(file.getParentFile(), adder);
       }
     }
     return adder.getResult();
   }
 
-  private static void addParents(SVNStatusClient statusClient, File file, final Adder adder) {
-    SVNStatus status;
-    try {
-      status = statusClient.doStatus(file, false);
-    }
-    catch (SVNException e) {
-      return;
-    }
+  private void addParents(File file, final Adder adder) {
+    SVNStatus status = getStatus(file);
+
     if (status != null &&
         (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED) ||
          SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_REPLACED))) {
@@ -374,11 +379,33 @@
       adder.add(file);
       file = file.getParentFile();
       if (file != null) {
-        addParents(statusClient, file, adder);
+        addParents(file, adder);
       }
     }
   }
 
+  private SVNStatus getStatus(File file) {
+    SVNStatus result = null;
+    WorkingCopyFormat format = mySvnVcs.getWorkingCopyFormat(file);
+
+    try {
+      result = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? getStatusCommandLine(file) : getStatusSvnKit(file);
+    }
+    catch (SVNException e) {
+      // do nothing
+    }
+
+    return result;
+  }
+
+  private SVNStatus getStatusSvnKit(File file) throws SVNException {
+    return mySvnVcs.createStatusClient().doStatus(file, false);
+  }
+
+  private SVNStatus getStatusCommandLine(File file) throws SVNException {
+    return new SvnCommandLineStatusClient(mySvnVcs.getProject()).doStatus(file, false);
+  }
+
   private static List<File> collectPaths(final List<Change> changes) {
     // case sensitive..
     ArrayList<File> result = new ArrayList<File>();
@@ -418,15 +445,14 @@
 
   public List<VcsException> scheduleMissingFileForDeletion(List<FilePath> filePaths) {
     List<VcsException> exceptions = new ArrayList<VcsException>();
-    final SVNWCClient wcClient = mySvnVcs.createWCClient();
-
     List<File> files = ChangesUtil.filePathsToFiles(filePaths);
+
     for (File file : files) {
       try {
-        wcClient.doDelete(file, true, false);
+        mySvnVcs.getFactory(file).createDeleteClient().delete(file, true);
       }
-      catch (SVNException e) {
-        exceptions.add(new VcsException(e));
+      catch (VcsException e) {
+        exceptions.add(e);
       }
     }
 
@@ -434,30 +460,22 @@
   }
 
   public List<VcsException> scheduleUnversionedFilesForAddition(List<VirtualFile> files) {
-    final List<VcsException> result = new ArrayList<VcsException>();
-    final SVNWCClient wcClient = mySvnVcs.createWCClient();
-
-    final List<SVNException> exceptionList = scheduleUnversionedFilesForAddition(wcClient, files);
-    for (SVNException svnException : exceptionList) {
-      result.add(new VcsException(svnException));
-    }
-    return result;
+    return scheduleUnversionedFilesForAddition(mySvnVcs, files);
   }
 
-  public static List<SVNException> scheduleUnversionedFilesForAddition(SVNWCClient wcClient, List<VirtualFile> files) {
-    return scheduleUnversionedFilesForAddition(wcClient, files, false);
+  public static List<VcsException> scheduleUnversionedFilesForAddition(@NotNull SvnVcs vcs, List<VirtualFile> files) {
+    return scheduleUnversionedFilesForAddition(vcs, files, false);
   }
 
-  public static List<SVNException> scheduleUnversionedFilesForAddition(SVNWCClient wcClient, List<VirtualFile> files, final boolean recursive) {
-    List<SVNException> exceptions = new ArrayList<SVNException>();
-
+  public static List<VcsException> scheduleUnversionedFilesForAddition(@NotNull SvnVcs vcs, List<VirtualFile> files, final boolean recursive) {
     Collections.sort(files, FilePathComparator.getInstance());
 
-    wcClient.setEventHandler(new ISVNEventHandler() {
+    ISVNEventHandler eventHandler = new ISVNEventHandler() {
       @Override
       public void handleEvent(SVNEvent event, double progress) throws SVNException {
         final ProgressManager pm = ProgressManager.getInstance();
         final ProgressIndicator pi = pm.getProgressIndicator();
+        // TODO: pi is null here when invoking "Add" action
         if (pi != null && event.getFile() != null) {
           File file = event.getFile();
           pi.setText(SvnBundle.message("progress.text2.adding", file.getName() + " (" + file.getParent() + ")"));
@@ -472,12 +490,18 @@
           if (pi.isCanceled()) throw new SVNCancelException();
         }
       }
-    });
+    };
+
+    List<VcsException> exceptions = new ArrayList<VcsException>();
+
     for (VirtualFile file : files) {
       try {
-        wcClient.doAdd(new File(FileUtil.toSystemDependentName(file.getPath())), true, false, true, recursive);
+        File convertedFile = new File(FileUtil.toSystemDependentName(file.getPath()));
+        SVNDepth depth = recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY;
+
+        vcs.getFactory(convertedFile).createAddClient().add(convertedFile, depth, true, false, true, eventHandler);
       }
-      catch (SVNException e) {
+      catch (VcsException e) {
         exceptions.add(e);
       }
     }
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java
similarity index 87%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java
index bdc9c2d..1944749 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java
@@ -13,9 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.commandLine;
 
 import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.auth.SVNAuthentication;
 
 import java.io.File;
 import java.io.IOException;
@@ -51,6 +53,17 @@
   boolean authenticateFor(@Nullable String realm, File base, boolean previousFailed, boolean passwordRequest);
 
   /**
+   * Provides authentication information to access given url by authentication protocol identified by type.
+   * For instance, username/password for http/svn protocols. SSL client certificate for two way SSL protocol.
+   *
+   * @param url  url to item in repository
+   * @param type authentication protocol type with svn specific values, like "svn.simple" for http.
+   * @return
+   */
+  @Nullable
+  SVNAuthentication requestCredentials(@Nullable SVNURL url, String type);
+
+  /**
    * @return config directory if TMP was created
    */
   @Nullable
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
new file mode 100644
index 0000000..737d8a8
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
@@ -0,0 +1,218 @@
+package org.jetbrains.idea.svn.commandLine;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnApplicationSettings;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.api.FileStatusResultParser;
+import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.wc.SVNDiffOptions;
+import org.tmatesoft.svn.core.wc.SVNInfo;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc.SVNStatusType;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CommandUtil {
+  public static SvnLineCommand runSimple(@NotNull SvnCommandName name,
+                                         @NotNull SvnVcs vcs,
+                                         @Nullable File base,
+                                         @Nullable SVNURL url,
+                                         List<String> parameters)
+    throws SVNException {
+    String exe = resolveExePath();
+    base = resolveBaseDirectory(base, exe);
+    url = resolveRepositoryUrl(vcs, url);
+
+    try {
+      return SvnLineCommand
+        .runWithAuthenticationAttempt(exe, base, url, name, new SvnCommitRunner.CommandListener(null),
+                                      new IdeaSvnkitBasedAuthenticationCallback(vcs), ArrayUtil.toStringArray(parameters));
+    }
+    catch (SvnBindException e) {
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
+    }
+  }
+
+  @Nullable
+  private static SVNURL resolveRepositoryUrl(@NotNull SvnVcs vcs, @Nullable SVNURL url) {
+    if (url == null) {
+      // TODO: or take it from RootUrlInfo
+      SVNInfo info = vcs.getInfo(vcs.getProject().getBaseDir());
+
+      url = info != null ? info.getURL() : null;
+    }
+    return url;
+  }
+
+  @NotNull
+  private static File resolveBaseDirectory(@Nullable File base, @NotNull String defaultBase) {
+    return base == null ? new File(defaultBase) : base;
+  }
+
+  @NotNull
+  private static String resolveExePath() {
+    return SvnApplicationSettings.getInstance().getCommandLinePath();
+  }
+
+  public static SvnLineCommand runSimple(@NotNull SvnSimpleCommand command, @NotNull SvnVcs vcs, @Nullable File base, @Nullable SVNURL url)
+    throws SVNException {
+    // empty command name passed, as command name is already in command.getParameters()
+    return runSimple(SvnCommandName.empty, vcs, base, url, new ArrayList<String>(Arrays.asList(command.getParameters())));
+  }
+
+  /**
+   * Puts given value to parameters if condition is satisfied
+   *
+   * @param parameters
+   * @param condition
+   * @param value
+   */
+  public static void put(@NotNull List<String> parameters, boolean condition, @NotNull String value) {
+    if (condition) {
+      parameters.add(value);
+    }
+  }
+
+  public static void put(@NotNull List<String> parameters, @NotNull File path) {
+    parameters.add(path.getAbsolutePath());
+  }
+
+  public static void put(@NotNull List<String> parameters, @NotNull File path, @Nullable SVNRevision pegRevision) {
+    put(parameters, path.getAbsolutePath(), pegRevision);
+  }
+
+  public static void put(@NotNull List<String> parameters, @NotNull String path, @Nullable SVNRevision pegRevision) {
+    StringBuilder builder = new StringBuilder(path);
+
+    if (pegRevision != null && !SVNRevision.UNDEFINED.equals(pegRevision) && !SVNRevision.WORKING.equals(pegRevision) &&
+        pegRevision.getNumber() > 0) {
+      builder.append("@");
+      builder.append(pegRevision);
+    }
+
+    parameters.add(builder.toString());
+  }
+
+  public static void put(@NotNull List<String> parameters, @NotNull File... paths) {
+    for (File path : paths) {
+      put(parameters, path);
+    }
+  }
+
+  public static void put(@NotNull List<String> parameters, @Nullable SVNDepth depth) {
+    if (depth != null && !SVNDepth.UNKNOWN.equals(depth)) {
+      parameters.add("--depth");
+      parameters.add(depth.getName());
+    }
+  }
+
+  public static void put(@NotNull List<String> parameters, @Nullable SVNRevision revision) {
+    if (revision != null && !SVNRevision.UNDEFINED.equals(revision) && !SVNRevision.WORKING.equals(revision) && revision.getNumber() >= 0) {
+      parameters.add("--revision");
+      parameters.add(revision.toString());
+    }
+  }
+
+  public static void put(@NotNull List<String> parameters, @Nullable SVNDiffOptions diffOptions) {
+    if (diffOptions != null) {
+      StringBuilder builder = new StringBuilder();
+
+      if (diffOptions.isIgnoreAllWhitespace()) {
+        builder.append(" --ignore-space-change");
+      }
+      if (diffOptions.isIgnoreAmountOfWhitespace()) {
+        builder.append(" --ignore-all-space");
+      }
+      if (diffOptions.isIgnoreEOLStyle()) {
+        builder.append(" --ignore-eol-style");
+      }
+
+      String value = builder.toString().trim();
+
+      if (!StringUtil.isEmpty(value)) {
+        parameters.add("--extensions");
+        parameters.add(value);
+      }
+    }
+  }
+
+  /**
+   * Utility method for running commands changing certain file status information.
+   * // TODO: Should be replaced with non-static analogue.
+   *
+   * @param vcs
+   * @param name
+   * @param parameters
+   * @param parser
+   * @throws VcsException
+   */
+  public static SvnCommand execute(@NotNull SvnVcs vcs,
+                                   @NotNull SvnCommandName name,
+                                   @NotNull List<String> parameters,
+                                   @Nullable FileStatusResultParser parser)
+    throws VcsException {
+    String exe = resolveExePath();
+    File base = resolveBaseDirectory(null, exe);
+    SVNURL url = resolveRepositoryUrl(vcs, null);
+
+    SvnLineCommand command = SvnLineCommand.runWithAuthenticationAttempt(
+      exe, base, url, name, new SvnCommitRunner.CommandListener(null),
+      new IdeaSvnkitBasedAuthenticationCallback(vcs),
+      ArrayUtil.toStringArray(parameters));
+
+    if (parser != null) {
+      parser.parse(command.getOutput());
+    }
+
+    return command;
+  }
+
+  /**
+   * Gets svn status represented by single character.
+   *
+   * @param type
+   * @return
+   */
+  public static char getStatusChar(@Nullable String type) {
+    return !StringUtil.isEmpty(type) ? type.charAt(0) : ' ';
+  }
+
+  @NotNull
+  public static SVNStatusType getStatusType(@Nullable String type) {
+    return getStatusType(getStatusChar(type));
+  }
+
+  @NotNull
+  public static SVNStatusType getStatusType(char first) {
+    final SVNStatusType contentsStatus;
+    if ('A' == first) {
+      contentsStatus = SVNStatusType.STATUS_ADDED;
+    } else if ('D' == first) {
+      contentsStatus = SVNStatusType.STATUS_DELETED;
+    } else if ('U' == first) {
+      contentsStatus = SVNStatusType.CHANGED;
+    } else if ('C' == first) {
+      contentsStatus = SVNStatusType.CONFLICTED;
+    } else if ('G' == first) {
+      contentsStatus = SVNStatusType.MERGED;
+    } else if ('R' == first) {
+      contentsStatus = SVNStatusType.STATUS_REPLACED;
+    } else if ('E' == first) {
+      contentsStatus = SVNStatusType.STATUS_OBSTRUCTED;
+    } else {
+      contentsStatus = SVNStatusType.STATUS_NORMAL;
+    }
+    return contentsStatus;
+  }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java
similarity index 95%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java
index 7f3bcf3..d748840 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.commandLine;
 
 import java.io.File;
 
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java
similarity index 96%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java
index 46609e4..87dc212 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.commandLine;
 
 /**
  * Created with IntelliJ IDEA.
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java
similarity index 100%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindClient.java
new file mode 100644
index 0000000..8f14cb2
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindClient.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.jetbrains.idea.svn.commandLine;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.containers.Convertor;
+import org.tmatesoft.svn.core.SVNURL;
+
+import java.util.Map;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/5/13
+ * Time: 3:08 PM
+ */
+public class SvnBindClient {
+  private final String myExecutablePath;
+  private CommitEventHandler myHandler;
+  private AuthenticationCallback myAuthenticationCallback;
+  private Convertor<String[], SVNURL> myUrlProvider;
+
+  public SvnBindClient(String path, Convertor<String[], SVNURL> urlProvider) {
+    myExecutablePath = path;
+    myUrlProvider = urlProvider;
+  }
+
+  public long commit(String[] path, String message, boolean recurse, boolean noUnlock) throws VcsException {
+    return commit(path, message, recurse? 3 : 0, noUnlock, false, null, null);
+  }
+
+  public long commit(String[] path,
+                     String message,
+                     int depth,
+                     boolean noUnlock,
+                     boolean keepChangelist,
+                     String[] changelists,
+                     Map revpropTable) throws VcsException {
+    final long commit = new SvnCommitRunner(myExecutablePath, myHandler, myAuthenticationCallback).
+        commit(path, message, depth, noUnlock, keepChangelist, changelists, revpropTable, myUrlProvider);
+    if (commit < 0) {
+      throw new VcsException("Wrong committed revision number: " + commit);
+    }
+    return commit;
+  }
+
+  public void setHandler(CommitEventHandler handler) {
+    myHandler = handler;
+  }
+
+  public void setAuthenticationCallback(AuthenticationCallback authenticationCallback) {
+    myAuthenticationCallback = authenticationCallback;
+  }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
similarity index 68%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
index 8957843..524b928 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
@@ -13,12 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn.config;
+package org.jetbrains.idea.svn.commandLine;
 
 import com.intellij.openapi.vcs.VcsException;
 
-import java.util.Collection;
-
 /**
  * Created with IntelliJ IDEA.
  * User: Irina.Chernushina
@@ -32,23 +30,7 @@
     super(message);
   }
 
-  public SvnBindException(Throwable throwable, boolean isWarning) {
-    super(throwable, isWarning);
-  }
-
   public SvnBindException(Throwable throwable) {
     super(throwable);
   }
-
-  public SvnBindException(String message, Throwable cause) {
-    super(message, cause);
-  }
-
-  public SvnBindException(String message, boolean isWarning) {
-    super(message, isWarning);
-  }
-
-  public SvnBindException(Collection<String> messages) {
-    super(messages);
-  }
 }
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindUtil.java
similarity index 73%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindUtil.java
index 1fec6b3..7d663ba 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindUtil.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.commandLine;
 
 import java.io.File;
 import java.text.DateFormat;
@@ -31,16 +31,7 @@
  * Time: 4:56 PM
  */
 public class SvnBindUtil {
-  /**
-   * SVN_ASP_DOT_NET_HACK allows use of an alternate name for Subversion working copy
-   * administrative directories on Windows (which were formerly always
-   * named ".svn"), by setting the SVN_ASP_DOT_NET_HACK environment variable.
-   * When the variable is set (to any value), the administrative directory
-   * will be "_svn" instead of ".svn".
-   *
-   * http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt
-   */
-  public static final String ADM_NAME = System.getenv("SVN_ASP_DOT_NET_HACK") != null ? "_svn" : ".svn";
+
   private final static List<DateFormat> ourFormats = new ArrayList<DateFormat>();
 
   static {
@@ -88,17 +79,4 @@
     }
     return null;
   }
-
-  public static File getWcRoot(File base) {
-    File current = base;
-    while (current != null) {
-      if (getWcDbUnder(current).exists()) return current;
-      current = current.getParentFile();
-    }
-    return null;
-  }
-
-  public static File getWcDbUnder(final File file) {
-    return new File(file, ADM_NAME + File.separator + "wc.db");
-  }
 }
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
similarity index 81%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
index d6df6ba..9e355e5 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
@@ -16,6 +16,7 @@
 package org.jetbrains.idea.svn.commandLine;
 
 import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.CapturingProcessAdapter;
 import com.intellij.execution.process.OSProcessHandler;
 import com.intellij.execution.process.ProcessEvent;
 import com.intellij.execution.process.ProcessListener;
@@ -38,6 +39,7 @@
  */
 public abstract class SvnCommand {
   static final Logger LOG = Logger.getInstance(SvnCommand.class.getName());
+  private final File myConfigDir;
 
   private boolean myIsDestroyed;
   private int myExitCode;
@@ -45,13 +47,13 @@
   private final File myWorkingDirectory;
   private Process myProcess;
   private OSProcessHandler myHandler;
+  // TODO: Try to implement commands in a way that they manually indicate if they need full output - to prevent situations
+  // TODO: when large amount of data needs to be stored instead of just sequential processing.
+  private CapturingProcessAdapter outputAdapter;
   private final Object myLock;
 
   private final EventDispatcher<ProcessEventListener> myListeners = EventDispatcher.create(ProcessEventListener.class);
-
-  // todo check version
-  /*c:\Program Files (x86)\CollabNet\Subversion Client17>svn --version --quiet
-  1.7.2*/
+  private final SvnCommandName myCommandName;
 
   public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
     this(workingDirectory, commandName, exePath, null);
@@ -59,15 +61,34 @@
 
   public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath,
                     @Nullable File configDir) {
+    myCommandName = commandName;
     myLock = new Object();
     myCommandLine = new GeneralCommandLine();
     myWorkingDirectory = workingDirectory;
     myCommandLine.setExePath(exePath);
     myCommandLine.setWorkDirectory(workingDirectory);
+    myConfigDir = configDir;
     if (configDir != null) {
       myCommandLine.addParameters("--config-dir", configDir.getPath());
     }
-    myCommandLine.addParameter(commandName.getName());
+    if (!SvnCommandName.empty.equals(commandName)) {
+      myCommandLine.addParameter(commandName.getName());
+    }
+  }
+
+  public String[] getParameters() {
+    synchronized (myLock) {
+      return myCommandLine.getParametersList().getArray();
+    }
+  }
+
+  /**
+   * Indicates if process was destroyed "manually" by command execution logic.
+   *
+   * @return
+   */
+  public boolean isManuallyDestroyed() {
+    return myIsDestroyed;
   }
 
   public void start() {
@@ -112,10 +133,16 @@
       }
     };
 
+    outputAdapter = new CapturingProcessAdapter();
+    myHandler.addProcessListener(outputAdapter);
     myHandler.addProcessListener(processListener);
     myHandler.startNotify();
   }
 
+  public String getOutput() {
+    return outputAdapter.getOutput().getStdout();
+  }
+
   /**
    * Wait for process termination
    * @param timeout
@@ -186,6 +213,18 @@
     }
   }
 
+  public String getCommandText() {
+    synchronized (myLock) {
+      return myCommandLine.getCommandLineString();
+    }
+  }
+
+  public String getExePath() {
+    synchronized (myLock) {
+      return myCommandLine.getExePath();
+    }
+  }
+
   /**
    * check that process is not started yet
    *
@@ -226,4 +265,8 @@
   protected File getWorkingDirectory() {
     return myWorkingDirectory;
   }
+
+  public SvnCommandName getCommandName() {
+    return myCommandName;
+  }
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
index 0d2f4d0..47b6b523 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
@@ -15,12 +15,13 @@
  */
 package org.jetbrains.idea.svn.commandLine;
 
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.CharsetToolkit;
 import com.intellij.util.Consumer;
-import org.jetbrains.idea.svn.SvnBindUtil;
+import org.jetbrains.idea.svn.SvnApplicationSettings;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
 import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient;
@@ -36,7 +37,9 @@
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Created with IntelliJ IDEA.
@@ -45,9 +48,12 @@
  * Time: 12:59 PM
  */
 public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
+
+  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient");
   private final Project myProject;
 
   public SvnCommandLineInfoClient(final Project project) {
+    // TODO: Remove svn kit client instantiation
     super(SvnVcs.getInstance(project).createWCClient());
     myProject = project;
   }
@@ -74,22 +80,56 @@
     base = SvnBindUtil.correctUpToExistingParent(base);
     if (base == null) {
       // very unrealistic
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), new RuntimeException("Can not find existing parent file"));
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not find existing parent file"));
     }
-    final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.info);
+    issueCommand(path.getAbsolutePath(), pegRevision, revision, depth, changeLists, handler, base);
+  }
 
-    if (depth != null) {
-      command.addParameters("--depth", depth.getName());
-    }
-    if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
-      command.addParameters("-r", revision.toString());
-    }
-    command.addParameters("--xml");
+  private void issueCommand(String path, SVNRevision pegRevision,
+                            SVNRevision revision,
+                            SVNDepth depth,
+                            Collection changeLists,
+                            final ISVNInfoHandler handler, File base) throws SVNException {
+    final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.info);
+    List<String> parameters = new ArrayList<String>();
+
+    fillParameters(path, pegRevision, revision, depth, parameters);
+    command.addParameters(parameters);
     SvnCommandLineStatusClient.changelistsToCommand(changeLists, command);
-    if (pegRevision != null && ! SVNRevision.UNDEFINED.equals(pegRevision) && ! SVNRevision.WORKING.equals(pegRevision)) {
-      command.addParameters(path.getPath() + "@" + pegRevision.toString());
-    } else {
-      command.addParameters(path.getPath());
+
+    parseResult(handler, base, execute(command));
+  }
+
+  private String execute(SvnSimpleCommand command) throws SVNException {
+    try {
+      return command.run();
+    }
+    catch (VcsException e) {
+      final String text = e.getMessage();
+      final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text);
+      if (notEmpty && text.contains("W155010")) {
+        // just null
+        return null;
+      }
+      // not a working copy exception
+      // "E155007: '' is not a working copy"
+      if (notEmpty && text.contains("is not a working copy")) {
+        if (StringUtil.isNotEmpty(command.getOutput())) {
+          // workaround: as in subversion 1.8 "svn info" on a working copy root outputs such error for parent folder,
+          // if there are files with conflicts.
+          // but the requested info is still in the output except root closing tag
+          return command.getOutput() + "</info>";
+        } else {
+          throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY, e), e);
+        }
+      }
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
+    }
+  }
+
+  private void parseResult(final ISVNInfoHandler handler, File base, String result) throws SVNException {
+    if (StringUtil.isEmpty(result)) {
+      return;
     }
 
     final SvnInfoHandler[] infoHandler = new SvnInfoHandler[1];
@@ -106,36 +146,32 @@
     });
 
     try {
-      final String result = command.run();
       SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
-      parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), infoHandler[0]);
 
+      parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), infoHandler[0]);
     }
     catch (SvnExceptionWrapper e) {
+      LOG.info("info output " + result);
       throw (SVNException) e.getCause();
     } catch (IOException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      LOG.info("info output " + result);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
     catch (ParserConfigurationException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      LOG.info("info output " + result);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
     catch (SAXException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      LOG.info("info output " + result);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
-    catch (VcsException e) {
-      final String text = e.getMessage();
-      final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text);
-      if (notEmpty && text.contains("W155010")) {
-        // just null
-        return;
-      }
-      // not a working copy exception
-      // "E155007: '' is not a working copy"
-      if (notEmpty && text.contains("is not a working copy")) {
-        throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY), e);
-      }
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
-    }
+  }
+
+  private void fillParameters(String path, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, List<String> parameters) {
+    CommandUtil.put(parameters, depth);
+    CommandUtil.put(parameters, revision);
+    CommandUtil.put(parameters, path, pegRevision);
+    parameters.add("--xml");
   }
 
   @Override
@@ -147,7 +183,14 @@
   @Override
   public void doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, ISVNInfoHandler handler)
     throws SVNException {
-    throw new UnsupportedOperationException();
+    String path = url.toDecodedString();
+    List<String> parameters = new ArrayList<String>();
+
+    fillParameters(path, pegRevision, revision, depth, parameters);
+    File base = new File(SvnApplicationSettings.getInstance().getCommandLinePath());
+    String result = CommandUtil.runSimple(SvnCommandName.info, SvnVcs.getInstance(myProject), base, url, parameters).getOutput();
+
+    parseResult(handler, base, result);
   }
 
   @Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
index a1a3153..c1429be 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
@@ -15,14 +15,16 @@
  */
 package org.jetbrains.idea.svn.commandLine;
 
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Getter;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.CharsetToolkit;
 import com.intellij.util.containers.Convertor;
-import org.jetbrains.idea.svn.SvnBindUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.portable.PortableStatus;
 import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
 import org.jetbrains.idea.svn.portable.SvnStatusClientI;
@@ -48,6 +50,8 @@
  * Time: 5:21 PM
  */
 public class SvnCommandLineStatusClient implements SvnStatusClientI {
+  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient");
+
   private final Project myProject;
   private final SvnCommandLineInfoClient myInfoClient;
 
@@ -102,47 +106,84 @@
     final SVNInfo infoBase = myInfoClient.doInfo(base, revision);
 
     final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.st);
-    putParameters(depth, remote, reportAll, includeIgnored, changeLists, command);
+    putParameters(path, depth, remote, reportAll, includeIgnored, changeLists, command);
 
-    final SvnStatusHandler[] svnHandl = new SvnStatusHandler[1];
-    svnHandl[0] = createStatusHandler(revision, handler, base, infoBase, svnHandl);
+    parseResult(path, revision, handler, base, infoBase, command, execute(command, base));
+    return 0;
+  }
+
+  private String execute(SvnSimpleCommand command, File base) throws SVNException {
+    String result = CommandUtil.runSimple(command, SvnVcs.getInstance(myProject), base, null).getOutput();
+
+    if (StringUtil.isEmptyOrSpaces(result)) {
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL, "Status request returned nothing for command: " +
+                                                                             command.myCommandLine.getCommandLineString()));
+    }
+
+    return result;
+  }
+
+  private void parseResult(final File path,
+                           SVNRevision revision,
+                           ISVNStatusHandler handler,
+                           File base,
+                           SVNInfo infoBase,
+                           SvnSimpleCommand command, String result) throws SVNException {
+
+    if (StringUtil.isEmpty(result)) {
+      return;
+    }
 
     try {
-      final String result = command.run();
-      if (StringUtil.isEmptyOrSpaces(result)) {
-        throw new VcsException("Status request returned nothing for command: " + command.myCommandLine.getCommandLineString());
-      }
+      final SvnStatusHandler[] svnHandl = new SvnStatusHandler[1];
+      svnHandl[0] = createStatusHandler(revision, handler, base, infoBase, svnHandl);
       SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
       parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), svnHandl[0]);
-      if (! svnHandl[0].isAnythingReported()) {
-        if (! SvnUtil.isSvnVersioned(myProject, path)) {
-          throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
+      if (!svnHandl[0].isAnythingReported()) {
+        if (!SvnUtil.isSvnVersioned(myProject, path)) {
+          throw new SVNException(
+            SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY, "Command - " + command.getCommandText() + ". Result - " + result));
+        } else {
+          // return status indicating "NORMAL" state
+          // typical output would be like
+          // <status>
+          // <target path="1.txt"></target>
+          // </status>
+          // so it does not contain any <entry> element and current parsing logic returns null
+
+          PortableStatus status = new PortableStatus();
+          status.setPath(path.getAbsolutePath());
+          status.setContentsStatus(SVNStatusType.STATUS_NORMAL);
+          status.setInfoGetter(new Getter<SVNInfo>() {
+            @Override
+            public SVNInfo get() {
+              return createInfoGetter(null).convert(path);
+            }
+          });
+          handler.handleStatus(status);
         }
       }
     }
     catch (SvnExceptionWrapper e) {
       throw (SVNException) e.getCause();
     } catch (IOException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
     catch (ParserConfigurationException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
     catch (SAXException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
+      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
     }
-    catch (VcsException e) {
-      throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
-    }
-    return 0;
   }
 
-  private void putParameters(SVNDepth depth,
+  private void putParameters(@NotNull File path, SVNDepth depth,
                              boolean remote,
                              boolean reportAll,
                              boolean includeIgnored,
                              Collection changeLists,
                              SvnSimpleCommand command) {
+    command.addParameters(path.getAbsolutePath());
     if (depth != null) {
       command.addParameters("--depth", depth.getName());
     }
@@ -171,7 +212,11 @@
                                                final SVNInfo infoBase, final SvnStatusHandler[] svnHandl) {
     final SvnStatusHandler.ExternalDataCallback callback = createStatusCallback(handler, base, infoBase, svnHandl);
 
-    return new SvnStatusHandler(callback, base, new Convertor<File, SVNInfo>() {
+    return new SvnStatusHandler(callback, base, createInfoGetter(revision));
+  }
+
+  private Convertor<File, SVNInfo> createInfoGetter(final SVNRevision revision) {
+    return new Convertor<File, SVNInfo>() {
       @Override
       public SVNInfo convert(File o) {
         try {
@@ -181,7 +226,7 @@
           throw new SvnExceptionWrapper(e);
         }
       }
-    });
+    };
   }
 
   public static SvnStatusHandler.ExternalDataCallback createStatusCallback(final ISVNStatusHandler handler,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
index c0e9c8e..e0834c2f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
@@ -24,7 +24,6 @@
 import org.jetbrains.idea.svn.SvnApplicationSettings;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
-import org.jetbrains.idea.svn.config.SvnBindException;
 import org.jetbrains.idea.svn.portable.SvnSvnkitUpdateClient;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.wc.*;
@@ -49,9 +48,9 @@
   private final VirtualFile myCommonAncestor;
   private boolean myIgnoreExternals;
 
-  public SvnCommandLineUpdateClient(final Project project, VirtualFile commonAncestor) {
-    super(SvnVcs.getInstance(project).createUpdateClient());
-    myProject = project;
+  public SvnCommandLineUpdateClient(final SvnVcs vcs, VirtualFile commonAncestor) {
+    super(vcs.createUpdateClient());
+    myProject = vcs.getProject();
     myCommonAncestor = commonAncestor;
   }
 
@@ -88,35 +87,7 @@
     File base = myCommonAncestor == null ? paths[0] : new File(myCommonAncestor.getPath());
     base = base.isDirectory() ? base : base.getParentFile();
 
-    final List<String> parameters = new ArrayList<String>();
-    if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
-      parameters.add("-r");
-      parameters.add(revision.toString());
-    }
-    // unknown depth is not used any more for 1.7 -> why?
-    if (depth != null && ! SVNDepth.UNKNOWN.equals(depth)) {
-      parameters.add("--depth");
-      parameters.add(depth.toString());
-    }
-    if (allowUnversionedObstructions) {
-      parameters.add("--force");
-    }
-    if (depthIsSticky && depth != null) {// !!! not sure, but not used
-      parameters.add("--set-depth");
-      parameters.add(depth.toString());
-    }
-    if (makeParents) {
-      parameters.add("--parents");
-    }
-    if (myIgnoreExternals) {
-      parameters.add("--ignore-externals");
-    }
-    parameters.add("--accept");
-    parameters.add("postpone");
-
-    for (File path : paths) {
-      parameters.add(path.getPath());
-    }
+    final List<String> parameters = prepareParameters(paths, revision, depth, allowUnversionedObstructions, depthIsSticky, makeParents);
 
     final AtomicReference<SVNException> excRef = new AtomicReference<SVNException>();
     final ISVNEventHandler handler = getEventHandler();
@@ -166,7 +137,7 @@
         }
       };
       SvnLineCommand.runWithAuthenticationAttempt(SvnApplicationSettings.getInstance().getCommandLinePath(),
-                                                  base, SvnCommandName.up, listener,
+                                                  base, info.getURL(), SvnCommandName.up, listener,
                                                   new IdeaSvnkitBasedAuthenticationCallback(SvnVcs.getInstance(myProject)),
                                                   ArrayUtil.toStringArray(parameters));
     }
@@ -180,6 +151,29 @@
     return updatedToRevision.get();
   }
 
+  private List<String> prepareParameters(File[] paths,
+                                         SVNRevision revision,
+                                         SVNDepth depth,
+                                         boolean allowUnversionedObstructions,
+                                         boolean depthIsSticky, boolean makeParents) {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, revision);
+    CommandUtil.put(parameters, depth);
+    CommandUtil.put(parameters, allowUnversionedObstructions, "--force");
+    if (depthIsSticky && depth != null) {// !!! not sure, but not used
+      parameters.add("--set-depth");
+      parameters.add(depth.toString());
+    }
+    CommandUtil.put(parameters, makeParents, "--parents");
+    CommandUtil.put(parameters, myIgnoreExternals, "--ignore-externals");
+    parameters.add("--accept");
+    parameters.add("postpone");
+    CommandUtil.put(parameters, paths);
+
+    return parameters;
+  }
+
 
   private void checkForException(final StringBuffer sbError) throws SVNException {
     if (sbError.length() == 0) return;
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
similarity index 75%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
index 58c2ff2..c19ea283 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
@@ -22,13 +22,25 @@
  * Time: 1:49 PM
  */
 public enum SvnCommandName {
+  // TODO: temporary command for "more smooth" converting between simple commands and line commands
+  empty("", false),
   version("--version", false),
   info("info", false),
   st("st", false),
   up("up", true),
   ci("commit", true),
-  cleanup("cleanup", true);
-  
+  cleanup("cleanup", true),
+  cat("cat", false),
+  add("add", true),
+  log("log", false),
+  revert("revert", true),
+  delete("delete", true),
+  copy("copy", true),
+  move("move", true),
+  resolve("resolve", true),
+  propget("propget", false),
+  blame("blame", false);
+
   private final String myName;
   private final boolean myWriteable;
 
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
similarity index 85%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
index 525d675..83f6ec1 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
@@ -13,22 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.commandLine;
 
 import com.intellij.execution.process.ProcessOutputTypes;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.Convertor;
 import org.apache.subversion.javahl.types.Revision;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.commandLine.LineCommandListener;
-import org.jetbrains.idea.svn.commandLine.SvnCommandName;
-import org.jetbrains.idea.svn.commandLine.SvnLineCommand;
-import org.jetbrains.idea.svn.config.SvnBindException;
-import org.tigris.subversion.javahl.BindClientException;
-import org.tigris.subversion.javahl.ClientException;
+import org.tmatesoft.svn.core.SVNURL;
 
 import java.io.File;
 import java.util.*;
@@ -42,7 +39,7 @@
 public class SvnCommitRunner {
   private final String myExePath;
   @Nullable private final AuthenticationCallback myAuthenticationCallback;
-  private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnCommitRunner");
+  private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.commandLine.SvnCommitRunner");
   private SvnCommitRunner.CommandListener myCommandListener;
 
   public SvnCommitRunner(@NotNull String path, @Nullable CommitEventHandler handler, @Nullable AuthenticationCallback authenticationCallback) {
@@ -57,7 +54,7 @@
                      boolean noUnlock,
                      boolean keepChangelist,
                      String[] changelists,
-                     Map revpropTable) throws ClientException {
+                     Map revpropTable, Convertor<String[], SVNURL> urlProvider) throws VcsException {
     if (paths.length == 0) return Revision.SVN_INVALID_REVNUM;
 
     final List<String> parameters = new ArrayList<String>();
@@ -84,19 +81,14 @@
     Arrays.sort(paths);
     parameters.addAll(Arrays.asList(paths));
 
-    try {
-      SvnLineCommand.runWithAuthenticationAttempt(myExePath, new File(paths[0]), SvnCommandName.ci,
-                                                  myCommandListener, myAuthenticationCallback, ArrayUtil.toStringArray(parameters));
-    }
-    catch (SvnBindException e) {
-      throw BindClientException.create(e, Revision.SVN_INVALID_REVNUM);
-    }
+    SvnLineCommand.runWithAuthenticationAttempt(myExePath, new File(paths[0]), urlProvider.convert(paths), SvnCommandName.ci,
+                                                myCommandListener, myAuthenticationCallback, ArrayUtil.toStringArray(parameters));
     myCommandListener.throwExceptionIfOccurred();
 
     return myCommandListener.getCommittedRevision();
   }
 
-  private static class CommandListener extends LineCommandListener {
+  public static class CommandListener extends LineCommandListener {
     @Nullable private final CommitEventHandler myHandler;
     private SvnBindException myException;
     private long myCommittedRevision = Revision.SVN_INVALID_REVNUM;
@@ -106,9 +98,9 @@
       myHandler = handler;
     }
 
-    public void throwExceptionIfOccurred() throws BindClientException {
+    public void throwExceptionIfOccurred() throws VcsException {
       if (myException != null) {
-        throw BindClientException.create(myException, Revision.SVN_INVALID_REVNUM);
+        throw myException;
       }
     }
 
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
index 022130e..d8dbb6c1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.util.Getter;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
 import org.tmatesoft.svn.core.SVNDepth;
 import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.SVNNodeKind;
@@ -49,7 +50,7 @@
   public SvnInfoHandler(File base, final Consumer<SVNInfo> infoConsumer) {
     myBase = base;
     myInfoConsumer = infoConsumer;
-    myPending = new SvnInfoStructure();
+    myPending = createPending();
     myElementsMap = new HashMap<String, Getter<ElementHandlerBase>>();
     fillElements();
     myParseStack = new ArrayList<ElementHandlerBase>();
@@ -70,7 +71,14 @@
       myInfoConsumer.consume(info);
     }
     myResultsMap.put(info.getFile(), info);
-    myPending = new SvnInfoStructure();
+    myPending = createPending();
+  }
+
+  private SvnInfoStructure createPending() {
+    SvnInfoStructure pending = new SvnInfoStructure();
+    pending.myDepth = SVNDepth.INFINITY;
+
+    return pending;
   }
 
   @Override
@@ -90,16 +98,13 @@
   public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
     assertSAX(! myParseStack.isEmpty());
     ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
-    if (mySb.length() > 0) {
-      current.characters(mySb.toString().trim(), myPending);
-      mySb.setLength(0);
-    }
 
     while (true) {
       final boolean createNewChild = current.startElement(uri, localName, qName, attributes);
       if (createNewChild) {
         assertSAX(myElementsMap.containsKey(qName));
         final ElementHandlerBase newChild = myElementsMap.get(qName).get();
+        newChild.setParent(current);
         newChild.updateInfo(attributes, myPending);
         myParseStack.add(newChild);
         return;
@@ -116,6 +121,18 @@
   }
 
   @Override
+  public void endElement(String uri, String localName, String qName) throws SAXException {
+    ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
+    String value = mySb.toString().trim();
+
+    if (!StringUtil.isEmpty(value)) {
+      current.characters(value, myPending);
+    }
+
+    mySb.setLength(0);
+  }
+
+  @Override
   public void characters(char[] ch, int start, int length) throws SAXException {
     assertSAX(! myParseStack.isEmpty());
     mySb.append(ch, start, length);
@@ -252,6 +269,24 @@
         return new Url();
       }
     });
+    myElementsMap.put("relative-url", new Getter<ElementHandlerBase>() {
+      @Override
+      public ElementHandlerBase get() {
+        return new RelativeUrl();
+      }
+    });
+    myElementsMap.put("lock", new Getter<ElementHandlerBase>() {
+      @Override
+      public ElementHandlerBase get() {
+        return new Lock();
+      }
+    });
+    myElementsMap.put("created", new Getter<ElementHandlerBase>() {
+      @Override
+      public ElementHandlerBase get() {
+        return new Date();
+      }
+    });
     myElementsMap.put("uuid", new Getter<ElementHandlerBase>() {
       @Override
       public ElementHandlerBase get() {
@@ -270,6 +305,18 @@
         return new WcInfo();
       }
     });
+    myElementsMap.put("moved-to", new Getter<ElementHandlerBase>() {
+      @Override
+      public ElementHandlerBase get() {
+        return new MovedPath();
+      }
+    });
+    myElementsMap.put("moved-from", new Getter<ElementHandlerBase>() {
+      @Override
+      public ElementHandlerBase get() {
+        return new MovedPath();
+      }
+    });
     myElementsMap.put("wcroot-abspath", new Getter<ElementHandlerBase>() {
       @Override
       public ElementHandlerBase get() {
@@ -295,6 +342,12 @@
 
     @Override
     protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
+      // TODO: Currently information for conflict (not tree-conflict) available in svn 1.8 is not used
+      // TODO: And it also not suite well for SVNKit api
+      if (getParent() instanceof Conflict) {
+        return;
+      }
+
       final String side = attributes.getValue("side");
       if ("source-left".equals(side)) {
         final SvnInfoStructure.ConflictVersion conflictVersion = new SvnInfoStructure.ConflictVersion();
@@ -382,7 +435,7 @@
 
     @Override
     public void characters(String s, SvnInfoStructure structure) throws SAXException {
-      structure.myConflictWorking = s;
+      structure.myConflictNew = new File(s).getName();
     }
   }
 
@@ -397,7 +450,7 @@
 
     @Override
     public void characters(String s, SvnInfoStructure structure) throws SAXException {
-      structure.myConflictNew = s;
+      structure.myConflictWorking = new File(s).getName();
     }
   }
 
@@ -412,14 +465,13 @@
 
     @Override
     public void characters(String s, SvnInfoStructure structure) throws SAXException {
-      // todo path? or plus base
-      structure.myConflictOld = s;
+      structure.myConflictOld = new File(s).getName();
     }
   }
 
   private static class Conflict extends ElementHandlerBase {
     private Conflict() {
-      super(new String[]{"prev-base-file","prev-wc-file","cur-base-file","prop-file"}, new String[]{});
+      super(new String[]{"prev-base-file","prev-wc-file","cur-base-file","prop-file"}, new String[]{"version"});
     }
 
     @Override
@@ -498,6 +550,25 @@
     }
   }
 
+  /**
+   * "moved-from" and "moved-to" elements are represented by this class.
+   */
+  private static class MovedPath extends ElementHandlerBase {
+
+    private MovedPath() {
+      super(new String[]{}, new String[]{});
+    }
+
+    @Override
+    protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
+    }
+
+    @Override
+    public void characters(String s, SvnInfoStructure structure) throws SAXException {
+      // TODO: is there some field to initialize from this value?
+    }
+  }
+
   private static class TextUpdated extends ElementHandlerBase {
     private TextUpdated() {
       super(new String[]{}, new String[]{});
@@ -617,7 +688,7 @@
   private static class WcInfo extends ElementHandlerBase {
     private WcInfo() {
       super(new String[]{"wcroot-abspath", "schedule", "depth", "text-updated", "checksum", "changelist", "copy-from-url",
-      "copy-from-rev"}, new String[]{});
+      "copy-from-rev", "moved-to", "moved-from"}, new String[]{});
     }
 
     @Override
@@ -698,11 +769,34 @@
     }
   }
 
+  private static class RelativeUrl extends Url{
+    @Override
+    public void characters(String s, SvnInfoStructure structure) throws SAXException {
+      structure.relativeUrl = s;
+    }
+  }
+
+  private static class Lock extends ElementHandlerBase {
+    private Lock() {
+      super(new String[]{"created"}, new String[]{});
+    }
+
+    @Override
+    protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
+      // TODO:
+    }
+
+    @Override
+    public void characters(String s, SvnInfoStructure structure) throws SAXException {
+      // TODO:
+    }
+  }
+
   private static class Entry extends ElementHandlerBase {
     private final File myBase;
 
     private Entry(final File base) {
-      super(new String[]{"url","repository","wc-info","commit","conflict","tree-conflict"}, new String[]{});
+      super(new String[]{"url", "relative-url", "lock", "repository","wc-info","commit","conflict","tree-conflict"}, new String[]{});
       myBase = base;
     }
 
@@ -763,12 +857,22 @@
   private abstract static class ElementHandlerBase {
     private final Set<String> myAwaitedChildren;
     private final Set<String> myAwaitedChildrenMultiple;
+    private ElementHandlerBase parent;
 
     ElementHandlerBase(String[] awaitedChildren, String[] awaitedChildrenMultiple) {
       myAwaitedChildren = new HashSet<String>(Arrays.asList(awaitedChildren));
       myAwaitedChildrenMultiple = new HashSet<String>(Arrays.asList(awaitedChildrenMultiple));
     }
 
+    @NotNull
+    public ElementHandlerBase getParent() {
+      return parent;
+    }
+
+    public void setParent(@NotNull ElementHandlerBase parent) {
+      this.parent = parent;
+    }
+
     protected abstract void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException;
 
     public boolean startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
index 0292b7d..1aa5248 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
@@ -34,6 +34,7 @@
  */
 public class SvnInfoStructure {
   public File myFile;
+  public String relativeUrl;
   public SVNURL myUrl;
   public SVNURL myRootURL;
   public long myRevision;
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
similarity index 62%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
index 5821d7a..c5e3b9e 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
@@ -23,20 +23,30 @@
 import com.intellij.openapi.vcs.LineHandlerHelper;
 import com.intellij.openapi.vcs.LineProcessEventListener;
 import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.ArrayUtil;
 import com.intellij.util.EventDispatcher;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.AuthenticationCallback;
-import org.jetbrains.idea.svn.SvnBindUtil;
-import org.jetbrains.idea.svn.config.SvnBindException;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
+import org.tmatesoft.svn.core.auth.SVNAuthentication;
+import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication;
+import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Created with IntelliJ IDEA.
@@ -47,11 +57,21 @@
  * honestly stolen from GitLineHandler
  */
 public class SvnLineCommand extends SvnCommand {
+
   public static final String AUTHENTICATION_REALM = "Authentication realm:";
   public static final String CERTIFICATE_ERROR = "Error validating server certificate for";
   public static final String PASSPHRASE_FOR = "Passphrase for";
   public static final String UNABLE_TO_CONNECT = "svn: E170001:";
   public static final String CANNOT_AUTHENTICATE_TO_PROXY = "Could not authenticate to proxy server";
+  public static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed";
+
+  private static final String INVALID_CREDENTIALS_FOR_SVN_PROTOCOL = "svn: E170001: Can't get";
+  private static final String UNTRUSTED_SERVER_CERTIFICATE = "Server SSL certificate untrusted";
+  private static final String ACCESS_TO_PREFIX = "Access to ";
+  private static final String FORBIDDEN_STATUS = "forbidden";
+  private static final String PASSWORD_STRING = "password";
+
+  private static final Pattern UNABLE_TO_CONNECT_TO_URL_PATTERN = Pattern.compile("Unable to connect to a repository at URL '(.*)'");
 
   // kept for exact text
   //public static final String CLIENT_CERTIFICATE_FILENAME = "Client certificate filename:";
@@ -66,6 +86,7 @@
   private final EventDispatcher<LineProcessEventListener> myLineListeners;
   private final AtomicReference<Integer> myExitCode;
   private final StringBuffer myErr;
+  private final StringBuffer myStdOut;
 
   public SvnLineCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
     this(workingDirectory, commandName, exePath, null);
@@ -76,6 +97,7 @@
     myLineListeners = EventDispatcher.create(LineProcessEventListener.class);
     myExitCode = new AtomicReference<Integer>();
     myErr = new StringBuffer();
+    myStdOut = new StringBuffer();
   }
 
   @Override
@@ -89,13 +111,14 @@
     }
   }
 
-  public static void runWithAuthenticationAttempt(final String exePath,
-                                                  final File firstFile,
-                                                  SvnCommandName commandName,
-                                                  final LineCommandListener listener,
-                                                  @Nullable AuthenticationCallback authenticationCallback,
-                                                  final String... parameters) throws SvnBindException {
-    File base = firstFile.isDirectory() ? firstFile : firstFile.getParentFile();
+  public static SvnLineCommand runWithAuthenticationAttempt(final String exePath,
+                                                            final File firstFile,
+                                                            final SVNURL url,
+                                                            SvnCommandName commandName,
+                                                            final LineCommandListener listener,
+                                                            @Nullable AuthenticationCallback authenticationCallback,
+                                                            String... parameters) throws SvnBindException {
+    File base = firstFile != null ? (firstFile.isDirectory() ? firstFile : firstFile.getParentFile()) : null;
     base = SvnBindUtil.correctUpToExistingParent(base);
 
     listener.baseDirectory(base);
@@ -111,27 +134,35 @@
 
       while (true) {
         final SvnLineCommand command = runCommand(exePath, commandName, listener, base, configDir, parameters);
-        if (command.myErr.length() > 0) {
-          final String errText = command.myErr.toString().trim();
-          if (authenticationCallback != null) {
-            final AuthCallbackCase callback = createCallback(errText, authenticationCallback, base);
-            if (callback != null) {
-              cleanup(exePath, commandName, base);
-              if (callback.getCredentials(errText)) {
-                if (authenticationCallback.getSpecialConfigDir() != null) {
-                  configDir = authenticationCallback.getSpecialConfigDir();
+        final Integer exitCode = command.myExitCode.get();
+
+        // could be situations when exit code = 0, but there is info "warning" in error stream
+        // for instance, for "svn status" on non-working copy folder
+        if (exitCode != 0) {
+          if (command.myErr.length() > 0) {
+            // handle authentication
+            final String errText = command.myErr.toString().trim();
+            if (authenticationCallback != null) {
+              final AuthCallbackCase callback = createCallback(errText, authenticationCallback, base, url);
+              if (callback != null) {
+                cleanup(exePath, command, base);
+                if (callback.getCredentials(errText)) {
+                  if (authenticationCallback.getSpecialConfigDir() != null) {
+                    configDir = authenticationCallback.getSpecialConfigDir();
+                  }
+                  parameters = updateParameters(callback, parameters);
+                  continue;
                 }
-                continue;
               }
             }
+            throw new SvnBindException(errText);
+          } else {
+            throw new SvnBindException("Svn process exited with error code: " + exitCode);
           }
-          throw new SvnBindException(errText);
+        } else if (command.myErr.length() > 0) {
+          LOG.info("Detected warning - " + command.myErr);
         }
-        final Integer exitCode = command.myExitCode.get();
-        if (exitCode != 0) {
-          throw new SvnBindException("Svn process exited with error code: " + exitCode);
-        }
-        return;
+        return command;
       }
     } finally {
       if (authenticationCallback != null) {
@@ -140,6 +171,13 @@
     }
   }
 
+  private static String[] updateParameters(AuthCallbackCase callback, String[] parameters) {
+    List<String> p = new ArrayList<String>(Arrays.asList(parameters));
+
+    callback.updateParameters(p);
+    return ArrayUtil.toStringArray(p);
+  }
+
   private static void writeIdeaConfig2SubversionConfig(@NotNull AuthenticationCallback authenticationCallback, @NotNull File base) throws SvnBindException {
     if (authenticationCallback.haveDataForTmpConfig()) {
       try {
@@ -158,7 +196,7 @@
     }
   }
 
-  private static AuthCallbackCase createCallback(final String errText, final AuthenticationCallback callback, final File base) {
+  private static AuthCallbackCase createCallback(final String errText, final AuthenticationCallback callback, final File base, final SVNURL url) {
     if (errText.startsWith(CERTIFICATE_ERROR)) {
       return new CertificateCallbackCase(callback, base);
     }
@@ -171,9 +209,85 @@
     if (errText.startsWith(UNABLE_TO_CONNECT) && errText.contains(CANNOT_AUTHENTICATE_TO_PROXY)) {
       return new ProxyCallback(callback, base);
     }
+    // http/https protocol invalid credentials
+    if (errText.contains(AUTHENTICATION_FAILED_MESSAGE)) {
+      return new UsernamePasswordCallback(callback, base, url);
+    }
+    // messages could be "Can't get password", "Can't get username or password"
+    if (errText.contains(INVALID_CREDENTIALS_FOR_SVN_PROTOCOL) && errText.contains(PASSWORD_STRING)) {
+      // svn protocol invalid credentials
+      return new UsernamePasswordCallback(callback, base, url);
+    }
+    // https one-way protocol untrusted server certificate
+    if (errText.contains(UNTRUSTED_SERVER_CERTIFICATE)) {
+      return new CertificateCallbackCase(callback, base);
+    }
+    // https two-way protocol invalid client certificate
+    if (errText.contains(ACCESS_TO_PREFIX) && errText.contains(FORBIDDEN_STATUS)) {
+      return new TwoWaySslCallback(callback, base, url);
+    }
     return null;
   }
 
+  // Special callback for svn 1.8 credentials request as --non-interactive does not return
+  // authentication realm (just url) - so we could not create temp cache
+  private static class UsernamePasswordCallback extends AuthCallbackCase {
+    protected SVNAuthentication myAuthentication;
+    protected SVNURL myUrl;
+
+    protected UsernamePasswordCallback(AuthenticationCallback callback, File base, SVNURL url) {
+      super(callback, base);
+      myUrl = url;
+    }
+
+    @Override
+    boolean getCredentials(String errText) throws SvnBindException {
+      myAuthentication = myAuthenticationCallback.requestCredentials(myUrl != null ? myUrl : parseUrlFromError(errText),
+                                                                     getType());
+
+      return myAuthentication != null;
+    }
+
+    public String getType() {
+      return ISVNAuthenticationManager.PASSWORD;
+    }
+
+    @Override
+    public void updateParameters(List<String> parameters) {
+      if (myAuthentication instanceof SVNPasswordAuthentication) {
+        SVNPasswordAuthentication auth = (SVNPasswordAuthentication)myAuthentication;
+
+        parameters.add("--username");
+        parameters.add(auth.getUserName());
+        parameters.add("--password");
+        parameters.add(auth.getPassword());
+        if (!auth.isStorageAllowed()) {
+          parameters.add("--no-auth-cache");
+        }
+      }
+    }
+
+    private SVNURL parseUrlFromError(String errorText) {
+      Matcher matcher = UNABLE_TO_CONNECT_TO_URL_PATTERN.matcher(errorText);
+      String urlValue = null;
+
+      if (matcher.find()) {
+        urlValue = matcher.group(1);
+      }
+
+      return urlValue != null ? parseUrl(urlValue) : null;
+    }
+
+    private SVNURL parseUrl(String urlValue) {
+      try {
+        return SVNURL.parseURIEncoded(urlValue);
+      }
+      catch (SVNException e) {
+        return null;
+      }
+    }
+  }
+
   private static class ProxyCallback extends AuthCallbackCase {
     protected ProxyCallback(AuthenticationCallback callback, File base) {
       super(callback, base);
@@ -192,7 +306,8 @@
 
     @Override
     boolean getCredentials(String errText) throws SvnBindException {
-      final String realm = cutFirstLine(errText).substring(AUTHENTICATION_REALM.length()).trim();
+      final String realm =
+        errText.startsWith(AUTHENTICATION_REALM) ? cutFirstLine(errText).substring(AUTHENTICATION_REALM.length()).trim() : null;
       final boolean isPassword = StringUtil.containsIgnoreCase(errText, "password");
       if (myTried) {
         myAuthenticationCallback.clearPassiveCredentials(realm, myBase, isPassword);
@@ -212,13 +327,16 @@
   }
 
   private static class CertificateCallbackCase extends AuthCallbackCase {
+    private boolean accepted;
+
     private CertificateCallbackCase(AuthenticationCallback callback, File base) {
       super(callback, base);
     }
 
     @Override
     public boolean getCredentials(final String errText) throws SvnBindException {
-      String realm = cutFirstLine(errText).substring(CERTIFICATE_ERROR.length());
+      // parse realm from error text
+      String realm = errText;
       final int idx1 = realm.indexOf('\'');
       if (idx1 == -1) {
         throw new SvnBindException("Can not detect authentication realm name: " + errText);
@@ -229,11 +347,48 @@
       }
       realm = realm.substring(idx1 + 1, idx2);
       if (! myTried && myAuthenticationCallback.acceptSSLServerCertificate(myBase, realm)) {
+        accepted = true;
         myTried = true;
         return true;
       }
       throw new SvnBindException("Server SSL certificate rejected");
     }
+
+    @Override
+    public void updateParameters(List<String> parameters) {
+      if (accepted) {
+        parameters.add("--trust-server-cert");
+      }
+    }
+  }
+
+  private static class TwoWaySslCallback extends UsernamePasswordCallback {
+
+    protected TwoWaySslCallback(AuthenticationCallback callback, File base, SVNURL url) {
+      super(callback, base, url);
+    }
+
+    @Override
+    public String getType() {
+      return ISVNAuthenticationManager.SSL;
+    }
+
+    @Override
+    public void updateParameters(List<String> parameters) {
+      if (myAuthentication instanceof SVNSSLAuthentication) {
+        SVNSSLAuthentication auth = (SVNSSLAuthentication)myAuthentication;
+
+        // TODO: Seems that config option should be specified for concrete server and not for global group.
+        // as in that case it could be overriden by settings in config file
+        parameters.add("--config-option");
+        parameters.add("servers:global:ssl-client-cert-file=" + auth.getCertificatePath());
+        parameters.add("--config-option");
+        parameters.add("servers:global:ssl-client-cert-password=" + auth.getPassword());
+        if (!auth.isStorageAllowed()) {
+          parameters.add("--no-auth-cache");
+        }
+      }
+    }
   }
 
   private static abstract class AuthCallbackCase {
@@ -247,17 +402,23 @@
     }
 
     abstract boolean getCredentials(final String errText) throws SvnBindException;
+
+    public void updateParameters(List<String> parameters) {
+    }
   }
 
-  private static void cleanup(String exePath, SvnCommandName commandName, File base) throws SvnBindException {
-    File wcRoot = SvnBindUtil.getWcRoot(base);
-    if (wcRoot == null) throw new SvnBindException("Can not find working copy root for: " + base.getPath());
+  private static void cleanup(String exePath, SvnCommand command, File base) throws SvnBindException {
+    // TODO: could be issues with fake "empty" command as it is not writable - but only read commands currently use "empty" command
+    // TODO: and "empty" command will be removed shortly
+    if (command.isManuallyDestroyed() && command.getCommandName().isWriteable()) {
+      File wcRoot = SvnUtil.getWorkingCopyRootNew(base);
+      if (wcRoot == null) {
+        throw new SvnBindException("Can not find working copy root for: " + base.getPath());
+      }
 
-    //cleanup -> check command type
-    if (commandName.isWriteable()) {
-      final SvnSimpleCommand command = new SvnSimpleCommand(wcRoot, SvnCommandName.cleanup, exePath);
+      final SvnSimpleCommand cleanupCommand = new SvnSimpleCommand(wcRoot, SvnCommandName.cleanup, exePath);
       try {
-        command.run();
+        cleanupCommand.run();
       }
       catch (VcsException e) {
         throw new SvnBindException(e);
@@ -320,6 +481,10 @@
     command.addLineListener(new LineProcessEventListener() {
       @Override
       public void onLineAvailable(String line, Key outputType) {
+        if (ProcessOutputTypes.STDOUT.equals(outputType)) {
+          command.myStdOut.append(line);
+        }
+
         if (SvnCommand.LOG.isDebugEnabled()) {
           SvnCommand.LOG.debug("==> " + line);
         }
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
similarity index 96%
rename from plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
index 75c43be..a088da0 100644
--- a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
@@ -94,7 +94,11 @@
       if (myException != null) throw myException;
       final int code = getExitCode();
       if (code == 0) {
-        return myStdout.toString();
+        String result = myStdout.toString();
+
+        LOG.debug(result);
+
+        return result;
       } else {
         final String msg = new StringBuilder("Svn process exited with error code: ").append(code).append("\n")
           .append("stderr: ").append(myStderr.toString()).append("\nstdout: ").append(getStdout().toString())
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
index 6536646..8700c36 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
@@ -62,6 +62,8 @@
   }
 
   public SVNEvent convert(final String line) {
+    // TODO: Add direct processing of "Summary of conflicts" lines at the end of "svn update" output (if there are conflicts).
+    // TODO: Now it works ok because parseNormalLine could not determine necessary statuses from that and further lines
     if (StringUtil.isEmptyOrSpaces(line)) return null;
 
     if (line.startsWith(UPDATING)) {
@@ -103,9 +105,9 @@
     if (line.length() < 5) return null;
     final char first = line.charAt(0);
     if (' ' != first && ! ourActions.contains(first)) return null;
-    final SVNStatusType contentsStatus = getStatusType(first);
+    final SVNStatusType contentsStatus = CommandUtil.getStatusType(first);
     final char second = line.charAt(1);
-    final SVNStatusType propertiesStatus = getStatusType(second);
+    final SVNStatusType propertiesStatus = CommandUtil.getStatusType(second);
     final char lock = line.charAt(2); // dont know what to do with stolen lock info
     if (' ' != lock && 'B' != lock) return null;
     final char treeConflict = line.charAt(3);
@@ -140,28 +142,6 @@
                         null, action, expectedAction, null, null, null, null, null);
   }
 
-  private SVNStatusType getStatusType(char first) {
-    final SVNStatusType contentsStatus;
-    if ('A' == first) {
-      contentsStatus = SVNStatusType.STATUS_ADDED;
-    } else if ('D' == first) {
-      contentsStatus = SVNStatusType.STATUS_DELETED;
-    } else if ('U' == first) {
-      contentsStatus = SVNStatusType.CHANGED;
-    } else if ('C' == first) {
-      contentsStatus = SVNStatusType.CONFLICTED;
-    } else if ('G' == first) {
-      contentsStatus = SVNStatusType.MERGED;
-    } else if ('R' == first) {
-      contentsStatus = SVNStatusType.STATUS_REPLACED;
-    } else if ('E' == first) {
-      contentsStatus = SVNStatusType.STATUS_OBSTRUCTED;
-    } else {
-      contentsStatus = SVNStatusType.STATUS_NORMAL;
-    }
-    return contentsStatus;
-  }
-
   @Nullable
   private long matchAndGetRevision(final Pattern pattern, final String line) {
     final Matcher matcher = pattern.matcher(line);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java
new file mode 100644
index 0000000..79614a2
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java
@@ -0,0 +1,33 @@
+package org.jetbrains.idea.svn.conflict;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.SVNDepth;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdConflictClient extends BaseSvnClient implements ConflictClient {
+
+  // TODO: Add possibility to resolve content conflicts separately from property conflicts.
+  @Override
+  public void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, path);
+    CommandUtil.put(parameters, SVNDepth.EMPTY);
+    parameters.add("--accept");
+    parameters.add("working");
+
+    // for now parsing of the output is not required as command is executed only for one file
+    // and will be either successful or exception will be thrown
+    CommandUtil.execute(myVcs, SvnCommandName.resolve, parameters, null);
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/ConflictClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/ConflictClient.java
new file mode 100644
index 0000000..812fdef
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/ConflictClient.java
@@ -0,0 +1,15 @@
+package org.jetbrains.idea.svn.conflict;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.SvnClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface ConflictClient extends SvnClient {
+
+  void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/SvnKitConflictClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/SvnKitConflictClient.java
new file mode 100644
index 0000000..33ee0f8
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/SvnKitConflictClient.java
@@ -0,0 +1,25 @@
+package org.jetbrains.idea.svn.conflict;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNConflictChoice;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitConflictClient extends BaseSvnClient implements ConflictClient {
+  @Override
+  public void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException {
+    try {
+      myVcs.createWCClient().doResolve(path, SVNDepth.EMPTY, true, resolvePropertyConflicts, SVNConflictChoice.MERGED);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java
new file mode 100644
index 0000000..c822fe0
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java
@@ -0,0 +1,39 @@
+package org.jetbrains.idea.svn.content;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdContentClient extends BaseSvnClient implements ContentClient {
+
+  @Override
+  public byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
+    throws VcsException, FileTooBigRuntimeException {
+    // TODO: rewrite this to provide output as Stream
+    // TODO: rewrite without conversion from String to byte[]
+    // TODO: Also implement max size constraint like in SvnKitContentClient
+    List<String> parameters = new ArrayList<String>();
+    CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
+    CommandUtil.put(parameters, revision);
+
+    SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.cat, parameters, null);
+
+    byte[] bytes = CharsetToolkit.getUtf8Bytes(command.getOutput());
+
+    ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), bytes.length);
+
+    return bytes;
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/ContentClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/ContentClient.java
new file mode 100644
index 0000000..3654d09
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/ContentClient.java
@@ -0,0 +1,17 @@
+package org.jetbrains.idea.svn.content;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface ContentClient extends SvnClient {
+
+  byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
+    throws VcsException, FileTooBigRuntimeException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/FileTooBigRuntimeException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/FileTooBigRuntimeException.java
new file mode 100644
index 0000000..0a0e585
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/FileTooBigRuntimeException.java
@@ -0,0 +1,7 @@
+package org.jetbrains.idea.svn.content;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class FileTooBigRuntimeException extends RuntimeException {
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/SvnKitContentClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/SvnKitContentClient.java
new file mode 100644
index 0000000..d591697
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/SvnKitContentClient.java
@@ -0,0 +1,61 @@
+package org.jetbrains.idea.svn.content;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.vcsUtil.VcsUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc.SVNWCClient;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitContentClient extends BaseSvnClient implements ContentClient {
+
+  @Override
+  public byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
+    throws VcsException, FileTooBigRuntimeException {
+    final int maxSize = VcsUtil.getMaxVcsLoadedFileSize();
+    ByteArrayOutputStream buffer = new ByteArrayOutputStream() {
+      @Override
+      public synchronized void write(int b) {
+        if (size() > maxSize) throw new FileTooBigRuntimeException();
+        super.write(b);
+      }
+
+      @Override
+      public synchronized void write(byte[] b, int off, int len) {
+        if (size() > maxSize) throw new FileTooBigRuntimeException();
+        super.write(b, off, len);
+      }
+
+      @Override
+      public synchronized void writeTo(OutputStream out) throws IOException {
+        if (size() > maxSize) throw new FileTooBigRuntimeException();
+        super.writeTo(out);
+      }
+    };
+    SVNWCClient wcClient = myVcs.createWCClient();
+    try {
+      if (target.isURL()) {
+        wcClient.doGetFileContents(target.getURL(), pegRevision, revision, true, buffer);
+      } else {
+        wcClient.doGetFileContents(target.getFile(), pegRevision, revision, true, buffer);
+      }
+      ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), buffer.size());
+    } catch (FileTooBigRuntimeException e) {
+      ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), buffer.size());
+    } catch (SVNException e) {
+      throw new VcsException(e);
+    }
+    return buffer.toByteArray();
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java
new file mode 100644
index 0000000..eceef14
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java
@@ -0,0 +1,30 @@
+package org.jetbrains.idea.svn.copy;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient {
+
+  @Override
+  public void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, src);
+    CommandUtil.put(parameters, dst);
+    CommandUtil.put(parameters, makeParents, "--parents");
+
+    // for now parsing of the output is not required as command is executed only for one file
+    // and will be either successful or exception will be thrown
+    CommandUtil.execute(myVcs, isMove ? SvnCommandName.move : SvnCommandName.copy, parameters, null);
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java
new file mode 100644
index 0000000..ec48107
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java
@@ -0,0 +1,15 @@
+package org.jetbrains.idea.svn.copy;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.SvnClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface CopyMoveClient extends SvnClient {
+
+  void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java
new file mode 100644
index 0000000..ea84bc6
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java
@@ -0,0 +1,28 @@
+package org.jetbrains.idea.svn.copy;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNCopySource;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitCopyMoveClient extends BaseSvnClient implements CopyMoveClient {
+
+  @Override
+  public void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException {
+    final SVNCopySource copySource = new SVNCopySource(isMove ? SVNRevision.UNDEFINED : SVNRevision.WORKING, SVNRevision.WORKING, src);
+
+    try {
+      myVcs.createCopyClient().doCopy(new SVNCopySource[]{copySource}, dst, isMove, makeParents, true);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java
new file mode 100644
index 0000000..5fc26ac
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java
@@ -0,0 +1,29 @@
+package org.jetbrains.idea.svn.delete;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdDeleteClient extends BaseSvnClient implements DeleteClient {
+
+  @Override
+  public void delete(@NotNull File path, boolean force) throws VcsException {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, path);
+    CommandUtil.put(parameters, force, "--force");
+
+    // for now parsing of the output is not required as command is executed only for one file
+    // and will be either successful or exception will be thrown
+    CommandUtil.execute(myVcs, SvnCommandName.delete, parameters, null);
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java
new file mode 100644
index 0000000..23a1cf9
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java
@@ -0,0 +1,15 @@
+package org.jetbrains.idea.svn.delete;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.SvnClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface DeleteClient extends SvnClient {
+
+  void delete(@NotNull File path, boolean force) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java
new file mode 100644
index 0000000..c97cfd2
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java
@@ -0,0 +1,24 @@
+package org.jetbrains.idea.svn.delete;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNException;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitDeleteClient extends BaseSvnClient implements DeleteClient {
+
+  @Override
+  public void delete(@NotNull File path, boolean force) throws VcsException {
+    try {
+      myVcs.createWCClient().doDelete(path, force, false);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java
index 62fc918..e1ad915 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java
@@ -263,17 +263,11 @@
     super.init();
     SvnVcs vcs = SvnVcs.getInstance(myProject);
     String revStr = "";
-    try {
-      SVNWCClient client = vcs.createWCClient();
-      SVNInfo info = client.doInfo(mySrcFile, SVNRevision.UNDEFINED);
-      if (info != null) {
-        mySrcURL = info.getURL() == null ? null : info.getURL().toString();
-        revStr = String.valueOf(info.getRevision());
-        myURL = mySrcURL;
-      }
-    }
-    catch (SVNException e) {
-      //
+    SVNInfo info = vcs.getInfo(mySrcFile);
+    if (info != null) {
+      mySrcURL = info.getURL() == null ? null : info.getURL().toString();
+      revStr = String.valueOf(info.getRevision());
+      myURL = mySrcURL;
     }
     if (myURL == null) {
       return;
@@ -354,15 +348,8 @@
         return true;
       }
       else if (myWorkingCopyRadioButton.isSelected()) {
-        String srcUrl;
-        try {
-          SVNWCClient client = SvnVcs.getInstance(myProject).createWCClient();
-          SVNInfo info = client.doInfo(mySrcFile, SVNRevision.UNDEFINED);
-          srcUrl = info != null && info.getURL() != null ? info.getURL().toString() : null;
-        }
-        catch (SVNException e) {
-          srcUrl = null;
-        }
+        SVNInfo info = SvnVcs.getInstance(myProject).getInfo(mySrcFile);
+        String srcUrl = info != null && info.getURL() != null ? info.getURL().toString() : null;
         if (srcUrl == null) {
           myErrorLabel.setText(SvnBundle.message("create.branch.no.working.copy.error", myWorkingCopyField.getText()));
           return false;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java
new file mode 100644
index 0000000..3948dde
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java
@@ -0,0 +1,223 @@
+package org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.LineSeparator;
+import com.intellij.util.containers.hash.HashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.jetbrains.idea.svn.commandLine.SvnLineCommand;
+import org.tmatesoft.svn.core.ISVNLogEntryHandler;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNLogEntry;
+import org.tmatesoft.svn.core.SVNLogEntryPath;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdHistoryClient extends BaseSvnClient implements HistoryClient {
+
+  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.CmdHistoryClient");
+
+  @Override
+  public void doLog(@NotNull File path,
+                    @NotNull SVNRevision startRevision,
+                    @NotNull SVNRevision endRevision,
+                    @Nullable SVNRevision pegRevision,
+                    boolean stopOnCopy,
+                    boolean discoverChangedPaths,
+                    boolean includeMergedRevisions,
+                    long limit,
+                    @Nullable String[] revisionProperties,
+                    @Nullable ISVNLogEntryHandler handler) throws VcsException {
+    // TODO: add revision properties parameter if necessary
+    // TODO: svn log command supports --xml option - could update parsing to use xml format
+
+    // TODO: after merge remove setting includeMergedRevisions to false and update parsing
+    includeMergedRevisions = false;
+
+    List<String> parameters =
+      prepareCommand(path, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions, limit);
+
+    try {
+      SvnLineCommand command = CommandUtil.runSimple(SvnCommandName.log, myVcs, path, null, parameters);
+      // TODO: handler should be called in parallel with command execution, but this will be in other thread
+      // TODO: check if that is ok for current handler implementation
+      parseOutput(handler, command);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+
+  private static void parseOutput(@Nullable ISVNLogEntryHandler handler, @NotNull SvnLineCommand command)
+    throws VcsException, SVNException {
+    Parser parser = new Parser(handler);
+    for (String line : StringUtil.splitByLines(command.getOutput(), false)) {
+      parser.onLine(line);
+    }
+  }
+
+  private static List<String> prepareCommand(@NotNull File path,
+                                             @NotNull SVNRevision startRevision,
+                                             @NotNull SVNRevision endRevision,
+                                             @Nullable SVNRevision pegRevision,
+                                             boolean stopOnCopy, boolean discoverChangedPaths, boolean includeMergedRevisions, long limit) {
+    List<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, path, pegRevision);
+    parameters.add("--revision");
+    parameters.add(startRevision + ":" + endRevision);
+
+    CommandUtil.put(parameters, stopOnCopy, "--stop-on-copy");
+    CommandUtil.put(parameters, discoverChangedPaths, "--verbose");
+    CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
+    if (limit > 0) {
+      parameters.add("--limit");
+      parameters.add(String.valueOf(limit));
+    }
+
+    return parameters;
+  }
+
+  private static class Parser {
+    private static final String REVISION = "\\s*r(\\d+)\\s*";
+    private static final String AUTHOR = "\\s*([^|]*)\\s*";
+    private static final String DATE = "\\s*([^|]*)\\s*";
+    private static final String MESSAGE_LINES = "\\s*(\\d+).*";
+
+    private static final Pattern ENTRY_START = Pattern.compile("-+");
+    private static final Pattern DETAILS = Pattern.compile(REVISION + "\\|" + AUTHOR + "\\|" + DATE + "\\|" + MESSAGE_LINES);
+
+    private static final String STATUS = "\\s*(\\w)";
+    private static final String PATH = "\\s*(.*?)\\s*";
+    private static final String COPY_FROM_PATH = "(/[^:]*)";
+    private static final String COPY_FROM_REVISION = "(\\d+)\\))\\s*";
+    private static final String COPY_FROM_INFO = "((\\(from " + COPY_FROM_PATH + ":" + COPY_FROM_REVISION + ")?";
+    private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + PATH + COPY_FROM_INFO);
+
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
+
+    ISVNLogEntryHandler handler;
+
+    Entry entry;
+    boolean waitDetails;
+    boolean waitChangedPath;
+    boolean waitMessage;
+
+    public Parser(@Nullable ISVNLogEntryHandler handler) {
+      this.handler = handler;
+    }
+
+    public void onLine(@NotNull String line) throws VcsException, SVNException {
+      if (ENTRY_START.matcher(line).matches()) {
+        processEntryStart();
+      }
+      else if (waitDetails) {
+        processDetails(line);
+      }
+      else if (waitMessage) {
+        processMessage(line);
+      }
+      else if (StringUtil.isEmpty(line.trim())) {
+        processChangedPathsFinished();
+      }
+      else if (line.startsWith("Changed paths:")) {
+        processChangedPathsStarted();
+      }
+      else if (waitChangedPath) {
+        processChangedPath(line);
+      }
+      else {
+        throw new VcsException("unknown state on line " + line);
+      }
+    }
+
+    private void processChangedPath(@NotNull String line) throws VcsException {
+      Matcher matcher = CHANGED_PATH.matcher(line);
+      if (!matcher.matches()) {
+        throw new VcsException("changed path not found in " + line);
+      }
+
+      String path = matcher.group(2);
+      char type = CommandUtil.getStatusChar(matcher.group(1));
+      String copyPath = matcher.group(5);
+      long copyRevision = !StringUtil.isEmpty(matcher.group(6)) ? Long.valueOf(matcher.group(6)) : 0;
+
+      entry.changedPaths.put(path, new SVNLogEntryPath(path, type, copyPath, copyRevision));
+    }
+
+    private void processChangedPathsStarted() {
+      waitChangedPath = true;
+    }
+
+    private void processChangedPathsFinished() {
+      waitChangedPath = false;
+      waitMessage = true;
+    }
+
+    private void processMessage(@NotNull String line) {
+      entry.message.append(line);
+      entry.message.append(LineSeparator.LF.getSeparatorString());
+    }
+
+    private void processDetails(@NotNull String line) throws VcsException {
+      Matcher matcher = DETAILS.matcher(line);
+      if (!matcher.matches()) {
+        throw new VcsException("details not found in " + line);
+      }
+      entry.revision = Long.valueOf(matcher.group(1));
+      entry.author = matcher.group(2).trim();
+      entry.date = tryGetDate(matcher.group(3));
+
+      waitDetails = false;
+    }
+
+    private void processEntryStart() throws SVNException {
+      if (entry != null) {
+        handler.handleLogEntry(entry.toLogEntry());
+      }
+      entry = new Entry();
+      waitDetails = true;
+      waitMessage = false;
+    }
+
+    private static Date tryGetDate(@NotNull String value) {
+      Date result = null;
+      try {
+        result = DATE_FORMAT.parse(value);
+      }
+      catch (ParseException e) {
+        LOG.debug(e);
+      }
+      return result;
+    }
+
+    private static class Entry {
+      Map<String, SVNLogEntryPath> changedPaths = new HashMap<String, SVNLogEntryPath>();
+      long revision;
+      String author;
+      Date date;
+      StringBuilder message = new StringBuilder();
+
+      private SVNLogEntry toLogEntry() {
+        return new SVNLogEntry(changedPaths, revision, author, date, message.toString());
+      }
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java
new file mode 100644
index 0000000..87e5e76
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java
@@ -0,0 +1,28 @@
+package org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.ISVNLogEntryHandler;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface HistoryClient extends SvnClient {
+
+  // TODO: Url is also supported as parameter in cmd - use Target class
+  void doLog(@NotNull File path,
+             @NotNull SVNRevision startRevision,
+             @NotNull SVNRevision endRevision,
+             @Nullable SVNRevision pegRevision,
+             boolean stopOnCopy,
+             boolean discoverChangedPaths,
+             boolean includeMergedRevisions,
+             long limit,
+             @Nullable String[] revisionProperties,
+             @Nullable ISVNLogEntryHandler handler) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
index 7ef0b2f..3552853 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
@@ -518,9 +518,8 @@
       revisionBefore = SVNRevision.create(revision);
 
       svnurl = SVNURL.parseURIEncoded(url);
-      final SVNWCClient client = myVcs.createWCClient();
-      final SVNInfo info = client.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
-      targetInfo = client.doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
+      final SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
+      targetInfo = myVcs.getInfo(new File(file.getPath()));
       if (info == null) {
         throw new VcsException("Can not get repository URL");
       }
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 5ca1150..d67e29b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
@@ -137,7 +137,7 @@
       final String url = myLocation.getURL();
       final SVNURL root;
       try {
-        root = SvnUtil.getRepositoryRoot(myVcs, SVNURL.parseURIEncoded(url), true);
+        root = SvnUtil.getRepositoryRoot(myVcs, SVNURL.parseURIEncoded(url));
         if (root == null) {
           myException = new VcsException("Can not determine repository root for URL: " + url);
           return;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
index bcb40a0..046e16c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
@@ -33,6 +33,7 @@
 import org.jetbrains.idea.svn.SvnVcs;
 import org.tmatesoft.svn.core.SVNLogEntry;
 import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -211,7 +212,7 @@
       }
 
       try {
-        myContents = SvnUtil.getFileContents(myVCS, myURL, true, myRevision, myPegRevision);
+        myContents = SvnUtil.getFileContents(myVCS, SvnTarget.fromURL(SvnUtil.parseUrl(myURL)), myRevision, myPegRevision);
       }
       catch (VcsException e) {
         myException = 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 4a2c872..860b646 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -42,7 +42,6 @@
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
 import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
-import org.tmatesoft.svn.core.io.SVNRepository;
 import org.tmatesoft.svn.core.wc.*;
 import org.tmatesoft.svn.util.SVNLogType;
 
@@ -50,7 +49,6 @@
 import javax.swing.table.TableCellRenderer;
 import java.awt.*;
 import java.awt.event.MouseEvent;
-import java.io.File;
 import java.nio.charset.Charset;
 import java.util.Collections;
 import java.util.Date;
@@ -285,18 +283,9 @@
 
     @Override
     protected void preliminary() throws SVNException {
-      SVNWCClient wcClient = myVcs.createWCClient();
-      myInfo = wcClient.doInfo(new File(myFile.getIOFile().getAbsolutePath()), SVNRevision.UNDEFINED);
-      wcClient.setEventHandler(new ISVNEventHandler() {
-        public void handleEvent(SVNEvent event, double progress) throws SVNException {
-        }
-
-        public void checkCancelled() throws SVNCancelException {
-          myPI.checkCanceled();
-        }
-      });
+      myInfo = myVcs.getInfo(myFile.getIOFile());
       if (myInfo == null || myInfo.getRepositoryRootURL() == null) {
-        myException = new VcsException("File ''{0}'' is not under version control" + myFile.getIOFile());
+        myException = new VcsException("File " + myFile.getPath() + " is not under version control");
         return;
       }
       if (myInfo.getURL() == null) {
@@ -319,14 +308,15 @@
         myPI.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", myUrl));
       }
       final SVNRevision pegRevision = myInfo.getRevision();
-      SVNLogClient client = myVcs.createLogClient();
       try {
-        // a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
-        client
-          .doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())},
-                 myFrom == null ? SVNRevision.HEAD : myFrom, myTo == null ? SVNRevision.create(1) : myTo, myPeg,
-                 false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
-                 new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, createConsumerAdapter(myConsumer), repoRootURL, myFile.getCharset()));
+        myVcs.getFactory(myFile.getIOFile()).createHistoryClient().doLog(
+          myFile.getIOFile(),
+          myFrom == null ? SVNRevision.HEAD : myFrom,
+          myTo == null ? SVNRevision.create(1) : myTo, myPeg,
+          false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
+          new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl,
+                                createConsumerAdapter(myConsumer),
+                                repoRootURL, myFile.getCharset()));
       }
       catch (SVNCancelException e) {
         //
@@ -383,7 +373,6 @@
           }
         }
 
-        SVNWCClient wcClient = myVcs.createWCClient();
         final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
         SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
         final SVNURL rootURL = getRepositoryRoot(svnurl, myFrom);
@@ -395,6 +384,7 @@
         if (myUrl.startsWith(root)) {
           relativeUrl = myUrl.substring(root.length());
         }
+        // TODO: Update this call to myVcs.getFactory.createHistoryClient
         SVNLogClient client = myVcs.createLogClient();
         // a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
         client.doLog(svnurl, new String[]{}, myPeg == null ? myFrom : myPeg,
@@ -420,6 +410,7 @@
           relativeUrl = myUrl.substring(root.length());
         }
 
+      // TODO: Update this call to myVcs.getFactory.createHistoryClient
         SVNLogClient client = myVcs.createLogClient();
 
         final RepositoryLogEntryHandler repositoryLogEntryHandler =
@@ -437,36 +428,15 @@
     }
 
     private SVNURL getRepositoryRoot(SVNURL svnurl, SVNRevision operationalFrom) throws SVNException {
-      final SVNRepository repository = myVcs.createRepository(svnurl);
-      final SVNURL root = repository.getRepositoryRoot(false);
-      if (root == null) {
-        return repository.getRepositoryRoot(true);
-      }
-      return root;
-      /*final SVNWCClient wcClient = myVcs.createWCClient();
-      try {
-        final SVNInfo info;
-        info = wcClient.doInfo(svnurl, myPeg, operationalFrom);
-        return info.getRepositoryRootURL();
-      }
-      catch (SVNException e) {
-        try {
-          final SVNInfo info;
-          info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
-          return info.getRepositoryRootURL();
-        } catch (SVNException e1) {
-          final SVNInfo info;
-          info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
-          return info.getRepositoryRootURL();
-        }
-      }*/
+      SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
+
+      return info != null ? info.getRepositoryRootURL() : null;
     }
 
     private boolean existsNow(SVNURL svnurl) {
-      final SVNWCClient wcClient = myVcs.createWCClient();
       final SVNInfo info;
       try {
-        info = wcClient.doInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD);
+        info = myVcs.getInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD, null);
       }
       catch (SVNException e) {
         return false;
@@ -493,6 +463,7 @@
     protected final SvnPathThroughHistoryCorrection myLastPathCorrector;
     private final Charset myCharset;
     protected final ThrowableConsumer<VcsFileRevision, SVNException> myResult;
+    private final String myLastPath;
     private VcsFileRevision myPrevious;
     private final SVNRevision myPegRevision;
     protected final String myUrl;
@@ -512,6 +483,7 @@
       throws SVNException, VcsException {
       myVcs = vcs;
       myLastPathCorrector = new SvnPathThroughHistoryCorrection(lastPath);
+      myLastPath = lastPath;
       myCharset = charset;
       myIndicator = ProgressManager.getInstance().getProgressIndicator();
       myResult = result;
@@ -610,9 +582,9 @@
       String author = logEntry.getAuthor();
       String message = logEntry.getMessage();
       SVNRevision rev = SVNRevision.create(logEntry.getRevision());
-//      final SVNURL url = myRepositoryRoot.appendPath(myLastPath, true);
-      final SVNURL url = entryPath != null ? myRepositoryRoot.appendPath(entryPath.getPath(), true) :
-                         myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false);
+      final SVNURL url = myRepositoryRoot.appendPath(myLastPath, true);
+//      final SVNURL url = entryPath != null ? myRepositoryRoot.appendPath(entryPath.getPath(), true) :
+//                         myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false);
       return new SvnFileRevision(myVcs, myPegRevision, rev, url.toString(), author, date, message, copyPath, myCharset);
     }
   }
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 e30f8ca..171b39c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
@@ -20,21 +20,19 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnRevisionNumber;
 import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.wc.SVNInfo;
 import org.tmatesoft.svn.core.wc.SVNRevision;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
 
 import java.io.File;
 import java.util.List;
 
 /**
-* Created with IntelliJ IDEA.
-* User: Irina.Chernushina
-* Date: 4/27/12
-* Time: 12:24 PM
-* To change this template use File | Settings | File Templates.
-*/
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 4/27/12
+ * Time: 12:24 PM
+ * To change this template use File | Settings | File Templates.
+ */
 public class SvnHistorySession extends VcsAbstractHistorySession {
   private final SvnVcs myVcs;
   private final FilePath myCommittedPath;
@@ -71,19 +69,8 @@
   }
 
   public static VcsRevisionNumber getCurrentCommittedRevision(final SvnVcs vcs, final File file) {
-    try {
-      SVNWCClient wcClient = vcs.createWCClient();
-      SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
-      if (info != null) {
-        return new SvnRevisionNumber(info.getCommittedRevision());
-      }
-      else {
-        return null;
-      }
-    }
-    catch (SVNException e) {
-      return null;
-    }
+    SVNInfo info = vcs.getInfo(file);
+    return info != null ? new SvnRevisionNumber(info.getCommittedRevision()) : null;
   }
 
   public FilePath getCommittedPath() {
@@ -101,7 +88,8 @@
 
   @Override
   public VcsHistorySession copy() {
-    return new SvnHistorySession(myVcs, getRevisionList(), myCommittedPath, myHaveMergeSources, getCurrentRevisionNumber(), true, myHasLocalSource);
+    return new SvnHistorySession(myVcs, getRevisionList(), myCommittedPath, myHaveMergeSources, getCurrentRevisionNumber(), true,
+                                 myHasLocalSource);
   }
 
   @Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java
new file mode 100644
index 0000000..6d41285
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java
@@ -0,0 +1,40 @@
+package org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.ISVNLogEntryHandler;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNLogClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitHistoryClient extends BaseSvnClient implements HistoryClient {
+  @Override
+  public void doLog(@NotNull File path,
+                    @NotNull SVNRevision startRevision,
+                    @NotNull SVNRevision endRevision,
+                    @Nullable SVNRevision pegRevision,
+                    boolean stopOnCopy,
+                    boolean discoverChangedPaths,
+                    boolean includeMergedRevisions,
+                    long limit,
+                    @Nullable String[] revisionProperties,
+                    @Nullable ISVNLogEntryHandler handler) throws VcsException {
+    try {
+      // TODO: a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
+      SVNLogClient client = myVcs.createLogClient();
+
+      client.doLog(new File[]{path}, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions,
+                   limit, revisionProperties, handler);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
index a668a54f9..b01308f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
@@ -38,13 +38,10 @@
 import com.intellij.openapi.vcs.impl.ContentRevisionCache;
 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.SvnUtil;
-import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.*;
 import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.io.SVNRepository;
 import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -108,7 +105,7 @@
     else {
       loader.run();
     }
-    final SVNException exception = loader.getException();
+    final Exception exception = loader.getException();
     if (exception != null) {
       throw new VcsException(exception);
     }
@@ -148,7 +145,7 @@
     private final String myPath;
     private final long myRevision;
     private final OutputStream myDst;
-    private SVNException myException;
+    private Exception myException;
 
     public ContentLoader(String path, OutputStream dst, long revision) {
       myPath = path;
@@ -156,7 +153,7 @@
       myRevision = revision;
     }
 
-    public SVNException getException() {
+    public Exception getException() {
       return myException;
     }
 
@@ -166,16 +163,16 @@
         progress.setText(SvnBundle.message("progress.text.loading.contents", myPath));
         progress.setText2(SvnBundle.message("progress.text2.revision.information", myRevision));
       }
+
       try {
-        SVNRepository repository = myVcs.createRepository(getFullPath());
-        try {
-          repository.getFile("", myRevision, null, myDst);
-        }
-        finally {
-          repository.closeSession();
-        }
+        byte[] contents = SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(SvnUtil.parseUrl(getFullPath())), SVNRevision.create(myRevision),
+                                                  SVNRevision.UNDEFINED);
+        myDst.write(contents);
       }
-      catch (SVNException e) {
+      catch (VcsException e) {
+        myException = e;
+      }
+      catch (IOException e) {
         myException = e;
       }
     }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
index 78718a7..bfb9f1f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
@@ -251,19 +251,10 @@
 
   @Nullable
   private static SVNURL realTargetUrl(final SvnVcs vcs, final WorkingCopyInfo info, final String targetBranchUrl) {
-    final SVNWCClient client = vcs.createWCClient();
-    try {
-      final SVNInfo svnInfo = client.doInfo(new File(info.getLocalPath()), SVNRevision.UNDEFINED);
-      final SVNURL svnurl = svnInfo.getURL();
+    final SVNInfo svnInfo = vcs.getInfo(info.getLocalPath());
+    final SVNURL svnurl = svnInfo != null ? svnInfo.getURL() : null;
 
-      if ((svnurl != null) && (svnurl.toString().startsWith(targetBranchUrl))) {
-        return svnurl;
-      }
-    }
-    catch (SVNException e) {
-      // tracked by return value
-    }
-    return null;
+    return (svnurl != null) && (svnurl.toString().startsWith(targetBranchUrl)) ? svnurl : null;
   }
 
   @Nullable
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 b6c6a89..bc08fff 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
@@ -238,12 +238,7 @@
   }
 
   private SVNInfo getInfo(final File pathFile) {
-    try {
-      return myClient.doInfo(pathFile, SVNRevision.UNDEFINED);
-    } catch (SVNException e) {
-      //
-    }
-    return null;
+    return myVcs.getInfo(pathFile);
   }
 
   private SvnMergeInfoCache.MergeCheckResult checkPathGoingUp(final long revisionAsked, final long targetRevision, final String branchRootPath,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java
index 184d559..9799cf7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java
@@ -117,6 +117,7 @@
         return null;
       }
     };
+    // TODO: Update working copy format detection
     setWorkingCopyFormat(WorkingCopyFormat.ONE_DOT_SEVEN.getFormat());
   }
 
@@ -242,6 +243,30 @@
   }
 
   @Override
+  public SVNURL getURL() {
+    SVNURL url = super.getURL();
+
+    if (url == null) {
+      SVNInfo info = initInfo();
+      url = info != null ? info.getURL() : url;
+    }
+
+    return url;
+  }
+
+  @Override
+  public File getFile() {
+    File file = super.getFile();
+
+    if (file == null) {
+      SVNInfo info = initInfo();
+      file = info != null ? info.getFile() : file;
+    }
+
+    return file;
+  }
+
+  @Override
   public SVNRevision getRevision() {
     final SVNRevision revision = super.getRevision();
     if (revision != null && revision.isValid()) return revision;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
new file mode 100644
index 0000000..4720b33
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
@@ -0,0 +1,65 @@
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommand;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.SVNPropertyValue;
+import org.tmatesoft.svn.core.wc.SVNInfo;
+import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
+
+  @Nullable
+  @Override
+  public SVNPropertyData getProperty(@NotNull File path,
+                                     @NotNull String property,
+                                     boolean revisionProperty,
+                                     @Nullable SVNRevision pegRevision,
+                                     @Nullable SVNRevision revision)
+    throws VcsException {
+    List<String> parameters = new ArrayList<String>();
+
+    parameters.add(property);
+    CommandUtil.put(parameters, path, pegRevision);
+    if (!revisionProperty) {
+      CommandUtil.put(parameters, revision);
+    } else {
+      parameters.add("--revprop");
+      CommandUtil.put(parameters, resolveRevisionNumber(path, revision));
+    }
+
+    SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.propget, parameters, null);
+
+    return new SVNPropertyData(property, SVNPropertyValue.create(StringUtil.nullize(command.getOutput())), null);
+  }
+
+  private SVNRevision resolveRevisionNumber(@NotNull File path, @Nullable SVNRevision revision) throws VcsException {
+    long result = revision != null ? revision.getNumber() : -1;
+
+    // base should be resolved manually - could not set revision to BASE to get revision property
+    if (SVNRevision.BASE.equals(revision)) {
+      SVNInfo info = myVcs.getInfo(path, SVNRevision.BASE);
+
+      result = info != null ? info.getRevision().getNumber() : -1;
+    }
+
+    if (result == -1) {
+      throw new VcsException("Could not determine revision number for file " + path + " and revision " + revision);
+    }
+
+    return SVNRevision.create(result);
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
new file mode 100644
index 0000000..118a397
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
@@ -0,0 +1,23 @@
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface PropertyClient extends SvnClient {
+
+  @Nullable
+  SVNPropertyData getProperty(@NotNull final File path,
+                              @NotNull final String property,
+                              boolean revisionProperty,
+                              @Nullable SVNRevision pegRevision,
+                              @Nullable SVNRevision revision) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
new file mode 100644
index 0000000..1c3c236
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
@@ -0,0 +1,68 @@
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNException;
+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.wc.SVNWCClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClient {
+
+  @Nullable
+  @Override
+  public SVNPropertyData getProperty(@NotNull File path,
+                                     @NotNull String property,
+                                     boolean revisionProperty,
+                                     @Nullable SVNRevision pegRevision,
+                                     @Nullable SVNRevision revision) throws VcsException {
+    try {
+      if (!revisionProperty) {
+        return myVcs.createWCClient().doGetProperty(path, property, pegRevision, revision);
+      } else {
+        return getRevisionProperty(path, property, revision);
+      }
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+
+  private SVNPropertyData getRevisionProperty(@NotNull File path, @NotNull final String property, @Nullable SVNRevision revision) throws SVNException{
+    final SVNWCClient client = myVcs.createWCClient();
+    final SVNPropertyData[] result = new SVNPropertyData[1];
+
+    client.doGetRevisionProperty(path, null, revision, new ISVNPropertyHandler() {
+      @Override
+      public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+        handle(property);
+      }
+
+      @Override
+      public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+        handle(property);
+      }
+
+      @Override
+      public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+        handle(property);
+      }
+
+      private void handle(@NotNull SVNPropertyData data) {
+        if (property.equals(data.getName())) {
+          result[0] = data;
+        }
+      }
+    });
+    return result[0];
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java
new file mode 100644
index 0000000..53c998f
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java
@@ -0,0 +1,79 @@
+package org.jetbrains.idea.svn.revert;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.containers.Convertor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.api.FileStatusResultParser;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNEvent;
+import org.tmatesoft.svn.core.wc.SVNEventAction;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdRevertClient extends BaseSvnClient implements RevertClient {
+
+  private static final String STATUS = "\\s*(.+?)\\s*";
+  private static final String PATH = "\\s*\'(.*?)\'\\s*";
+  private static final String OPTIONAL_COMMENT = "(.*)";
+  private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + PATH + OPTIONAL_COMMENT);
+
+  @Override
+  public void revert(@NotNull File[] paths, @Nullable SVNDepth depth, @Nullable ISVNEventHandler handler) throws VcsException {
+    List<String> parameters = prepareParameters(paths, depth);
+
+    // TODO: handler should be called in parallel with command execution, but this will be in other thread
+    // TODO: check if that is ok for current handler implementation
+    // TODO: add possibility to invoke "handler.checkCancelled" - process should be killed
+    CommandUtil
+      .execute(myVcs, SvnCommandName.revert, parameters, new FileStatusResultParser(CHANGED_PATH, handler, new RevertStatusConvertor()));
+  }
+
+  private static List<String> prepareParameters(File[] paths, SVNDepth depth) {
+    ArrayList<String> parameters = new ArrayList<String>();
+
+    CommandUtil.put(parameters, paths);
+    CommandUtil.put(parameters, depth);
+
+    return parameters;
+  }
+
+  private static class RevertStatusConvertor implements Convertor<Matcher, SVNEvent> {
+
+    public SVNEvent convert(@NotNull Matcher matcher) {
+      String statusMessage = matcher.group(1);
+      String path = matcher.group(2);
+
+      return new SVNEvent(new File(path), null, null, 0, null, null, null, null, createAction(statusMessage), null, null, null, null, null,
+                          null);
+    }
+
+    @Nullable
+    public static SVNEventAction createAction(@NotNull String code) {
+      SVNEventAction result = null;
+
+      if ("Reverted".equals(code)) {
+        result = SVNEventAction.REVERT;
+      }
+      else if ("Failed to revert".equals(code)) {
+        result = SVNEventAction.FAILED_REVERT;
+      }
+      else if ("Skipped".equals(code)) {
+        result = SVNEventAction.SKIP;
+      }
+
+      return result;
+    }
+  }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java
new file mode 100644
index 0000000..053de37
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java
@@ -0,0 +1,18 @@
+package org.jetbrains.idea.svn.revert;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface RevertClient extends SvnClient {
+
+  void revert(@NotNull File[] paths, @Nullable SVNDepth depth, @Nullable ISVNEventHandler handler) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java
new file mode 100644
index 0000000..17c725c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java
@@ -0,0 +1,31 @@
+package org.jetbrains.idea.svn.revert;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNWCClient;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitRevertClient extends BaseSvnClient implements RevertClient {
+
+  @Override
+  public void revert(@NotNull File[] paths, @Nullable SVNDepth depth, @Nullable ISVNEventHandler handler) throws VcsException {
+    SVNWCClient client = myVcs.createWCClient();
+
+    client.setEventHandler(handler);
+    try {
+      client.doRevert(paths, depth, null);
+    }
+    catch (SVNException e) {
+      throw new VcsException(e);
+    }
+  }
+}
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 265d4ca..4140ca7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -28,6 +28,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.revert.RevertClient;
 import org.tmatesoft.svn.core.*;
 import org.tmatesoft.svn.core.wc.*;
 
@@ -74,8 +75,7 @@
     checker.gather(changes);
     exceptions.addAll(checker.getExceptions());
 
-    final SVNWCClient client = mySvnVcs.createWCClient();
-    client.setEventHandler(new ISVNEventHandler() {
+    ISVNEventHandler revertHandler = new ISVNEventHandler() {
       public void handleEvent(SVNEvent event, double progress) {
         if (event.getAction() == SVNEventAction.REVERT) {
           final File file = event.getFile();
@@ -91,7 +91,7 @@
       public void checkCancelled() {
         listener.checkCanceled();
       }
-    });
+    };
 
     final List<CopiedAsideInfo> fromToModified = new ArrayList<CopiedAsideInfo>();
     final MultiMap<File, SVNPropertyData> properties = new MultiMap<File, SVNPropertyData>();
@@ -99,7 +99,7 @@
     // adds (deletes)
     // deletes (adds)
     // modifications
-    final Reverter reverter = new Reverter(client, exceptions);
+    final Reverter reverter = new Reverter(mySvnVcs.getFactory().createRevertClient(), revertHandler, exceptions);
     reverter.revert(checker.getForAdds(), true);
     reverter.revert(checker.getForDeletes(), true);
     final List<File> edits = checker.getForEdits();
@@ -256,24 +256,36 @@
   }
 
   private static class Reverter {
-    private final SVNWCClient myClient;
+    private final RevertClient myClient;
+    private ISVNEventHandler myHandler;
     private final List<VcsException> myExceptions;
 
-    private Reverter(SVNWCClient client, List<VcsException> exceptions) {
+    private Reverter(RevertClient client, ISVNEventHandler handler, List<VcsException> exceptions) {
       myClient = client;
+      myHandler = handler;
       myExceptions = exceptions;
     }
 
     public void revert(final File[] files, final boolean recursive) {
       if (files.length == 0) return;
       try {
-        myClient.doRevert(files, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, null);
+        myClient.revert(files, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, myHandler);
       }
-      catch (SVNException e) {
-        if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_NOT_DIRECTORY) {
-          // skip errors on unversioned resources.
-          myExceptions.add(new VcsException(e));
+      catch (VcsException e) {
+        processRevertError(e);
+      }
+    }
+
+    private void processRevertError(@NotNull VcsException e) {
+      if (e.getCause() instanceof  SVNException) {
+        SVNException cause = (SVNException)e.getCause();
+
+        // skip errors on unversioned resources.
+        if (cause.getErrorMessage().getErrorCode() != SVNErrorCode.WC_NOT_DIRECTORY) {
+          myExceptions.add(e);
         }
+      } else {
+        myExceptions.add(e);
       }
     }
   }
@@ -294,18 +306,17 @@
   }
 
   private void revertFileOrDir(File file) throws SVNException, VcsException {
-    final SVNWCClient wcClient = mySvnVcs.createWCClient();
-    SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
+    SVNInfo info = mySvnVcs.getInfo(file);
     if (info != null) {
       if (info.getKind() == SVNNodeKind.FILE) {
-        wcClient.doRevert(file, false);
+        doRevert(file, false);
       } else {
         if (SVNProperty.SCHEDULE_ADD.equals(info.getSchedule())) {
-          wcClient.doRevert(file, true);
+          doRevert(file, true);
         } else {
           boolean under17Copy = isUnder17Copy(file, info);
           if (under17Copy) {
-            wcClient.doRevert(file, true);
+            doRevert(file, true);
           } else {
             // do update to restore missing directory.
             mySvnVcs.createUpdateClient().doUpdate(file, SVNRevision.HEAD, true);
@@ -317,10 +328,16 @@
     }
   }
 
+  private void doRevert(@NotNull File path, boolean recursive) throws VcsException {
+    mySvnVcs.getFactory(path).createRevertClient().revert(new File[]{path}, SVNDepth.fromRecurse(recursive), null);
+  }
+
   private boolean isUnder17Copy(final File file, final SVNInfo info) throws VcsException {
     final RootsToWorkingCopies copies = mySvnVcs.getRootsToWorkingCopies();
     WorkingCopy copy = copies.getMatchingCopy(info.getURL());
     if (copy == null) {
+      // TODO: Why null could be here?
+      // TODO: Think we could just rewrite it with mySvnVcs.getWorkingCopyFormat(file)
       SVNStatus status = null;
       try {
         status = mySvnVcs.createStatusClient().doStatus(file, false);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
index ecc3fa6..d6bdf63 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
@@ -109,17 +109,8 @@
 
   @Nullable
   private SVNURL getUrlFor(@NotNull final FilePath root) {
-    try {
-      SVNWCClient wcClient = myVCS.createWCClient();
-      final SVNInfo info = wcClient.doInfo(root.getIOFile(), SVNRevision.UNDEFINED);
-      if (info != null) {
-        return info.getURL();
-      }
-      return null;
-    }
-    catch (SVNException e) {
-      return null;
-    }
+    final SVNInfo info = myVCS.getInfo(root.getIOFile());
+    return info != null ? info.getURL() : null;
   }
 
   protected abstract JComponent getPanel();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractUpdateIntegrateCrawler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractUpdateIntegrateCrawler.java
index e9e7b0b..826f753 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractUpdateIntegrateCrawler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractUpdateIntegrateCrawler.java
@@ -59,7 +59,7 @@
       SVNUpdateClient client = myVcs.createUpdateClient();
       client.setEventHandler(myHandler);
 
-      long rev = doUpdate(root, client);
+      long rev = doUpdate(root);
 
       if (rev < 0 && !isMerge()) {
         throw new SVNException(SVNErrorMessage.create(SVNErrorCode.UNKNOWN, SvnBundle.message("exception.text.root.was.not.properly.updated", root)));
@@ -73,9 +73,7 @@
 
   protected abstract void showProgressMessage(ProgressIndicator progress, File root);
 
-  protected abstract long doUpdate(
-    File root,
-    SVNUpdateClient client) throws SVNException;
+  protected abstract long doUpdate(File root) throws SVNException;
 
   protected abstract boolean isMerge();
 }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/MergeRootInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/MergeRootInfo.java
index b8ea052..96701b51 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/MergeRootInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/MergeRootInfo.java
@@ -18,6 +18,7 @@
 import org.jetbrains.idea.svn.SvnVcs;
 import org.tmatesoft.svn.core.SVNException;
 import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.wc.SVNInfo;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc.SVNWCClient;
 
@@ -33,17 +34,9 @@
     myRevision1 = SVNRevision.HEAD;
     myRevision2 = SVNRevision.HEAD;
 
-    try {
-      SVNWCClient wcClient = vcs.createWCClient();
-      final SVNURL url = wcClient.doInfo(file, SVNRevision.UNDEFINED).getURL();
-      myUrl1 = url.toString();
-      myUrl2 = url.toString();
-    }
-    catch (SVNException e) {
-      myUrl1 = "";
-      myUrl2 = "";
-    }
-
+    SVNInfo info = vcs.getInfo(file);
+    myUrl1 = info != null && info.getURL() != null ? info.getURL().toString() : "";
+    myUrl2 = myUrl1;
   }
 
   public SVNURL getUrl1() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
index 9e8a599..9f4a95f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
@@ -91,10 +91,7 @@
       }
     }
 
-    protected long doUpdate(
-      final File root,
-      final SVNUpdateClient client) throws
-                                                                                                        SVNException {
+    protected long doUpdate(final File root) throws SVNException {
       final SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject());
 
       MergeRootInfo info = svnConfig.getMergeRootInfo(root, myVcs);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
index 80e43aa..5d2d415 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
@@ -33,7 +33,6 @@
 import org.tmatesoft.svn.core.wc.SVNInfo;
 import org.tmatesoft.svn.core.wc.SVNRevision;
 import org.tmatesoft.svn.core.wc.SVNUpdateClient;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -76,10 +75,7 @@
       progress.setText(SvnBundle.message("progress.text.updating", root.getAbsolutePath()));
     }
 
-    protected long doUpdate(
-      final File root,
-      final SVNUpdateClient client) throws
-                                    SVNException {
+    protected long doUpdate(final File root) throws SVNException {
       final long rev;
 
       final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
@@ -104,13 +100,15 @@
 
     private SvnUpdateClientI createUpdateClient(SvnConfiguration configuration, File root, boolean isSwitch, SVNURL sourceUrl) {
       final SvnUpdateClientI updateClient;
+      boolean is18Format = myVcs.getWorkingCopyFormat(root) == WorkingCopyFormat.ONE_DOT_EIGHT;
+
       // do not do from command line for switch now
-      if (! isSwitch && SvnConfiguration.UseAcceleration.commandLine.equals(configuration.myUseAcceleration) &&
+      if (! isSwitch && (is18Format || SvnConfiguration.UseAcceleration.commandLine.equals(configuration.myUseAcceleration) &&
           Svn17Detector.is17(myVcs.getProject(), root) && (
           SvnAuthenticationManager.HTTP.equals(sourceUrl.getProtocol()) ||
           SvnAuthenticationManager.HTTPS.equals(sourceUrl.getProtocol())
-          )) {
-        updateClient = new SvnCommandLineUpdateClient(myVcs.getProject(), null);
+          ))) {
+        updateClient = new SvnCommandLineUpdateClient(myVcs, null);
       } else {
         updateClient = new SvnSvnkitUpdateClient(myVcs.createUpdateClient());
       }
@@ -129,18 +127,8 @@
 
   @Nullable
   private static SVNURL getSourceUrl(final SvnVcs vcs, final File root) {
-    try {
-      SVNWCClient wcClient = vcs.createWCClient();
-      final SVNInfo svnInfo = wcClient.doInfo(root, SVNRevision.UNDEFINED);
-      if (svnInfo != null) {
-        return svnInfo.getURL();
-      } else {
-        return null;
-      }
-    }
-    catch (SVNException e) {
-      return null;
-    }
+    final SVNInfo svnInfo = vcs.getInfo(root);
+    return svnInfo != null ? svnInfo.getURL() : null;
   }
 
   public boolean validateOptions(final Collection<FilePath> roots) {
@@ -193,9 +181,8 @@
 
   // false - do not do update
   private boolean checkAncestry(final File sourceFile, final SVNURL targetUrl, final SVNRevision targetRevision) throws SVNException {
-    final SVNWCClient client = myVcs.createWCClient();
-    final SVNInfo sourceSvnInfo = client.doInfo(sourceFile, SVNRevision.UNDEFINED);
-    final SVNInfo targetSvnInfo = client.doInfo(targetUrl, SVNRevision.UNDEFINED, targetRevision);
+    final SVNInfo sourceSvnInfo = myVcs.getInfo(sourceFile);
+    final SVNInfo targetSvnInfo = myVcs.getInfo(targetUrl, targetRevision);
 
     if (sourceSvnInfo == null || targetSvnInfo == null) {
       // cannot check
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateRootInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateRootInfo.java
index 4852e9f..201260e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateRootInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateRootInfo.java
@@ -31,20 +31,9 @@
 
   public UpdateRootInfo(File file, SvnVcs vcs) {
     myRevision = SVNRevision.HEAD;
-    try {
-      SVNWCClient wcClient = vcs.createWCClient();
-      SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
-      if (info != null) {
-        final SVNURL url = info.getURL();
-        myUrl = url.toString();
-      } else {
-        myUrl = "";
-      }
-    }
-    catch (SVNException e) {
-      myUrl = "";
-    }
 
+    SVNInfo info = vcs.getInfo(file);
+    myUrl = info != null && info.getURL() != null ? info.getDepth().toString() : "";
   }
 
   public SVNURL getUrl() {
diff --git a/plugins/svn4idea/svn4idea-tests.iml b/plugins/svn4idea/svn4idea-tests.iml
index 9a537c2..0b826ed 100644
--- a/plugins/svn4idea/svn4idea-tests.iml
+++ b/plugins/svn4idea/svn4idea-tests.iml
@@ -38,7 +38,6 @@
         </SOURCES>
       </library>
     </orderEntry>
-    <orderEntry type="module" module-name="bindSvn" />
   </component>
 </module>
 
diff --git a/plugins/svn4idea/svn4idea.iml b/plugins/svn4idea/svn4idea.iml
index 4f0d931..53dd661 100644
--- a/plugins/svn4idea/svn4idea.iml
+++ b/plugins/svn4idea/svn4idea.iml
@@ -76,16 +76,6 @@
         </SOURCES>
       </library>
     </orderEntry>
-    <orderEntry type="module" module-name="bindSvn" />
-    <orderEntry type="module-library">
-      <library>
-        <CLASSES>
-          <root url="jar://$MODULE_DIR$/bindSvn/lib/javahl.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES />
-      </library>
-    </orderEntry>
   </component>
 </module>
 
diff --git a/plugins/svn4idea/testData18/svn/bin/windows/svn.exe b/plugins/svn4idea/testData18/svn/bin/windows/svn.exe
new file mode 100644
index 0000000..827753f4
--- /dev/null
+++ b/plugins/svn4idea/testData18/svn/bin/windows/svn.exe
Binary files differ
diff --git a/plugins/svn4idea/testData18/svn/newrepo.zip b/plugins/svn4idea/testData18/svn/newrepo.zip
new file mode 100644
index 0000000..fd9a577
--- /dev/null
+++ b/plugins/svn4idea/testData18/svn/newrepo.zip
Binary files differ
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
index 14d1b4c..d5a5552 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
@@ -78,13 +78,19 @@
  * @author yole
  */
 public abstract class SvnTestCase extends AbstractJunitVcsTestCase  {
+
+  public static String ourGlobalTestDataDir;
+  public static Boolean ourGlobalUseNativeAcceleration;
+
   protected TempDirTestFixture myTempDirFixture;
   protected String myRepoUrl;
   protected TestClientRunner myRunner;
   protected String myWcRootName;
-  protected boolean myUseNativeAcceleration = new GregorianCalendar().get(Calendar.HOUR_OF_DAY) % 2 == 0;
+  // TODO: Change this to explicitly run either with native acceleration or not.
+  // properties set through run configurations or different runners (like Suite) could be used
+  private boolean myUseNativeAcceleration = new GregorianCalendar().get(Calendar.HOUR_OF_DAY) % 2 == 0;
 
-  protected final String myTestDataDir;
+  private String myTestDataDir;
   private File myRepoRoot;
   private File myWcRoot;
   private ChangeListManagerGate myGate;
@@ -118,7 +124,13 @@
 
   @Before
   public void setUp() throws Exception {
-    System.out.println("Native client for status: " + myUseNativeAcceleration);
+    System.out.println("Native client for status: " + isUseNativeAcceleration());
+
+    String property = System.getProperty("svn.test.data.directory");
+    if (!StringUtil.isEmpty(property)) {
+      myTestDataDir = property;
+    }
+
     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
       @Override
       public void run() {
@@ -138,7 +150,7 @@
             myPluginRoot = new File(rootPath).getParentFile().getParentFile().getParentFile();
           }
 
-          File svnBinDir =  new File(myPluginRoot, myTestDataDir + "/svn/bin");
+          File svnBinDir =  new File(myPluginRoot, getTestDataDir() + "/svn/bin");
           File svnExecutable = null;
           if (SystemInfo.isWindows) {
             svnExecutable = new File(svnBinDir, "windows/svn.exe");
@@ -156,7 +168,7 @@
                      ? createClientRunner(Collections.singletonMap("DYLD_LIBRARY_PATH", myClientBinaryPath.getPath()))
                      : createClientRunner();
 
-          ZipUtil.extract(new File(myPluginRoot, myTestDataDir + "/svn/newrepo.zip"), myRepoRoot, null);
+          ZipUtil.extract(new File(myPluginRoot, getTestDataDir() + "/svn/newrepo.zip"), myRepoRoot, null);
 
           myWcRoot = new File(myTempDirFixture.getTempDirPath(), myWcRootName);
           assert myWcRoot.mkdir() || myWcRoot.isDirectory() : myWcRoot;
@@ -205,7 +217,7 @@
 
   @Override
   protected void projectCreated() {
-    if (myUseNativeAcceleration) {
+    if (isUseNativeAcceleration()) {
       SvnConfiguration.getInstance(myProject).myUseAcceleration = SvnConfiguration.UseAcceleration.commandLine;
       SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
     }
@@ -319,6 +331,22 @@
     //clManager.ensureUpToDate(false);
   }
 
+  public String getTestDataDir() {
+    return StringUtil.isEmpty(ourGlobalTestDataDir) ? myTestDataDir : ourGlobalTestDataDir;
+  }
+
+  public void setTestDataDir(String testDataDir) {
+    myTestDataDir = testDataDir;
+  }
+
+  public boolean isUseNativeAcceleration() {
+    return ourGlobalUseNativeAcceleration != null ? ourGlobalUseNativeAcceleration : myUseNativeAcceleration;
+  }
+
+  public void setUseNativeAcceleration(boolean useNativeAcceleration) {
+    myUseNativeAcceleration = useNativeAcceleration;
+  }
+
   protected class SubTree {
     public VirtualFile myRootDir;
     public VirtualFile mySourceDir;
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/IgnoredFilesTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/IgnoredFilesTest.java
index 270e6d4..bded7af 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/IgnoredFilesTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/IgnoredFilesTest.java
@@ -54,6 +54,7 @@
 
   @Before
   public void setUp() throws Exception {
+    super.setUp();
     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
       @Override
       public void run() {
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnChangesCorrectlyRefreshedNativeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnChangesCorrectlyRefreshedNativeTest.java
index a9c1074..6153d65 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnChangesCorrectlyRefreshedNativeTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnChangesCorrectlyRefreshedNativeTest.java
@@ -34,7 +34,7 @@
 
   @Override
   public void setUp() throws Exception {
-    myUseNativeAcceleration = true;
+    setUseNativeAcceleration(true);
     super.setUp();
 
     clManager = ChangeListManager.getInstance(myProject);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java
index f4da04e..f18b6a5 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java
@@ -465,7 +465,7 @@
     return feedback;
   }
 
-  private void checkinFile(VirtualFile file, FileStatus status) {
+  protected void checkinFile(VirtualFile file, FileStatus status) {
     final Change change = myChangeListManager.getChange(file);
     Assert.assertNotNull(change);
     Assert.assertEquals(status, change.getFileStatus());
@@ -478,6 +478,7 @@
   }
 
   protected void run2variants(final MyRunner runner) throws Exception {
+    // TODO: Change this to run different variants separately. See SvnTestCase.myUseAcceleration.
     setNativeAcceleration(false);
     runner.run();
     runner.cleanup();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
index 500acbd..3e3b2fd 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
@@ -27,6 +27,7 @@
 import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ui.UIUtil;
 import junit.framework.Assert;
 import org.junit.Test;
 
@@ -171,8 +172,7 @@
 
   private void updatedCreatedExternalFromIDEAImpl() {
     final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
-    ProjectLevelVcsManager.getInstance(myProject).setDirectoryMappings(
-      Arrays.asList(new VcsDirectoryMapping(FileUtil.toSystemIndependentName(sourceDir.getPath()), myVcs.getName())));
+    setNewDirectoryMappings(sourceDir);
     imitUpdate(myProject);
 
     final File externalFile = new File(sourceDir, "external/t11.txt");
@@ -180,6 +180,16 @@
     Assert.assertNotNull(externalVf);
   }
 
+  private void setNewDirectoryMappings(final File sourceDir) {
+    UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+      @Override
+      public void run() {
+        ProjectLevelVcsManager.getInstance(myProject).setDirectoryMappings(
+          Arrays.asList(new VcsDirectoryMapping(FileUtil.toSystemIndependentName(sourceDir.getPath()), myVcs.getName())));
+      }
+    });
+  }
+
   @Test
   public void testUncommittedExternalStatus() throws Exception {
     prepareExternal(false, true, false);
@@ -221,8 +231,7 @@
 
   private void uncommittedExternalCopyIsDetectedImpl() {
     final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
-    ProjectLevelVcsManager.getInstance(myProject).setDirectoryMappings(
-      Arrays.asList(new VcsDirectoryMapping(FileUtil.toSystemIndependentName(sourceDir.getPath()), myVcs.getName())));
+    setNewDirectoryMappings(sourceDir);
     imitUpdate(myProject);
     refreshSvnMappingsSynchronously();
 
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
index 171bb1c..7c32af9 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
@@ -22,6 +22,7 @@
 import junit.framework.Assert;
 import junit.framework.TestCase;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.tmatesoft.sqljet.core.SqlJetException;
 import org.tmatesoft.sqljet.core.table.ISqlJetBusyHandler;
 import org.tmatesoft.sqljet.core.table.ISqlJetTransaction;
@@ -42,6 +43,8 @@
  * Date: 10/23/12
  * Time: 2:27 PM
  */
+// TODO: Locking functionality which is tested by this test is not required anymore. Likely test needs to be removed.
+@Ignore
 public class SvnLockingTest extends TestCase {
   private File myWorkingCopyRoot;
   private SvnTestWriteOperationLocks myLocks;
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
index 61aca567..b6d6ae1 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
@@ -72,7 +72,7 @@
   @Before
   public void setUp() throws Exception {
     super.setUp();
-    final File certFile = new File(myPluginRoot, myTestDataDir + "/svn/____.pfx");
+    final File certFile = new File(myPluginRoot, getTestDataDir() + "/svn/____.pfx");
     setNativeAcceleration(true);
     myVcs = SvnVcs.getInstance(myProject);
     // replace authentication provider so that pass credentials without dialogs
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnChangesCorrectlyRefreshedNativeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnChangesCorrectlyRefreshedNativeTest.java
index 2057336..8939f1c 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnChangesCorrectlyRefreshedNativeTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnChangesCorrectlyRefreshedNativeTest.java
@@ -49,7 +49,7 @@
 
   @Override
   public void setUp() throws Exception {
-    myUseNativeAcceleration = true;
+    setUseNativeAcceleration(true);
     super.setUp();
 
     clManager = ChangeListManager.getInstance(myProject);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn18/Svn18TestSuite.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn18/Svn18TestSuite.java
new file mode 100644
index 0000000..a701973
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn18/Svn18TestSuite.java
@@ -0,0 +1,33 @@
+package org.jetbrains.idea.svn18;
+
+import org.jetbrains.idea.SvnTestCase;
+import org.jetbrains.idea.svn.*;
+import org.junit.ClassRule;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+// TODO: Add svn clients for mac and linux
+@RunWith(Suite.class)
+@Suite.SuiteClasses({SvnAddTest.class, SvnDeleteTest.class})
+public class Svn18TestSuite {
+
+  @ClassRule
+  public static TestRule configuration = new ExternalResource() {
+    @Override
+    protected void before() throws Throwable {
+      SvnTestCase.ourGlobalTestDataDir = "testData18";
+      SvnTestCase.ourGlobalUseNativeAcceleration = true;
+    }
+
+    @Override
+    protected void after() {
+      SvnTestCase.ourGlobalTestDataDir = null;
+      SvnTestCase.ourGlobalUseNativeAcceleration = null;
+    }
+  };
+}
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
index 13b8e7d..ffa9118 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
@@ -46,14 +46,12 @@
   public static final int STATE_UPDATING = 0x0008;
   /**
    * Supporting this feature means that server implements some kind of issues filtering.
-   * It may be special query language like the one used in Youtrack or mere plain
+   * It may be special query language like the one used in YouTrack or mere plain
    * text search.
-   * If server supports this feature it MUST return tasks already
-   * filtered according to {@code query} parameter from {@code getIssues} method.
-   * Otherwise they will be filtered using {@code TaskSearchSupport#filterTasks}
-   *
-   * @see com.intellij.tasks.impl.TaskManagerImpl
-   * @see com.intellij.tasks.actions.TaskSearchSupport
+   * <p>
+   * If server supports this feature it MUST return tasks already filtered according
+   * to {@code query} parameter from {@link #getIssues}} method, otherwise they will
+   * be filtered internally in {@link TaskManager#getIssues}
    */
   public static final int NATIVE_SEARCH = 0x0010;
 
@@ -106,7 +104,7 @@
 
   /**
    * Get issues from the repository. If query is null, return issues should assigned to current user only.
-   * If server supports {@code NATIVE_SEARCH} feature, tasks returned MUST be filtered by specified query.
+   * If server supports {@link #NATIVE_SEARCH} feature, tasks returned MUST be filtered by specified query.
    *
    * @param query repository specific.
    * @param max   maximum issues number to return
diff --git a/plugins/tasks/tasks-core/src/META-INF/plugin.xml b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
index 3573bb1..dd42d52 100644
--- a/plugins/tasks/tasks-core/src/META-INF/plugin.xml
+++ b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
@@ -8,6 +8,8 @@
   <!--fake dependency for Web IDE-->
   <depends>com.intellij.modules.xml</depends>
   <depends optional="true" config-file="java-contexts.xml">com.intellij.modules.java</depends>
+  <!-- Optional dependency on XPath plugin for syntax highlighting in GenericRepository configuration dialog -->
+  <depends optional="true">XPathView</depends>
 
   <project-components>
     <component>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java
index cdc20c5..756abde 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java
@@ -14,7 +14,6 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.popup.JBPopup;
 import com.intellij.openapi.util.Ref;
-import com.intellij.psi.PsiManager;
 import com.intellij.tasks.LocalTask;
 import com.intellij.tasks.Task;
 import com.intellij.tasks.TaskManager;
@@ -22,7 +21,6 @@
 import com.intellij.tasks.impl.TaskManagerImpl;
 import com.intellij.tasks.impl.TaskUtil;
 import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
 import com.intellij.util.IconUtil;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
@@ -67,53 +65,25 @@
                                     boolean everywhere,
                                     @NotNull ProgressIndicator cancelled,
                                     @NotNull Processor<Object> consumer) {
-        List<Task> cachedAndLocalTasks = TaskSearchSupport.getLocalAndCachedTasks(TaskManager.getManager(project), pattern, everywhere);
-        List<TaskPsiElement> taskPsiElements = ContainerUtil.map(cachedAndLocalTasks, new Function<Task, TaskPsiElement>() {
-          @Override
-          public TaskPsiElement fun(Task task) {
-            return new TaskPsiElement(PsiManager.getInstance(project), task);
-          }
-        });
 
         CREATE_NEW_TASK_ACTION.setTaskName(pattern);
-        cancelled.checkCanceled();
         if (!consumer.process(CREATE_NEW_TASK_ACTION)) return false;
 
-        boolean cachedTasksFound = taskPsiElements.size() != 0;
-        if (cachedTasksFound) {
-          cancelled.checkCanceled();
-          if (!consumer.process(ChooseByNameBase.NON_PREFIX_SEPARATOR)) return false;
-        }
-
-        for (Object element : taskPsiElements) {
-          cancelled.checkCanceled();
-          if (!consumer.process(element)) return false;
-        }
+        List<Task> cachedAndLocalTasks = TaskSearchSupport.getLocalAndCachedTasks(TaskManager.getManager(project), pattern, everywhere);
+        boolean cachedTasksFound = !cachedAndLocalTasks.isEmpty();
+        if (!processTasks(cachedAndLocalTasks, consumer, cachedTasksFound, cancelled)) return false;
 
         List<Task> tasks = TaskSearchSupport
           .getRepositoriesTasks(TaskManager.getManager(project), pattern, base.getMaximumListSizeLimit(), 0, true, everywhere, cancelled);
         tasks.removeAll(cachedAndLocalTasks);
-        taskPsiElements = ContainerUtil.map(tasks, new Function<Task, TaskPsiElement>() {
-          @Override
-          public TaskPsiElement fun(Task task) {
-            return new TaskPsiElement(PsiManager.getInstance(project), task);
-          }
-        });
 
-        if (!cachedTasksFound && taskPsiElements.size() != 0) {
-          cancelled.checkCanceled();
-          if (!consumer.process(ChooseByNameBase.NON_PREFIX_SEPARATOR)) return false;
-        }
-
-        for (Object element : taskPsiElements) {
-          cancelled.checkCanceled();
-          if (!consumer.process(element)) return false;
-        }
-        return true;
+        return processTasks(tasks, consumer, cachedTasksFound, cancelled);
       }
     }, null, false, 0);
+
     popup.setShowListForEmptyPattern(true);
     popup.setSearchInAnyPlace(true);
+    popup.setFixLostTyping(false);
     popup.setAdText("<html>Press SHIFT to merge with current context<br/>" +
                     "Pressing " +
                     KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC)) +
@@ -166,6 +136,16 @@
     }, null, popup);
   }
 
+  private static boolean processTasks(List<Task> tasks, Processor<Object> consumer, boolean cachedTasksFound, ProgressIndicator cancelled) {
+    if (!cachedTasksFound && !tasks.isEmpty() && !consumer.process(ChooseByNameBase.NON_PREFIX_SEPARATOR)) return false;
+
+    for (Object element : tasks) {
+      cancelled.checkCanceled();
+      if (!consumer.process(element)) return false;
+    }
+    return true;
+  }
+
   private static void showOpenTaskDialog(final Project project, final Task task) {
     JBPopup hint = DocumentationManager.getInstance(project).getDocInfoHint();
     if (hint != null) hint.cancel();
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
index 489afb9..3eeea41 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
@@ -117,6 +117,11 @@
 
   @Override
   protected void doOKAction() {
+    createTask();
+    super.doOKAction();
+  }
+
+  public void createTask() {
     TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
 
     taskManager.getState().markAsInProgress = isMarkAsInProgress();
@@ -133,18 +138,17 @@
         LOG.warn(ex);
       }
     }
+    LocalTask activeTask = taskManager.getActiveTask();
     LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
     if (myCreateChangelist.isSelected()) {
       taskManager.createChangeList(localTask, myChangelistName.getText());
     }
     if (myCreateBranch.isSelected()) {
-      LocalTask activeTask = taskManager.getActiveTask();
       taskManager.createBranch(localTask, activeTask, myBranchName.getText());
     }
     if (myTask.getType() == TaskType.EXCEPTION && AnalyzeTaskStacktraceAction.hasTexts(myTask)) {
       AnalyzeTaskStacktraceAction.analyzeStacktrace(myTask, myProject);
     }
-    super.doOKAction();
   }
 
   @Nullable
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskCellRenderer.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskCellRenderer.java
index 65a4d45..bb8f458 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskCellRenderer.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskCellRenderer.java
@@ -7,7 +7,6 @@
 import com.intellij.tasks.LocalTask;
 import com.intellij.tasks.Task;
 import com.intellij.tasks.TaskManager;
-import com.intellij.tasks.doc.TaskPsiElement;
 import com.intellij.ui.LayeredIcon;
 import com.intellij.ui.SimpleColoredComponent;
 import com.intellij.ui.SimpleTextAttributes;
@@ -39,8 +38,8 @@
     final JPanel panel = new JPanel(new BorderLayout());
     panel.setBackground(UIUtil.getListBackground(sel));
     panel.setForeground(UIUtil.getListForeground(sel));
-    if (value instanceof TaskPsiElement) {
-      final Task task = ((TaskPsiElement)value).getTask();
+    if (value instanceof Task) {
+      final Task task = ((Task)value);
       final SimpleColoredComponent c = new SimpleColoredComponent();
       final TaskManager taskManager = TaskManager.getManager(myProject);
       final boolean isLocalTask = taskManager.findTask(task.getId()) != null;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java
index c2c6306..98704b7 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java
@@ -77,12 +77,7 @@
                                     String pattern,
                                     boolean cached,
                                     boolean autopopup) {
-    final Matcher matcher = getMatcher(pattern);
-    return ContainerUtil.mapNotNull(getTasks(pattern, cached, autopopup, myManager), new NullableFunction<Task, Task>() {
-      public Task fun(Task task) {
-        return matcher.matches(task.getId()) || matcher.matches(task.getSummary()) ? task : null;
-      }
-    });
+    return filterTasks(pattern, getTasks(pattern, cached, autopopup, myManager));
   }
 
 
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
index 5c4733b..f437897 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
@@ -27,6 +27,7 @@
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.JDOMUtil;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.tasks.Task;
 import com.intellij.util.NullableFunction;
@@ -170,7 +171,7 @@
       //noinspection ResultOfMethodCallIgnored
       tasksFolder.mkdir();
     }
-    String projectName = myProject.getName();
+    String projectName = FileUtil.sanitizeFileName(myProject.getName());
     return new File(tasksFolder, projectName + postfix);
   }
 
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
index f3ed0f9..c4c5869 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
@@ -16,6 +16,7 @@
 import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.GetMethod;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -31,19 +32,22 @@
 public class GenericRepository extends BaseRepositoryImpl {
   private static final Logger LOG = Logger.getInstance(GenericRepository.class);
 
-  public final PredefinedFactoryVariable SERVER_URL_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("serverUrl") {
+  public final FactoryVariable SERVER_URL_TEMPLATE_VARIABLE = new FactoryVariable("serverUrl") {
+    @NotNull
     @Override
     public String getValue() {
       return GenericRepository.this.getUrl();
     }
   };
-  public final PredefinedFactoryVariable USERNAME_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("username") {
+  public final FactoryVariable USERNAME_TEMPLATE_VARIABLE = new FactoryVariable("username") {
+    @NotNull
     @Override
     public String getValue() {
       return GenericRepository.this.getUsername();
     }
   };
-  public final PredefinedFactoryVariable PASSWORD_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("password", true) {
+  public final FactoryVariable PASSWORD_TEMPLATE_VARIABLE = new FactoryVariable("password", true) {
+    @NotNull
     @Override
     public String getValue() {
       return GenericRepository.this.getPassword();
@@ -155,7 +159,7 @@
   public boolean isConfigured() {
     if (!super.isConfigured()) return false;
     for (TemplateVariable variable : getTemplateVariables()) {
-      if (variable.getIsShownOnFirstTab() && StringUtil.isEmpty(variable.getValue())) {
+      if (variable.isShownOnFirstTab() && StringUtil.isEmpty(variable.getValue())) {
         return false;
       }
     }
@@ -171,8 +175,8 @@
       executeMethod(getLoginMethod());
     }
     List<TemplateVariable> variables = concat(getAllTemplateVariables(),
-                                              new TemplateVariable("max", max),
-                                              new TemplateVariable("since", since));
+                                              new TemplateVariable("max", String.valueOf(max)),
+                                              new TemplateVariable("since", String.valueOf(since)));
     String requestUrl = GenericRepositoryUtil.substituteTemplateVariables(getTasksListUrl(), variables);
     String responseBody = executeMethod(getHttpMethod(requestUrl, myTasksListMethodType));
     Task[] tasks = getActiveResponseHandler().parseIssues(responseBody, max);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java
index 6ddb8da..c677744 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java
@@ -131,7 +131,7 @@
           myRepository.setTemplateVariables(ContainerUtil.filter(dialog.getTemplateVariables(), new Condition<TemplateVariable>() {
             @Override
             public boolean value(TemplateVariable variable) {
-              return !variable.getIsPredefined();
+              return !variable.isReadOnly();
             }
           }));
           myCustomPanel.removeAll();
@@ -186,8 +186,8 @@
     myField2Variable = new IdentityHashMap<JTextField, TemplateVariable>();
     FormBuilder builder = FormBuilder.createFormBuilder();
     for (final TemplateVariable variable : myRepository.getTemplateVariables()) {
-      if (variable.getIsShownOnFirstTab()) {
-        JTextField field = variable.getIsHidden() ? new JPasswordField(variable.getValue()) : new JTextField(variable.getValue());
+      if (variable.isShownOnFirstTab()) {
+        JTextField field = variable.isHidden() ? new JPasswordField(variable.getValue()) : new JTextField(variable.getValue());
         myField2Variable.put(field, variable);
         installListener(field);
         JBLabel label = new JBLabel(prettifyVariableName(variable.getName()) + ":", SwingConstants.RIGHT);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
index 1a9bb42..95f865b 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
@@ -59,7 +59,8 @@
   public List<TaskRepositorySubtype> getAvailableSubtypes() {
     return Arrays.asList(
       this,
-      new AsanaRepository()
+      new AsanaRepository(),
+      new AssemblaRepository()
     );
   }
 
@@ -111,4 +112,10 @@
       super("Asana", TasksIcons.Asana);
     }
   }
+
+  public class AssemblaRepository extends GenericSubtype {
+    public AssemblaRepository() {
+      super("Assembla", TasksIcons.Assembla);
+    }
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java
index cc80ed2..c97a77f 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java
@@ -1,7 +1,5 @@
 package com.intellij.tasks.generic;
 
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.PlainTextFileType;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.Function;
@@ -17,7 +15,7 @@
 import java.util.Map;
 
 /**
- * Author: Mikhail Golubev
+ * @author Mikhail Golubev
  */
 @Tag("JsonResponseHandler")
 public final class JsonPathResponseHandler extends SelectorBasedResponseHandler {
@@ -44,11 +42,6 @@
     super(repository);
   }
 
-  @Override
-  public FileType getSelectorFileType() {
-    return PlainTextFileType.INSTANCE;
-  }
-
   @Nullable
   private Object extractRawValue(@NotNull Selector selector, @NotNull String source) throws Exception {
     if (StringUtil.isEmpty(selector.getPath())) {
@@ -140,6 +133,7 @@
     return myCompiledCache.get(path);
   }
 
+  @NotNull
   @Override
   public ResponseType getResponseType() {
     return ResponseType.JSON;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java
index e9e6d5e..3c3ed23 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java
@@ -60,7 +60,7 @@
 
         @Override
         public boolean isCellEditable(TemplateVariable templateVariable) {
-          return !templateVariable.getIsPredefined();
+          return !templateVariable.isReadOnly();
         }
 
         @Override
@@ -82,7 +82,7 @@
 
         @Override
         public boolean isCellEditable(TemplateVariable templateVariable) {
-          return !templateVariable.getIsPredefined();
+          return !templateVariable.isReadOnly();
         }
 
         @Override
@@ -93,7 +93,7 @@
 
         @Override
         public TableCellRenderer getRenderer(TemplateVariable variable) {
-          if (variable.getIsHidden()) {
+          if (variable.isHidden()) {
             return new TableCellRenderer() {
               @Override
               public Component getTableCellRendererComponent(JTable table,
@@ -112,7 +112,7 @@
         @Nullable
         @Override
         public TableCellEditor getEditor(final TemplateVariable variable) {
-          if (variable.getIsHidden()) {
+          if (variable.isHidden()) {
             return new AbstractTableCellEditor() {
               private JPasswordField myPasswordField;
               @Override
@@ -141,12 +141,12 @@
         @Nullable
         @Override
         public Boolean valueOf(TemplateVariable o) {
-          return o.getIsShownOnFirstTab();
+          return o.isShownOnFirstTab();
         }
 
         @Override
         public void setValue(TemplateVariable variable, Boolean value) {
-          variable.setIsShownOnFirstTab(value);
+          variable.setShownOnFirstTab(value);
           setModified();
         }
 
@@ -157,7 +157,7 @@
 
         @Override
         public boolean isCellEditable(TemplateVariable variable) {
-          return !variable.getIsPredefined();
+          return !variable.isReadOnly();
         }
 
         @Nullable
@@ -171,12 +171,12 @@
         @Nullable
         @Override
         public Boolean valueOf(TemplateVariable o) {
-          return o.getIsHidden();
+          return o.isHidden();
         }
 
         @Override
         public void setValue(TemplateVariable variable, Boolean value) {
-          variable.setIsHidden(value);
+          variable.setHidden(value);
           setModified();
           // value column editor may be changed
           TemplateVariablesTable.this.refreshValues();
@@ -189,7 +189,7 @@
 
         @Override
         public boolean isCellEditable(TemplateVariable variable) {
-          return !variable.getIsPredefined();
+          return !variable.isReadOnly();
         }
 
         @Nullable
@@ -203,7 +203,7 @@
 
     @Override
     protected TemplateVariable createElement() {
-      return new TemplateVariable("", "", false, null);
+      return new TemplateVariable("", "");
     }
 
     @Override
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java
index c080851..4d7f5a5 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java
@@ -68,8 +68,9 @@
     return myTaskRegex.hashCode();
   }
 
+  @NotNull
   @Override
-  public JComponent getConfigurationComponent(Project project) {
+  public JComponent getConfigurationComponent(@NotNull Project project) {
     FormBuilder builder = FormBuilder.createFormBuilder();
     final EditorTextField taskPatternText;
     taskPatternText = new LanguageTextField(RegExpLanguage.INSTANCE, project, myTaskRegex, false);
@@ -86,7 +87,7 @@
 
   @NotNull
   @Override
-  public Task[] parseIssues(String response, int max) throws Exception {
+  public Task[] parseIssues(@NotNull String response, int max) throws Exception {
     final List<String> placeholders = getPlaceholders(myTaskRegex);
     if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
       throw new Exception("Incorrect Task Pattern");
@@ -120,7 +121,7 @@
 
   @Nullable
   @Override
-  public Task parseIssue(String response) throws Exception {
+  public Task parseIssue(@NotNull String response) throws Exception {
     return null;
   }
 
@@ -150,6 +151,7 @@
     return !StringUtil.isEmpty(myTaskRegex);
   }
 
+  @NotNull
   @Override
   public ResponseType getResponseType() {
     return ResponseType.TEXT;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java
index d51c38a..cb8830b 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java
@@ -10,7 +10,7 @@
 
 /**
  * ResponseHandler subclasses represent different strategies of extracting tasks from
- * task server responses (e.g. using regular expressions, XPath, JSONPath, CSS selector etc.).
+ * task server responses (e.g. using regular expressions, XPath, JSONPath, CSS selector etc.)
  *
  * @see XPathResponseHandler
  * @see JsonPathResponseHandler
@@ -19,36 +19,40 @@
  */
 public abstract class ResponseHandler implements Cloneable {
 
-  // XXX: what about serialization of circular dependencies?
   protected GenericRepository myRepository;
 
-  // Serialization constructor
+  /**
+   * Serialization constructor
+   */
   public ResponseHandler() {
     // empty
   }
 
-  public ResponseHandler(GenericRepository repository) {
+  public ResponseHandler(@NotNull GenericRepository repository) {
     myRepository = repository;
   }
 
-  public void setRepository(GenericRepository repository) {
+  public void setRepository(@NotNull GenericRepository repository) {
     myRepository = repository;
   }
 
+  @NotNull
   @Transient
   public GenericRepository getRepository() {
     return myRepository;
   }
 
-  public abstract JComponent getConfigurationComponent(Project project);
+  @NotNull
+  public abstract JComponent getConfigurationComponent(@NotNull Project project);
 
+  @NotNull
   public abstract ResponseType getResponseType();
 
   @NotNull
-  public abstract Task[] parseIssues(String response, int max) throws Exception;
+  public abstract Task[] parseIssues(@NotNull String response, int max) throws Exception;
 
   @Nullable
-  public abstract Task parseIssue(String response) throws Exception;
+  public abstract Task parseIssue(@NotNull String response) throws Exception;
 
   public abstract boolean isConfigured();
 
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseType.java
index aa4bd78..8889e26 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseType.java
@@ -2,40 +2,82 @@
 
 import com.intellij.ide.highlighter.HtmlFileType;
 import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.fileTypes.PlainTextFileType;
 import org.intellij.lang.regexp.RegExpFileType;
-import org.intellij.lang.xpath.XPathFileType;
+import org.jetbrains.annotations.NotNull;
+
 
 /**
- * User: evgeny.zakrevsky
- * Date: 10/25/12
+ * ResponseType contains information about what selector types used
+ * to extract information from server responses with specific content-type.
+ *
+ * @author evgeny.zakrevsky
+ * @author Mikhail Golubev
  */
 public enum ResponseType {
-  XML("application/xml", XmlFileType.INSTANCE, XPathFileType.XPATH2),
-  JSON("application/json", PlainTextFileType.INSTANCE, PlainTextFileType.INSTANCE),
+
+  XML("application/xml", XmlFileType.INSTANCE, findXPathFileType()),
+  JSON("application/json", findFileTypePlainDefault("JSON"), PlainTextFileType.INSTANCE),
   // TODO: think about possible selector type if it needed at all (e.g. CSS selector)
   HTML("text/html", HtmlFileType.INSTANCE, PlainTextFileType.INSTANCE),
   TEXT("text/plain", PlainTextFileType.INSTANCE, RegExpFileType.INSTANCE);
 
-  private String myMimeType;
-  private FileType myContentFileType;
-  private FileType mySelectorFileType;
+  private final String myMimeType;
+  private final FileType myContentFileType;
+  private final FileType mySelectorFileType;
 
-  ResponseType(final String s, final FileType contentFileType, final FileType selectorFileType) {
+  private static Logger LOG = Logger.getInstance(ResponseType.class);
+
+
+  ResponseType(@NotNull String s, @NotNull FileType contentFileType, @NotNull FileType selectorFileType) {
     myMimeType = s;
     myContentFileType = contentFileType;
     mySelectorFileType = selectorFileType;
   }
 
+  /**
+   * Unfortunately XPATH instance can't be received this way, because XPathSupportLoader
+   * registers XPathFileType in FileTypeManager only in unit test and debug modes
+   */
+  @NotNull
+  private static FileType findFileTypePlainDefault(@NotNull final String name) {
+    FileType fileType = FileTypeManager.getInstance().findFileTypeByName(name);
+    return fileType == null ? PlainTextFileType.INSTANCE : fileType;
+  }
+
+  /**
+   * Temporary workaround for IDEA-112605
+   */
+  @NotNull
+  private static FileType findXPathFileType() {
+    if (LOG == null) {
+      LOG = Logger.getInstance(ResponseType.class);
+    }
+    try {
+      Class<?> xPathClass = Class.forName("org.intellij.lang.xpath.XPathFileType");
+      LOG.debug("XPathFileType class loaded successfully");
+      return (FileType)xPathClass.getField("XPATH").get(null);
+    }
+    catch (Exception e) {
+      LOG.debug("XPathFileType class not found. Using PlainText.INSTANCE instead");
+      return PlainTextFileType.INSTANCE;
+    }
+  }
+
+  @NotNull
   public String getMimeType() {
     return myMimeType;
   }
 
+  @NotNull
   public FileType getContentFileType() {
     return myContentFileType;
   }
 
+  @NotNull
   public FileType getSelectorFileType() {
     return mySelectorFileType;
   }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java
index 865e43d..0394cc5 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java
@@ -1,5 +1,6 @@
 package com.intellij.tasks.generic;
 
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
@@ -24,6 +25,7 @@
  * @author Mikhail Golubev
  */
 public abstract class SelectorBasedResponseHandler extends ResponseHandler {
+  private static final Logger LOG = Logger.getInstance(SelectorBasedResponseHandler.class);
 
   // Supported selector names
   @NonNls protected static final String TASKS = "tasks";
@@ -81,8 +83,6 @@
     ));
   }
 
-  public abstract FileType getSelectorFileType();
-
   @Tag("selectors")
   @Property(surroundWithTag = false)
   @AbstractCollection(surroundWithTag = false)
@@ -112,11 +112,11 @@
     return s.getPath();
   }
 
+  @NotNull
   @Override
-  public JComponent getConfigurationComponent(Project project) {
-    HighlightedSelectorsTable table = new HighlightedSelectorsTable(getSelectorFileType(),
-                                                                    project,
-                                                                    getSelectors());
+  public JComponent getConfigurationComponent(@NotNull Project project) {
+    FileType fileType = getResponseType().getSelectorFileType();
+    HighlightedSelectorsTable table = new HighlightedSelectorsTable(fileType, project, getSelectors());
     return new JBScrollPane(table);
   }
 
@@ -158,13 +158,14 @@
 
   @NotNull
   @Override
-  public final Task[] parseIssues(String response, int max) throws Exception {
+  public final Task[] parseIssues(@NotNull String response, int max) throws Exception {
     if (StringUtil.isEmpty(getSelectorPath(TASKS)) ||
         StringUtil.isEmpty(getSelectorPath(ID)) ||
         StringUtil.isEmpty(getSelectorPath(SUMMARY))) {
       throw new Exception("Selectors 'tasks', 'id' and 'summary' are mandatory");
     }
     List<Object> tasks = selectTasksList(response, max);
+    LOG.debug(String.format("Total %d tasks extracted from response", tasks.size()));
     List<Task> result = new ArrayList<Task>(tasks.size());
     for (Object context : tasks) {
       String id = selectString(getSelector(ID), context);
@@ -232,7 +233,7 @@
 
   @Nullable
   @Override
-  public final Task parseIssue(String response) throws Exception {
+  public final Task parseIssue(@NotNull String response) throws Exception {
     if (StringUtil.isEmpty(getSelectorPath(SINGLE_TASK_ID)) ||
         StringUtil.isEmpty(getSelectorPath(SINGLE_TASK_SUMMARY))) {
       throw new Exception("Selectors 'singleTask-id' and 'singleTask-summary' are mandatory");
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/TemplateVariable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/TemplateVariable.java
index d8377bb..f3b59fe 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/TemplateVariable.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/TemplateVariable.java
@@ -3,51 +3,42 @@
 import com.intellij.util.xmlb.annotations.Attribute;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
- * User: evgeny.zakrevsky
- * Date: 10/26/12
+ * Editable variable which name can be used as placeholder and auto completed in EditorFields of
+ * {@link GenericRepositoryEditor}. Variables is editable via {@link ManageTemplateVariablesDialog},
+ * but if {@code shownOnFirstTab} property was set, it will also be shown on "General" tab among
+ * standard fields like "Server URL", "Username" and "Password".
+ *
+ * @see GenericRepositoryEditor
+ * @see ManageTemplateVariablesDialog
+ *
+ * @author evgeny.zakrevsky
+ * @author Mikhail Golubev
  */
 public class TemplateVariable {
   private String myName;
   private String myValue = "";
-  private String myDescription;
-  private boolean myIsPredefined;
-  private boolean myIsHidden;
-  private boolean myIsShownOnFirstTab;
+  private String myDescription = "";
+  private boolean myReadOnly;
+  private boolean myHidden;
+  private boolean myShownOnFirstTab;
 
-  public static TemplateVariableBuilder builder(String name) {
-    return new TemplateVariableBuilder(name);
-  }
-
-  private TemplateVariable(TemplateVariableBuilder builder) {
-    myName = builder.myName;
-    myValue = builder.myValue;
-    myDescription = builder.myDescription;
-    myIsHidden = builder.myIsHidden;
-    myIsShownOnFirstTab = builder.myIsShowOnFirstTab;
-    myIsPredefined = builder.myIsPredefined;
-  }
-
-  public TemplateVariable(String name, Object value) {
-    this(name, value, false, "");
-  }
-
-  public TemplateVariable(@NotNull @NonNls String name, @NotNull @NonNls Object value, boolean isPredefined, @Nullable String description) {
+  public TemplateVariable(@NotNull @NonNls String name, @NotNull @NonNls String value) {
     myName = name;
     myValue = String.valueOf(value);
-    myIsPredefined = isPredefined;
-    myDescription = description;
+    myReadOnly = false;
+    myDescription = "";
   }
 
   /**
    * Serialization constructor
    */
+  @SuppressWarnings("unusedDesclaration")
   public TemplateVariable() {
+    // empty
   }
 
-
   /**
    * Cloning constructor
    */
@@ -55,157 +46,119 @@
     myName = other.getName();
     myValue = other.getValue();
     myDescription = other.getDescription();
-    myIsHidden = other.getIsHidden();
-    myIsPredefined = other.getIsPredefined();
-    myIsShownOnFirstTab = other.getIsShownOnFirstTab();
+    myHidden = other.isHidden();
+    myReadOnly = other.isReadOnly();
+    myShownOnFirstTab = other.isShownOnFirstTab();
   }
 
-  public void setName(String name) {
+  public void setName(@NotNull @NonNls String name) {
     myName = name;
   }
 
-  public void setValue(String value) {
+  public void setValue(@NotNull @NonNls String value) {
     myValue = value;
   }
 
+  @NotNull
   public String getName() {
     return myName;
   }
 
+  @NotNull
   public String getValue() {
     return myValue;
   }
 
-  @Nullable
+  // TODO: actually not used in UI
+  @NotNull
   public String getDescription() {
     return myDescription;
   }
 
-  @Attribute("isPredefined")
-  public boolean getIsPredefined() {
-    return myIsPredefined;
+  public void setDescription(@NotNull @NonNls String description) {
+    myDescription = description;
   }
 
-  public void setIsPredefined(boolean isPredefined) {
-    myIsPredefined = isPredefined;
+  @Attribute("readOnly")
+  public boolean isReadOnly() {
+    return myReadOnly;
   }
 
-  @Attribute("isHidden")
-  public boolean getIsHidden() {
-    return myIsHidden;
+  public void setReadOnly(boolean readOnly) {
+    myReadOnly = readOnly;
   }
 
-  public void setIsHidden(boolean isHidden) {
-    myIsHidden = isHidden;
+  @Attribute("hidden")
+  public boolean isHidden() {
+    return myHidden;
+  }
+
+  public void setHidden(boolean hidden) {
+    myHidden = hidden;
   }
 
   @Attribute("shownOnFirstTab")
-  public boolean getIsShownOnFirstTab() {
-    return myIsShownOnFirstTab;
+  public boolean isShownOnFirstTab() {
+    return myShownOnFirstTab;
   }
 
-  public void setIsShownOnFirstTab(boolean isShownOnFirstTab) {
-    myIsShownOnFirstTab = isShownOnFirstTab;
+  public void setShownOnFirstTab(boolean shownOnFirstTab) {
+    myShownOnFirstTab = shownOnFirstTab;
   }
 
   public TemplateVariable clone() {
     return new TemplateVariable(this);
   }
 
-  public void setDescription(final String description) {
-    myDescription = description;
-  }
-
   @Override
   public String toString() {
     return String.format("TemplateVariable(name='%s', value='%s')", getName(), getValue());
   }
 
-  public static class TemplateVariableBuilder {
-    private String myName;
-    private String myValue = "";
-    private String myDescription;
-    private boolean myIsHidden;
-    private boolean myIsPredefined;
-    private boolean myIsShowOnFirstTab;
-
-    private TemplateVariableBuilder(String name) {
-      myName = name;
-    }
-
-    public TemplateVariableBuilder value(Object value) {
-      myValue = String.valueOf(value);
-      return this;
-    }
-
-    public TemplateVariableBuilder description(String description) {
-      myDescription = description;
-      return this;
-    }
-
-    public TemplateVariableBuilder isHidden(boolean isHidden) {
-      myIsHidden = isHidden;
-      return this;
-    }
-
-    public TemplateVariableBuilder isPredefined(boolean isPredefined) {
-      myIsPredefined = isPredefined;
-      return this;
-    }
-
-    public TemplateVariableBuilder isShownOnFirstTab(boolean isShowOnFirstTab) {
-      myIsShowOnFirstTab = isShowOnFirstTab;
-      return this;
-    }
-
-    public TemplateVariable build() {
-      return new TemplateVariable(this);
-    }
-  }
-
   /**
    * Represents predefined template variable such as "serverUrl", "login" or "password" which are not
    * set explicitly by user but instead taken from repository itself.
+   *
+   * @see GenericRepository
    */
-  public abstract static class PredefinedFactoryVariable extends TemplateVariable {
+  public abstract static class FactoryVariable extends TemplateVariable {
 
-    protected PredefinedFactoryVariable(String name) {
+    protected FactoryVariable(@NotNull @NonNls String name) {
       this(name, false);
     }
 
-    public PredefinedFactoryVariable(String name, boolean isHidden) {
-      this(name, name, isHidden);
+    public FactoryVariable(@NotNull @NonNls String name, boolean hidden) {
+      super(name, "");
+      setHidden(hidden);
     }
 
-    public PredefinedFactoryVariable(String name, String description, boolean isHidden) {
-      super(builder(name).description(description).isHidden(isHidden));
-    }
 
+    @NotNull
     @Override
     public abstract String getValue();
 
     @Override
-    public final void setName(String name) {
+    public final void setName(@NotNull String name) {
       throw new UnsupportedOperationException("Name of predefined variable can't be changed");
     }
 
     @Override
-    public final void setValue(String value) {
+    public final void setValue(@NotNull String value) {
       throw new UnsupportedOperationException("Value of predefined variable can't be changed explicitly");
     }
 
     @Override
-    public final void setIsShownOnFirstTab(boolean isShownOnFirstTab) {
+    public final void setShownOnFirstTab(boolean shownOnFirstTab) {
       throw new UnsupportedOperationException("This parameter can't be changed for predefined variable");
     }
 
     @Override
-    public void setIsPredefined(boolean isPredefined) {
+    public void setReadOnly(boolean readOnly) {
       throw new UnsupportedOperationException("This parameter can't be changed for predefined variable");
     }
 
     @Override
-    public boolean getIsPredefined() {
+    public boolean isReadOnly() {
       return true;
     }
   }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java
index f768258..8d82ac1 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java
@@ -1,10 +1,8 @@
 package com.intellij.tasks.generic;
 
-import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.xmlb.annotations.Tag;
-import org.intellij.lang.xpath.XPathFileType;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
@@ -79,11 +77,7 @@
     return myCompiledCache.get(path);
   }
 
-  @Override
-  public FileType getSelectorFileType() {
-    return XPathFileType.XPATH;
-  }
-
+  @NotNull
   @Override
   public ResponseType getResponseType() {
     return ResponseType.XML;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml
index 942ca6f..94d69c1 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml
@@ -55,8 +55,8 @@
   <option name="tasksListUrl" value="{serverUrl}/projects/{project_ID}/tasks?assignee=me"/>
   <option name="templateVariables">
     <list>
-      <TemplateVariable isHidden="false" isPredefined="false" shownOnFirstTab="true">
-        <option name="description"/>
+      <TemplateVariable hidden="false" readOnly="false" shownOnFirstTab="true">
+        <option name="description" value=""/>
         <option name="name" value="project_ID"/>
         <option name="value" value=""/>
       </TemplateVariable>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml
new file mode 100644
index 0000000..da466a6
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml
@@ -0,0 +1,64 @@
+<Assembla shared="false" url="http://www.assembla.com">
+  <commitMessageFormat>{id} {summary}</commitMessageFormat>
+  <option name="downloadTasksInSeparateRequests" value="false" />
+  <password/>
+  <option name="loginAnonymously" value="false" />
+  <option name="loginMethodType" value="GET" />
+  <option name="loginUrl" value="" />
+  <option name="responseHandlers">
+    <XPathResponseHandler>
+      <selectors>
+        <selector name="tasks" path="/tickets/ticket" />
+        <selector name="id" path="id" />
+        <selector name="summary" path="summary" />
+        <selector name="description" path="description" />
+        <selector name="updated" path="updated-at" />
+        <selector name="created" path="created-on" />
+        <selector name="closed" path="" />
+        <selector name="issueUrl" path="" />
+        <selector name="singleTask-id" path="" />
+        <selector name="singleTask-summary" path="" />
+        <selector name="singleTask-description" path="" />
+        <selector name="singleTask-updated" path="" />
+        <selector name="singleTask-created" path="" />
+        <selector name="singleTask-closed" path="" />
+        <selector name="singleTask-issueUrl" path="" />
+      </selectors>
+    </XPathResponseHandler>
+    <JsonResponseHandler>
+      <selectors>
+        <selector name="tasks" path="" />
+        <selector name="id" path="" />
+        <selector name="summary" path="" />
+        <selector name="description" path="" />
+        <selector name="updated" path="" />
+        <selector name="created" path="" />
+        <selector name="closed" path="" />
+        <selector name="issueUrl" path="" />
+        <selector name="singleTask-id" path="" />
+        <selector name="singleTask-summary" path="" />
+        <selector name="singleTask-description" path="" />
+        <selector name="singleTask-updated" path="" />
+        <selector name="singleTask-created" path="" />
+        <selector name="singleTask-closed" path="" />
+        <selector name="singleTask-issueUrl" path="" />
+      </selectors>
+    </JsonResponseHandler>
+    <RegExResponseHandler>
+      <option name="taskRegex" value=""/>
+    </RegExResponseHandler>
+  </option>
+  <option name="responseType" value="XML" />
+  <option name="shouldFormatCommitMessage" value="false" />
+  <option name="singleTaskMethodType" value="GET" />
+  <option name="singleTaskUrl" value="" />
+  <option name="subtypeName" />
+  <option name="tasksListMethodType" value="GET" />
+  <option name="tasksListUrl" value="http://www.assembla.com/tickets.xml" />
+  <option name="templateVariables">
+    <list />
+  </option>
+  <option name="useHttpAuthentication" value="true" />
+  <option name="useProxy" value="false" />
+  <username/>
+</Assembla>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java
index fde826e..9d9dc91 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java
@@ -15,22 +15,49 @@
  */
 package com.intellij.tasks.jira.jql;
 
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.tree.IElementType;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+import java.lang.reflect.Constructor;
+
 /**
  * @author Mikhail Golubev
  */
 public class JqlElementType extends IElementType {
-  private String myName;
+  private static final Class<?>[] PARAMETER_TYPES = {ASTNode.class};
+
+  private final Class<? extends PsiElement> myClass;
+  private Constructor<? extends PsiElement> myConstructor;
+
   public JqlElementType(@NotNull @NonNls String debugName) {
+    this(debugName, ASTWrapperPsiElement.class);
+  }
+
+  public JqlElementType(@NotNull @NonNls String debugName, @NotNull Class<? extends PsiElement> cls) {
     super(debugName, JqlLanguage.INSTANCE);
-    myName = debugName;
+    myClass = cls;
   }
 
   @Override
   public String toString() {
     return "JQL: " + super.toString();
   }
+
+  @NotNull
+  public PsiElement createElement(@NotNull ASTNode node) {
+    try {
+      if (myConstructor == null) {
+        myConstructor = myClass.getConstructor(PARAMETER_TYPES);
+      }
+      return myConstructor.newInstance(node);
+    }
+    catch (Exception e) {
+      throw new AssertionError(
+        String.format("Class %s must have constructor accepting single ASTNode parameter", myClass.getName()));
+    }
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java
index 68a9893..9919eb6 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java
@@ -3,6 +3,7 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.IFileElementType;
 import com.intellij.psi.tree.TokenSet;
+import com.intellij.tasks.jira.jql.psi.impl.*;
 
 /**
  * @author Mikhail Golubev
@@ -14,8 +15,9 @@
  * or_clause ::= and_clause {or_op and_clause}
  * and_clause ::= not_expr {and_op not_expr}
  * not_expr ::= not_op not_expr
- *            | "(" or_clause ")"
+ *            | subclause
  *            | terminal_clause
+ * subclause ::= "(" or_clause ")"
  * terminal_clause ::= simple_clause
  *                   | was_clause
  *                   | changed_clause
@@ -46,11 +48,12 @@
  * field ::= string
  *         | NUMBER
  *         | CUSTOM_FIELD
- * operand ::= ("empty" | "null")
+ * operand ::= empty
  *           | string
  *           | NUMBER
  *           | func
  *           | list
+ * empty ::= "empty" | "null"
  * list ::= "(" operand {"," operand} ")"
  * func ::= fname "(" arg_list ")"
  * # function name can be even number (!)
@@ -58,7 +61,7 @@
  * arg_list ::= argument {"," argument}
  * argument ::= string | NUMBER
  * string ::= SQUOTED_STRING
- *          | QUOTED_STRIN
+ *          | QUOTED_STRING
  *          | UNQOUTED_STRING
  * order_by ::= "order" "by" sort_key {sort_key}
  * sort_key ::= field ("asc" | "desc")
@@ -66,26 +69,28 @@
  */
 public interface JqlElementTypes {
   IFileElementType FILE = new IFileElementType(JqlLanguage.INSTANCE);
-  IElementType QUERY = new JqlElementType("QUERY");
-  IElementType OR_CLAUSE = new JqlElementType("OR_CLAUSE");
-  IElementType AND_CLAUSE = new JqlElementType("AND_CLAUSE");
-  IElementType NOT_CLAUSE = new JqlElementType("NOT_CLAUSE");
+  IElementType QUERY = new JqlElementType("QUERY", JqlQueryImpl.class);
+  IElementType OR_CLAUSE = new JqlElementType("OR_CLAUSE", JqlOrClauseImpl.class);
+  IElementType AND_CLAUSE = new JqlElementType("AND_CLAUSE", JqlAndClauseImpl.class);
+  IElementType NOT_CLAUSE = new JqlElementType("NOT_CLAUSE", JqlNotClauseImpl.class);
+  // actually parenthesized clause, named so to be consistent with official grammar
+  IElementType SUB_CLAUSE = new JqlElementType("SUB_CLAUSE", JqlSubClauseImpl.class);
   //IElementType TERMINAL_CLAUSE = new JqlElementType("TERMINAL_CLAUSE");
   // field (= | != | ~ | !~ | < | > | <= | >= | is [not] | [not] in) value
-  IElementType SIMPLE_CLAUSE = new JqlElementType("SIMPLE_CLAUSE");
+  IElementType SIMPLE_CLAUSE = new JqlElementType("SIMPLE_CLAUSE", JqlSimpleClauseImpl.class);
   // field was [not] [in] value {history_predicate}
-  IElementType WAS_CLAUSE = new JqlElementType("WAS_CLAUSE");
+  IElementType WAS_CLAUSE = new JqlElementType("WAS_CLAUSE", JqlWasClauseImpl.class);
   // field changed {history_predicate}
-  IElementType CHANGED_CLAUSE = new JqlElementType("CHANGED_CLAUSE");
-  IElementType LIST = new JqlElementType("LIST");
-  IElementType ORDER_BY = new JqlElementType("ORDER_BY");
-  IElementType IDENTIFIER = new JqlElementType("IDENTIFIER");
-  IElementType LITERAL = new JqlElementType("LITERAL");
-  IElementType FUNCTION_CALL = new JqlElementType("FUNCTION_CALL");
-  IElementType ARGUMENT_LIST = new JqlElementType("ARGUMENT_LIST");
-  IElementType SORT_KEY = new JqlElementType("SORT_KEY");
-  IElementType EMPTY = new JqlElementType("EMPTY");
-  IElementType HISTORY_PREDICATE = new JqlElementType("HISTORY_PREDICATE");
+  IElementType CHANGED_CLAUSE = new JqlElementType("CHANGED_CLAUSE", JqlChangedClauseImpl.class);
+  IElementType LIST = new JqlElementType("LIST", JqlListImpl.class);
+  IElementType ORDER_BY = new JqlElementType("ORDER_BY", JqlOrderByImpl.class);
+  IElementType IDENTIFIER = new JqlElementType("IDENTIFIER", JqlIdentifierImpl.class);
+  IElementType LITERAL = new JqlElementType("LITERAL", JqlLiteralImpl.class);
+  IElementType FUNCTION_CALL = new JqlElementType("FUNCTION_CALL", JqlFunctionCallImpl.class);
+  IElementType ARGUMENT_LIST = new JqlElementType("ARGUMENT_LIST", JqlArgumentListImpl.class);
+  IElementType SORT_KEY = new JqlElementType("SORT_KEY", JqlSortKeyImpl.class);
+  IElementType EMPTY = new JqlElementType("EMPTY", JqlEmptyValueImpl.class);
+  IElementType HISTORY_PREDICATE = new JqlElementType("HISTORY_PREDICATE", JqlHistoryPredicateImpl.class);
 
   TokenSet OPERAND_NODES = TokenSet.create(
     JqlTokenTypes.NUMBER_LITERAL, JqlTokenTypes.STRING_LITERAL, LIST, FUNCTION_CALL
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParser.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParser.java
index 1dcac36..2021bc9 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParser.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParser.java
@@ -12,7 +12,7 @@
  * @author Mikhail Golubev
  */
 public class JqlParser implements PsiParser {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.jira.jql.JqlParser");
+  private static final Logger LOG = Logger.getInstance(JqlParser.class);
 
   @NotNull
   @Override
@@ -92,16 +92,17 @@
   }
 
   private boolean parseSubClause(PsiBuilder builder) {
+    LOG.assertTrue(builder.getTokenType() == JqlTokenTypes.LPAR);
+    PsiBuilder.Marker marker = builder.mark();
     if (!advanceIfMatches(builder, JqlTokenTypes.LPAR)) {
+      marker.drop();
       return false;
     }
-    if (!parseORClause(builder)) {
-      return false;
-    }
+    parseORClause(builder);
     if (!advanceIfMatches(builder, JqlTokenTypes.RPAR)) {
       builder.error("Expecting ')'");
-      return false;
     }
+    marker.done(JqlElementTypes.SUB_CLAUSE);
     return true;
   }
 
@@ -142,6 +143,7 @@
   }
 
   private void parseCHANGEDClause(PsiBuilder builder) {
+    LOG.assertTrue(builder.getTokenType() == JqlTokenTypes.CHANGED_KEYWORD);
     if (!advanceIfMatches(builder, JqlTokenTypes.CHANGED_KEYWORD)) {
       return;
     }
@@ -151,6 +153,7 @@
   }
 
   private void parseWASClause(PsiBuilder builder) {
+    LOG.assertTrue(builder.getTokenType() == JqlTokenTypes.WAS_KEYWORD);
     if (!advanceIfMatches(builder, JqlTokenTypes.WAS_KEYWORD)) {
       return;
     }
@@ -163,6 +166,7 @@
   }
 
   private void parseHistoryPredicate(PsiBuilder builder) {
+    LOG.assertTrue(JqlTokenTypes.HISTORY_PREDICATES.contains(builder.getTokenType()));
     PsiBuilder.Marker marker = builder.mark();
     if (!advanceIfMatches(builder, JqlTokenTypes.HISTORY_PREDICATES)) {
       marker.drop();
@@ -204,6 +208,7 @@
   }
 
   private boolean parseList(PsiBuilder builder) {
+    LOG.assertTrue(builder.getTokenType() == JqlTokenTypes.LPAR);
     PsiBuilder.Marker marker = builder.mark();
     if (!advanceIfMatches(builder, JqlTokenTypes.LPAR)) {
       marker.drop();
@@ -235,6 +240,7 @@
   }
 
   private void parseArgumentList(PsiBuilder builder) {
+    LOG.assertTrue(builder.getTokenType() == JqlTokenTypes.LPAR);
     PsiBuilder.Marker marker = builder.mark();
     if (!advanceIfMatches(builder, JqlTokenTypes.LPAR)) {
       marker.drop();
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java
index 7e3eb55..a826962 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java
@@ -13,7 +13,6 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.IFileElementType;
 import com.intellij.psi.tree.TokenSet;
-import com.intellij.tasks.jira.jql.psi.impl.*;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -59,54 +58,9 @@
   @NotNull
   @Override
   public PsiElement createElement(ASTNode node) {
-    IElementType type = node.getElementType();
-    if (type == JqlElementTypes.QUERY) {
-      return new JqlQueryImpl(node);
-    }
-    if (type == JqlElementTypes.AND_CLAUSE) {
-      return new JqlAndClauseImpl(node);
-    }
-    if (type == JqlElementTypes.OR_CLAUSE) {
-      return new JqlOrClauseImpl(node);
-    }
-    if (type == JqlElementTypes.NOT_CLAUSE) {
-      return new JqlNotClauseImpl(node);
-    }
-    if (type == JqlElementTypes.SIMPLE_CLAUSE) {
-      return new JqlSimpleClauseImpl(node);
-    }
-    if (type == JqlElementTypes.WAS_CLAUSE) {
-      return new JqlWasClauseImpl(node);
-    }
-    if (type == JqlElementTypes.CHANGED_CLAUSE) {
-      return new JqlChangedClauseImpl(node);
-    }
-    if (type == JqlElementTypes.FUNCTION_CALL) {
-      return new JqlFunctionCallImpl(node);
-    }
-    if (type == JqlElementTypes.IDENTIFIER) {
-      return new JqlIdentifierImpl(node);
-    }
-    if (type == JqlElementTypes.HISTORY_PREDICATE) {
-      return new JqlHistoryPredicateImpl(node);
-    }
-    if (type == JqlElementTypes.ARGUMENT_LIST) {
-      return new JqlArgumentListImpl(node);
-    }
-    if (type == JqlElementTypes.LITERAL) {
-      return new JqlLiteralImpl(node);
-    }
-    if (type == JqlElementTypes.EMPTY) {
-      return new JqlEmptyValueImpl(node);
-    }
-    if (type == JqlElementTypes.LIST) {
-      return new JqlListImpl(node);
-    }
-    if (type == JqlElementTypes.SORT_KEY) {
-      return new JqlSortKeyImpl(node);
-    }
-    if (type == JqlElementTypes.ORDER_BY) {
-      return new JqlOrderByImpl(node);
+    final IElementType type = node.getElementType();
+    if (type instanceof JqlElementType) {
+      return ((JqlElementType)type).createElement(node);
     }
     return new ASTWrapperPsiElement(node);
   }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java
index 1d0c6f1..ddb8bdf 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java
@@ -104,12 +104,6 @@
   TokenSet HISTORY_PREDICATES = TokenSet.create(
     ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, FROM_KEYWORD, TO_KEYWORD, BY_KEYWORD
   );
-  TokenSet WAS_CONSTRAINTS = TokenSet.create(
-    ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, BY_KEYWORD
-  );
-  TokenSet CHANGED_CONSTRAINTS = TokenSet.create(
-    ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, FROM_KEYWORD, TO_KEYWORD, BY_KEYWORD
-  );
   TokenSet SORT_ORDERS = TokenSet.create(ASC_KEYWORD, DESC_KEYWORD);
   TokenSet EMPTY_VALUES = TokenSet.create(EMPTY_KEYWORD, NULL_KEYWORD);
   TokenSet LITERALS = TokenSet.create(NUMBER_LITERAL, STRING_LITERAL);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlCompletionContributor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlCompletionContributor.java
index 484a357bc..e243402 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlCompletionContributor.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlCompletionContributor.java
@@ -55,15 +55,15 @@
         if (!(element instanceof PsiElement)) return false;
         PsiElement prevLeaf = PsiTreeUtil.prevVisibleLeaf((PsiElement)element);
         if (prevLeaf == null) return false;
-        PsiElement enclosingClause = PsiTreeUtil.findFirstParent(prevLeaf, new Condition<PsiElement>() {
+        PsiElement parent = PsiTreeUtil.findFirstParent(prevLeaf, new Condition<PsiElement>() {
           @Override
           public boolean value(PsiElement element) {
             return pattern.accepts(element);
           }
         });
-        if (enclosingClause == null) return false;
-        if (PsiTreeUtil.hasErrorElements(enclosingClause)) return false;
-        return prevLeaf.getTextRange().getEndOffset() == enclosingClause.getTextRange().getEndOffset();
+        if (parent == null) return false;
+        if (PsiTreeUtil.hasErrorElements(parent)) return false;
+        return prevLeaf.getTextRange().getEndOffset() == parent.getTextRange().getEndOffset();
       }
 
       @Override
@@ -83,7 +83,10 @@
     psiElement().and(rightAfterElement(JqlClauseWithHistoryPredicates.class));
 
   private static final PsiElementPattern.Capture<PsiElement> AFTER_ANY_CLAUSE =
-    psiElement().and(rightAfterElement(JqlTerminalClause.class));
+    psiElement().andOr(
+      rightAfterElement(JqlTerminalClause.class),
+      // in other words after closing parenthesis
+      rightAfterElement(JqlSubClause.class));
 
   private static final PsiElementPattern.Capture<PsiElement> AFTER_ORDER_KEYWORD =
     psiElement().afterLeaf(psiElement(JqlTokenTypes.ORDER_KEYWORD));
@@ -263,7 +266,6 @@
       JqlFieldType operandType;
       boolean listFunctionExpected;
       PsiElement curElem = parameters.getPosition();
-      PsiElement origElem = parameters.getOriginalPosition();
       JqlHistoryPredicate predicate = PsiTreeUtil.getParentOfType(curElem, JqlHistoryPredicate.class);
       if (predicate != null) {
         listFunctionExpected = false;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlElementVisitor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlElementVisitor.java
index e0dc689..bbf71de 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlElementVisitor.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlElementVisitor.java
@@ -3,6 +3,7 @@
 import com.intellij.psi.PsiElementVisitor;
 import com.intellij.tasks.jira.jql.psi.impl.JqlArgumentListImpl;
 import com.intellij.tasks.jira.jql.psi.impl.JqlHistoryPredicateImpl;
+import com.intellij.tasks.jira.jql.psi.impl.JqlSubClauseImpl;
 
 /**
  * @author Mikhail Golubev
@@ -40,4 +41,6 @@
   public abstract void visitJqlArgumentList(JqlArgumentListImpl list);
 
   public abstract void visitJqlHistoryPredicate(JqlHistoryPredicateImpl predicate);
+
+  public abstract void visitJqlSubClause(JqlSubClauseImpl subClause);
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlQuery.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlQuery.java
index b832b9d..79bb3bf 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlQuery.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlQuery.java
@@ -9,7 +9,7 @@
 public interface JqlQuery extends JqlElement {
   @Nullable
   JqlClause getClause();
-  boolean isOrdered();
-  @NotNull
-  JqlSortKey[] getOrderKeys();
+
+  @Nullable
+  JqlOrderBy getOrderBy();
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlSubClause.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlSubClause.java
new file mode 100644
index 0000000..c28de28
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlSubClause.java
@@ -0,0 +1,11 @@
+package com.intellij.tasks.jira.jql.psi;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Mikhail Golubev
+ */
+public interface JqlSubClause extends JqlClause {
+  @Nullable
+  JqlClause getInnerClause();
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlTerminalClause.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlTerminalClause.java
index d16a106..f440161 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlTerminalClause.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/JqlTerminalClause.java
@@ -10,7 +10,7 @@
 /**
  * @author Mikhail Golubev
  */
-public interface JqlTerminalClause extends JqlElement {
+public interface JqlTerminalClause extends JqlClause {
   enum Type {
     EQ(false),
     NE(false),
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlQueryImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlQueryImpl.java
index c9ed11a..0565800 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlQueryImpl.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlQueryImpl.java
@@ -1,11 +1,9 @@
 package com.intellij.tasks.jira.jql.psi.impl;
 
 import com.intellij.lang.ASTNode;
-import com.intellij.tasks.jira.jql.psi.JqlClause;
-import com.intellij.tasks.jira.jql.psi.JqlElementVisitor;
-import com.intellij.tasks.jira.jql.psi.JqlSortKey;
-import com.intellij.tasks.jira.jql.psi.JqlQuery;
+import com.intellij.tasks.jira.jql.psi.*;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author Mikhail Golubev
@@ -25,13 +23,9 @@
     return findChildByClass(JqlClause.class);
   }
 
+  @Nullable
   @Override
-  public boolean isOrdered() {
-    return getOrderKeys().length != 0;
-  }
-
-  @Override
-  public JqlSortKey[] getOrderKeys() {
-    return findChildrenByClass(JqlSortKey.class);
+  public JqlOrderBy getOrderBy() {
+    return findChildByClass(JqlOrderBy.class);
   }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlSubClauseImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlSubClauseImpl.java
new file mode 100644
index 0000000..05f959a
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/psi/impl/JqlSubClauseImpl.java
@@ -0,0 +1,28 @@
+package com.intellij.tasks.jira.jql.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.tasks.jira.jql.psi.JqlClause;
+import com.intellij.tasks.jira.jql.psi.JqlElementVisitor;
+import com.intellij.tasks.jira.jql.psi.JqlSubClause;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class JqlSubClauseImpl extends JqlElementImpl implements JqlSubClause {
+  public JqlSubClauseImpl(@NotNull ASTNode node) {
+    super(node);
+  }
+
+  @Override
+  public void accept(JqlElementVisitor visitor) {
+    visitor.visitJqlSubClause(this);
+  }
+
+  @Nullable
+  @Override
+  public JqlClause getInnerClause() {
+    return findChildByClass(JqlClause.class);
+  }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
index f1571fb..697e71b 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
@@ -185,10 +185,10 @@
     // Ad-hoc fix for IDEA-110012
     Date parsed;
     try {
-      parsed = (new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US)).parse(date);
+      parsed = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US).parse(date);
     }
     catch (ParseException e) {
-      LOG.warn("Unparseable date: " + date, e);
+      LOG.warn("Unparseable date: '" + date + "'. Trying ISO-8601 format instead.");
       parsed = TaskUtil.parseDate(date);
     }
     return parsed;
diff --git a/plugins/tasks/tasks-core/tasks-core.iml b/plugins/tasks/tasks-core/tasks-core.iml
index 11c3bc9..460f43f 100644
--- a/plugins/tasks/tasks-core/tasks-core.iml
+++ b/plugins/tasks/tasks-core/tasks-core.iml
@@ -39,7 +39,6 @@
     <orderEntry type="library" name="gson" level="project" />
     <orderEntry type="module" module-name="xml" />
     <orderEntry type="module" module-name="core-api" />
-    <orderEntry type="module" module-name="xpath" />
     <orderEntry type="module" module-name="RegExpSupport" />
     <orderEntry type="module-library">
       <library>
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java
new file mode 100644
index 0000000..def2a678f2
--- /dev/null
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java
@@ -0,0 +1,51 @@
+package com.intellij.tasks;
+
+import com.intellij.tasks.impl.TaskUtil;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class TaskUtilTest {
+  private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+  static {
+    FORMATTER.setTimeZone(TimeZone.getTimeZone("GMT"));
+  }
+
+  private static void compareDates(@NotNull Date expected, @NotNull String formattedDate) {
+    Date parsed = TaskUtil.parseDate(formattedDate);
+    assertEquals(expected, parsed);
+  }
+
+  /**
+   * Test ISO8601 date parsing
+   */
+  @Test
+  public void testDateParsings() throws Exception {
+    final Date expected = FORMATTER.parse("2013-08-23 10:11:12.000");
+    final Date expectedWithMillis = FORMATTER.parse("2013-08-23 10:11:12.100");
+    // JIRA, Redmine and Pivotal
+    compareDates(expectedWithMillis, "2013-08-23T14:11:12.100+0400");
+    // Trello
+    compareDates(expectedWithMillis, "2013-08-23T10:11:12.100Z");
+    // Assmbla
+    compareDates(expectedWithMillis, "2013-08-23T14:11:12.100+04:00");
+
+    // Formatting variations
+    compareDates(expected, "2013/08/23 10:11:12");
+    compareDates(expectedWithMillis, "2013-08-23 14:11:12.100123+04");
+
+    // Malformed date
+    assertNull(TaskUtil.parseDate("Fri Aug 23 14:11:12 MSK 2013"));
+    assertNull(TaskUtil.parseDate("2013/00/23"));
+    assertNull(TaskUtil.parseDate("2013/08/23 10:11:12 GMT+04:00"));
+  }
+}
\ No newline at end of file
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
index 98a3dd0..029b9a7 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
@@ -17,6 +17,7 @@
 package com.intellij.tasks.context;
 
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.impl.ProjectImpl;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.tasks.TaskManagerTestCase;
 import com.intellij.xdebugger.XDebuggerManager;
@@ -93,6 +94,18 @@
     manager.clearContext();
   }
 
+  public void testContextFileName() throws Exception {
+    ProjectImpl project = (ProjectImpl)getProject();
+    String name = project.getName();
+    try {
+      project.setProjectName("invalid | name");
+      getContextManager().saveContext("foo", "bar");
+    }
+    finally {
+      project.setProjectName(name);
+    }
+  }
+
   private WorkingContextManager getContextManager() {
     return WorkingContextManager.getInstance(getProject());
   }
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/jira/jql/CompletionTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/jira/jql/CompletionTest.java
index d3ee5b1..6269e48 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/jira/jql/CompletionTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/jira/jql/CompletionTest.java
@@ -104,10 +104,14 @@
     checkCompletionVariants(JqlStandardFunction.allOfType(JqlFieldType.DATE, false));
   }
 
-  public void testAfterParenthesisInSubClause() throws Exception {
+  public void testAfterLeftParenthesisInSubClause() throws Exception {
     checkCompletionVariants(ALL_FIELD_NAMES, "not");
   }
 
+  public void testAfterSubClause() throws Exception {
+    checkCompletionVariants("and", "or", "order by");
+  }
+
   public void testFunctionArguments() throws Exception {
     // only literals accepted so we can't assume anything
     checkCompletionVariants(ContainerUtil.<String>emptyList());
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
index 1261d12..36cc584 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
@@ -15,10 +15,17 @@
  */
 package com.intellij.tasks.vcs;
 
+import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsTaskHandler;
+import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.tasks.BranchInfo;
 import com.intellij.tasks.LocalTask;
 import com.intellij.tasks.TaskManager;
+import com.intellij.tasks.actions.OpenTaskDialog;
 import com.intellij.tasks.impl.LocalTaskImpl;
 import com.intellij.tasks.impl.TaskManagerImpl;
 import com.intellij.testFramework.PlatformTestCase;
@@ -29,8 +36,10 @@
 import git4idea.repo.GitRepository;
 import git4idea.test.GitExecutor;
 import git4idea.test.GitTestUtil;
+import git4idea.util.GitFileUtils;
 
 import java.io.File;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -41,6 +50,8 @@
 public class TaskBranchesTest extends PlatformTestCase {
 
   private TaskManagerImpl myTaskManager;
+  private ChangeListManagerImpl myChangeListManager;
+  private VcsDirtyScopeManagerImpl myDirtyScopeManager;
 
   public void testGitTaskHandler() throws Exception {
 
@@ -104,6 +115,46 @@
     myTaskManager.activateTask(foo, false);
   }
 
+  public void testCommit() throws Exception {
+    GitRepository repository = initRepository("foo");
+    LocalTask defaultTask = myTaskManager.getActiveTask();
+    LocalTaskImpl foo = myTaskManager.createLocalTask("foo");
+    final LocalTask localTask = myTaskManager.activateTask(foo, false);
+    myTaskManager.createBranch(localTask, defaultTask, myTaskManager.suggestBranchName(localTask));
+
+    VirtualFile root = repository.getRoot();
+    File file = new File(root.getPath(), "foo.txt");
+    assertTrue(file.createNewFile());
+    final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+    GitFileUtils.addFiles(getProject(), root, virtualFile);
+    myDirtyScopeManager.fileDirty(virtualFile);
+    myChangeListManager.ensureUpToDate(false);
+    Change change = myChangeListManager.getChange(virtualFile);
+    assertNotNull(change);
+    ProjectLevelVcsManager.getInstance(getProject()).getAllActiveVcss()[0].getCheckinEnvironment()
+      .commit(Collections.singletonList(change), "foo");
+    myTaskManager.mergeBranch(localTask);
+
+    repository.update();
+    assertEquals("master", repository.getCurrentBranch().getName());
+    assertEquals(1, repository.getBranches().getLocalBranches().size());
+  }
+
+  public void testOpenTaskDialog() throws Exception {
+    initRepository("foo");
+    LocalTaskImpl task = myTaskManager.createLocalTask("foo");
+    OpenTaskDialog dialog = new OpenTaskDialog(getProject(), task);
+    Disposer.register(myTestRootDisposable, dialog.getDisposable());
+    dialog.createTask();
+    assertEquals("foo", myTaskManager.getActiveTask().getSummary());
+    List<BranchInfo> branches = task.getBranches(true);
+    assertEquals(1, branches.size());
+    assertEquals("master", branches.get(0).name);
+    branches = task.getBranches(false);
+    assertEquals(1, branches.size());
+    assertEquals("foo", branches.get(0).name);
+  }
+
   private List<GitRepository> initRepositories(String... names) {
     return ContainerUtil.map(names, new Function<String, GitRepository>() {
       @Override
@@ -128,5 +179,10 @@
     super.setUp();
     myTaskManager = (TaskManagerImpl)TaskManager.getManager(getProject());
     GitVcsSettings.getInstance(myProject).getAppSettings().setPathToGit(GitExecutor.GIT_EXECUTABLE);
+
+    myChangeListManager = (ChangeListManagerImpl)ChangeListManager.getInstance(getProject());
+    myChangeListManager.projectOpened();
+    myDirtyScopeManager = ((VcsDirtyScopeManagerImpl)VcsDirtyScopeManager.getInstance(getProject()));
+    myDirtyScopeManager.projectOpened();
   }
 }
diff --git a/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterParenthesisInSubClause.jql b/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterLeftParenthesisInSubClause.jql
similarity index 100%
rename from plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterParenthesisInSubClause.jql
rename to plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterLeftParenthesisInSubClause.jql
diff --git a/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterSubClause.jql b/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterSubClause.jql
new file mode 100644
index 0000000..d2ce0ae
--- /dev/null
+++ b/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterSubClause.jql
@@ -0,0 +1 @@
+(reporter was in (bob, mark)) <caret>
\ No newline at end of file
diff --git a/plugins/tasks/tasks-tests/testData/jira/jql/psi/Subclauses.txt b/plugins/tasks/tasks-tests/testData/jira/jql/psi/Subclauses.txt
index d004bc4..3ec6387 100644
--- a/plugins/tasks/tasks-tests/testData/jira/jql/psi/Subclauses.txt
+++ b/plugins/tasks/tasks-tests/testData/jira/jql/psi/Subclauses.txt
@@ -1,46 +1,50 @@
 FILE(0,50)
   JqlQuery((a = foo or (b > 12 and ((c < 40)))) and d ~ 'foo')(0,50)
     JqlAndClause((a = foo or (b > 12 and ((c < 40)))) and d ~ 'foo')(0,50)
-      PsiElement(JQL: LPAR)('(')(0,1)
-      JqlOrClause(a = foo or (b > 12 and ((c < 40))))(1,35)
-        JqlSimpleClause(a = foo)(1,8)
-          JqlIdentifier(a)(1,2)
-            PsiElement(JQL: STRING_LITERAL)('a')(1,2)
-          PsiWhiteSpace(' ')(2,3)
-          PsiElement(JQL: EQ)('=')(3,4)
-          PsiWhiteSpace(' ')(4,5)
-          JqlLiteral(foo)(5,8)
-            PsiElement(JQL: STRING_LITERAL)('foo')(5,8)
-        PsiWhiteSpace(' ')(8,9)
-        PsiElement(JQL: OR_KEYWORD)('or')(9,11)
-        PsiWhiteSpace(' ')(11,12)
-        PsiElement(JQL: LPAR)('(')(12,13)
-        JqlAndClause(b > 12 and ((c < 40)))(13,34)
-          JqlSimpleClause(b > 12)(13,19)
-            JqlIdentifier(b)(13,14)
-              PsiElement(JQL: STRING_LITERAL)('b')(13,14)
-            PsiWhiteSpace(' ')(14,15)
-            PsiElement(JQL: GT)('>')(15,16)
-            PsiWhiteSpace(' ')(16,17)
-            JqlLiteral(12)(17,19)
-              PsiElement(JQL: NUMBER_LITERAL)('12')(17,19)
-          PsiWhiteSpace(' ')(19,20)
-          PsiElement(JQL: AND_KEYWORD)('and')(20,23)
-          PsiWhiteSpace(' ')(23,24)
-          PsiElement(JQL: LPAR)('(')(24,25)
-          PsiElement(JQL: LPAR)('(')(25,26)
-          JqlSimpleClause(c < 40)(26,32)
-            JqlIdentifier(c)(26,27)
-              PsiElement(JQL: STRING_LITERAL)('c')(26,27)
-            PsiWhiteSpace(' ')(27,28)
-            PsiElement(JQL: LT)('<')(28,29)
-            PsiWhiteSpace(' ')(29,30)
-            JqlLiteral(40)(30,32)
-              PsiElement(JQL: NUMBER_LITERAL)('40')(30,32)
-          PsiElement(JQL: RPAR)(')')(32,33)
-          PsiElement(JQL: RPAR)(')')(33,34)
-        PsiElement(JQL: RPAR)(')')(34,35)
-      PsiElement(JQL: RPAR)(')')(35,36)
+      JqlSubClause((a = foo or (b > 12 and ((c < 40)))))(0,36)
+        PsiElement(JQL: LPAR)('(')(0,1)
+        JqlOrClause(a = foo or (b > 12 and ((c < 40))))(1,35)
+          JqlSimpleClause(a = foo)(1,8)
+            JqlIdentifier(a)(1,2)
+              PsiElement(JQL: STRING_LITERAL)('a')(1,2)
+            PsiWhiteSpace(' ')(2,3)
+            PsiElement(JQL: EQ)('=')(3,4)
+            PsiWhiteSpace(' ')(4,5)
+            JqlLiteral(foo)(5,8)
+              PsiElement(JQL: STRING_LITERAL)('foo')(5,8)
+          PsiWhiteSpace(' ')(8,9)
+          PsiElement(JQL: OR_KEYWORD)('or')(9,11)
+          PsiWhiteSpace(' ')(11,12)
+          JqlSubClause((b > 12 and ((c < 40))))(12,35)
+            PsiElement(JQL: LPAR)('(')(12,13)
+            JqlAndClause(b > 12 and ((c < 40)))(13,34)
+              JqlSimpleClause(b > 12)(13,19)
+                JqlIdentifier(b)(13,14)
+                  PsiElement(JQL: STRING_LITERAL)('b')(13,14)
+                PsiWhiteSpace(' ')(14,15)
+                PsiElement(JQL: GT)('>')(15,16)
+                PsiWhiteSpace(' ')(16,17)
+                JqlLiteral(12)(17,19)
+                  PsiElement(JQL: NUMBER_LITERAL)('12')(17,19)
+              PsiWhiteSpace(' ')(19,20)
+              PsiElement(JQL: AND_KEYWORD)('and')(20,23)
+              PsiWhiteSpace(' ')(23,24)
+              JqlSubClause(((c < 40)))(24,34)
+                PsiElement(JQL: LPAR)('(')(24,25)
+                JqlSubClause((c < 40))(25,33)
+                  PsiElement(JQL: LPAR)('(')(25,26)
+                  JqlSimpleClause(c < 40)(26,32)
+                    JqlIdentifier(c)(26,27)
+                      PsiElement(JQL: STRING_LITERAL)('c')(26,27)
+                    PsiWhiteSpace(' ')(27,28)
+                    PsiElement(JQL: LT)('<')(28,29)
+                    PsiWhiteSpace(' ')(29,30)
+                    JqlLiteral(40)(30,32)
+                      PsiElement(JQL: NUMBER_LITERAL)('40')(30,32)
+                  PsiElement(JQL: RPAR)(')')(32,33)
+                PsiElement(JQL: RPAR)(')')(33,34)
+            PsiElement(JQL: RPAR)(')')(34,35)
+        PsiElement(JQL: RPAR)(')')(35,36)
       PsiWhiteSpace(' ')(36,37)
       PsiElement(JQL: AND_KEYWORD)('and')(37,40)
       PsiWhiteSpace(' ')(40,41)
diff --git a/plugins/terminal/lib/jediterm-pty-0.08.jar b/plugins/terminal/lib/jediterm-pty-0.08.jar
index 0e3c223..f4bd386 100644
--- a/plugins/terminal/lib/jediterm-pty-0.08.jar
+++ b/plugins/terminal/lib/jediterm-pty-0.08.jar
Binary files differ
diff --git a/plugins/terminal/lib/pty4j-0.3.jar b/plugins/terminal/lib/pty4j-0.3.jar
index 67200e1..3c7f3db 100644
--- a/plugins/terminal/lib/pty4j-0.3.jar
+++ b/plugins/terminal/lib/pty4j-0.3.jar
Binary files differ
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
index c1ceb92..fcf0627 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
@@ -1,5 +1,6 @@
 package org.jetbrains.plugins.terminal;
 
+import com.google.common.base.Predicate;
 import com.intellij.execution.ExecutionManager;
 import com.intellij.execution.Executor;
 import com.intellij.execution.executors.DefaultRunExecutor;
@@ -8,30 +9,22 @@
 import com.intellij.execution.ui.actions.CloseAction;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.keymap.KeymapManager;
 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.ui.Messages;
-import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.openapi.wm.ToolWindow;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.util.ui.UIUtil;
-import com.jediterm.pty.PtyProcessTtyConnector;
 import com.jediterm.terminal.TtyConnector;
-import com.jediterm.terminal.emulator.ColorPalette;
-import com.jediterm.terminal.ui.AbstractSystemSettingsProvider;
 import com.jediterm.terminal.ui.TerminalSession;
 import com.jediterm.terminal.ui.TerminalWidget;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -90,9 +83,14 @@
   protected abstract ProcessHandler createProcessHandler(T process);
 
   public JBTabbedTerminalWidget createTerminalWidget() {
-    JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
-    JBTabbedTerminalWidget terminalWidget = new JBTabbedTerminalWidget(provider);
-    provider.setTerminalWidget(terminalWidget);
+    final JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
+    JBTabbedTerminalWidget terminalWidget = new JBTabbedTerminalWidget(provider, new Predicate<TerminalWidget>() {
+      @Override
+      public boolean apply(TerminalWidget widget) {
+        openSession(widget);
+        return true;
+      }
+    });
     openSession(terminalWidget);
     return terminalWidget;
   }
@@ -102,9 +100,14 @@
     final DefaultActionGroup toolbarActions = new DefaultActionGroup();
     final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false);
 
-    JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
-    TerminalWidget widget = new JBTabbedTerminalWidget(provider);
-    provider.setTerminalWidget(widget);
+    final JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
+    TerminalWidget widget = new JBTabbedTerminalWidget(provider, new Predicate<TerminalWidget>() {
+      @Override
+      public boolean apply(TerminalWidget widget) {
+        openSession(widget);
+        return true;
+      }
+    });
 
     openSession(widget, createTtyConnector(process));
 
@@ -160,57 +163,6 @@
     return myProject;
   }
 
-  private class JBTerminalSystemSettingsProvider extends AbstractSystemSettingsProvider {
-    private TerminalWidget myTerminalWidget;
-
-    public void setTerminalWidget(TerminalWidget terminalWidget) {
-      myTerminalWidget = terminalWidget;
-    }
-
-    @Override
-    public AbstractAction getNewSessionAction() {
-      return new AbstractAction("New Session") {
-        @Override
-        public void actionPerformed(ActionEvent event) {
-          openSession(myTerminalWidget);
-        }
-      };
-    }
-
-    @Override
-    public KeyStroke[] getCopyKeyStrokes() {
-      return getKeyStrokesByActionId("$Copy");
-    }
-
-    @Override
-    public KeyStroke[] getPasteKeyStrokes() {
-      return getKeyStrokesByActionId("$Paste");
-    }
-
-    @Override
-    public ColorPalette getPalette() {
-      return SystemInfo.isWindows ? ColorPalette.WINDOWS_PALETTE : ColorPalette.XTERM_PALETTE;
-    }
-
-    private KeyStroke[] getKeyStrokesByActionId(String actionId) {
-      List<KeyStroke> keyStrokes = new ArrayList<KeyStroke>();
-      Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(actionId);
-      for (Shortcut sc : shortcuts) {
-        if (sc instanceof KeyboardShortcut) {
-          KeyStroke ks = ((KeyboardShortcut)sc).getFirstKeyStroke();
-          keyStrokes.add(ks);
-        }
-      }
-
-      return keyStrokes.toArray(new KeyStroke[keyStrokes.size()]);
-    }
-
-    @Override
-    public boolean shouldCloseTabOnLogout(TtyConnector ttyConnector) {
-      return ttyConnector instanceof PtyProcessTtyConnector; //close tab only on logout of local pty, not remote
-    }
-  }
-
   public void openSession(TerminalWidget terminalWidget) {
     // Create Server process
     try {
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java
index 051a5a5..50a7e41 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java
@@ -1,12 +1,14 @@
 package org.jetbrains.plugins.terminal;
 
+import com.google.common.base.Predicate;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.jediterm.terminal.ui.JediTermWidget;
-import com.jediterm.terminal.ui.SystemSettingsProvider;
 import com.jediterm.terminal.ui.TabbedTerminalWidget;
 import com.jediterm.terminal.ui.TerminalAction;
+import com.jediterm.terminal.ui.TerminalWidget;
+import com.jediterm.terminal.ui.settings.SettingsProvider;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -17,8 +19,9 @@
  * @author traff
  */
 public class JBTabbedTerminalWidget extends TabbedTerminalWidget {
-  public JBTabbedTerminalWidget(@NotNull SystemSettingsProvider settingsProvider) {
-    super(settingsProvider);
+
+  public JBTabbedTerminalWidget(@NotNull SettingsProvider settingsProvider, @NotNull Predicate<TerminalWidget> createNewSessionAction) {
+    super(settingsProvider, createNewSessionAction);
 
     convertActions(this, getActions());
   }
@@ -28,12 +31,7 @@
       AnAction a = new DumbAwareAction() {
         @Override
         public void actionPerformed(AnActionEvent e) {
-          if (e.getInputEvent() instanceof KeyEvent) {
-            action.perform((KeyEvent)e.getInputEvent());
-          }
-          else {
-            action.perform(null);
-          }
+          action.perform(e.getInputEvent() instanceof KeyEvent? (KeyEvent)e.getInputEvent() : null);
         }
       };
       a.registerCustomShortcutSet(action.getKeyCode(), action.getModifiers(), component);
@@ -41,7 +39,7 @@
   }
 
   @Override
-  protected JediTermWidget createInnerTerminalWidget() {
-    return new JBTerminalWidget(getSystemSettingsProvider());
+  protected JediTermWidget createInnerTerminalWidget(SettingsProvider settingsProvider) {
+    return new JBTerminalWidget(settingsProvider);
   }
 }
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
index e5b6e53..788a4f9 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
@@ -22,17 +22,14 @@
 
 package org.jetbrains.plugins.terminal;
 
-import com.intellij.openapi.editor.colors.EditorColors;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.util.JBHiDPIScaledImage;
 import com.intellij.util.ui.GraphicsUtil;
 import com.intellij.util.ui.UIUtil;
-import com.jediterm.terminal.TerminalColor;
-import com.jediterm.terminal.TextStyle;
 import com.jediterm.terminal.display.BackBuffer;
 import com.jediterm.terminal.display.StyleState;
-import com.jediterm.terminal.ui.SystemSettingsProvider;
 import com.jediterm.terminal.ui.TerminalPanel;
+import com.jediterm.terminal.ui.settings.SettingsProvider;
 import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
@@ -41,69 +38,57 @@
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
 import java.io.IOException;
-import java.util.List;
 
 public class JBTerminalPanel extends TerminalPanel {
-  private final EditorColorsScheme myColorScheme;
-
-  public JBTerminalPanel(@NotNull SystemSettingsProvider settingsProvider,
+  public JBTerminalPanel(@NotNull SettingsProvider settingsProvider,
                          @NotNull BackBuffer backBuffer,
-                         @NotNull StyleState styleState,
-                         @NotNull EditorColorsScheme scheme) {
+                         @NotNull StyleState styleState) {
     super(settingsProvider, backBuffer, styleState);
-    myColorScheme = scheme;
 
-
-    styleState.setDefaultStyle(new TextStyle(TerminalColor.awt(myColorScheme.getDefaultForeground()), TerminalColor.awt(
-      myColorScheme.getDefaultBackground())));
-
-    setSelectionColor(new TextStyle(TerminalColor.awt(myColorScheme.getColor(EditorColors.SELECTION_FOREGROUND_COLOR)),
-                                    TerminalColor.awt(myColorScheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR))));
-
-    setLineSpace(myColorScheme.getConsoleLineSpacing());
-    
     JBTabbedTerminalWidget.convertActions(this, getActions());
   }
 
-  protected Font createFont() {
-
-    Font normalFont = Font.decode(getFontName());
-
-    if (normalFont == null) {
-      normalFont = super.createFont();
-    }
-
-    normalFont = normalFont.deriveFont((float)myColorScheme.getConsoleFontSize());
-
-    return normalFont;
-  }
-
   protected void setupAntialiasing(Graphics graphics, boolean antialiasing) {
     GraphicsUtil.setupAntialiasing(graphics, antialiasing, false);
   }
 
   @Override
-  public Color getBackground() {
-    if (myColorScheme != null) {
-      return myColorScheme.getDefaultBackground();
-    }
-    return super.getBackground();
-  }
-
-  @Override
-  public Color getForeground() {
-    if (myColorScheme != null) {
-      return myColorScheme.getDefaultForeground();
-    }
-    return super.getBackground();
-  }
-
-  @Override
   protected void setCopyContents(StringSelection selection) {
     CopyPasteManager.getInstance().setContents(selection);
   }
 
+  @Override
+  protected void drawImage(Graphics2D gfx, BufferedImage image, int x, int y, ImageObserver observer) {
+    UIUtil.drawImage(gfx, image, x, y, observer);
+  }
+
+  @Override
+  protected void drawImage(Graphics2D g, BufferedImage image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
+    drawImage(g, image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
+  }
+
+  public static void drawImage(Graphics g, Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+    if (image instanceof JBHiDPIScaledImage) {
+      final Graphics2D newG = (Graphics2D)g.create(0, 0, image.getWidth(observer), image.getHeight(observer));
+      newG.scale(0.5, 0.5);
+      Image img = ((JBHiDPIScaledImage)image).getDelegate();
+      if (img == null) {
+        img = image;
+      }
+      newG.drawImage(img, 2*dx1, 2*dy1, 2*dx2, 2*dy2, sx1, sy1, sx2, sy2, observer);
+      newG.scale(1, 1);
+      newG.dispose();
+    } else {
+      g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
+    }
+  }
+
+  @Override
+  protected boolean isRetina() {
+    return UIUtil.isRetina();
+  }
 
   @Override
   protected String getClipboardContent() throws IOException, UnsupportedFlavorException {
@@ -118,28 +103,5 @@
   protected BufferedImage createBufferedImage(int width, int height) {
     return UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB);
   }
-  
-  @Override
-  protected void drawImage(Graphics2D g, BufferedImage image) {
-    UIUtil.drawImage(g, image, null, 0, 0);
-  } 
-
-  public String getFontName() {
-    List<String> fonts = myColorScheme.getConsoleFontPreferences().getEffectiveFontFamilies();
-
-    for (String font : fonts) {
-      if (isApplicable(font)) {
-        return font;
-      }
-    }
-    return super.getFontName();
-  }
-
-  private static boolean isApplicable(String font) {
-    if ("Source Code Pro".equals(font)) {
-      return false;
-    }
-    return true;
-  }
 }
 
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java
new file mode 100644
index 0000000..3b983e2
--- /dev/null
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java
@@ -0,0 +1,367 @@
+package org.jetbrains.plugins.terminal;
+
+import com.intellij.application.options.OptionsConstants;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
+import com.intellij.openapi.actionSystem.Shortcut;
+import com.intellij.openapi.editor.colors.*;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.openapi.options.FontSize;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.util.containers.HashMap;
+import com.jediterm.pty.PtyProcessTtyConnector;
+import com.jediterm.terminal.TerminalColor;
+import com.jediterm.terminal.TextStyle;
+import com.jediterm.terminal.TtyConnector;
+import com.jediterm.terminal.emulator.ColorPalette;
+import com.jediterm.terminal.ui.settings.DefaultSettingsProvider;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author traff
+ */
+class JBTerminalSystemSettingsProvider extends DefaultSettingsProvider {
+
+  private final EditorColorsScheme myColorScheme;
+
+  JBTerminalSystemSettingsProvider() {
+    myColorScheme = getColorScheme();
+  }
+
+  @Override
+  public KeyStroke[] getCopyKeyStrokes() {
+    return getKeyStrokesByActionId("$Copy");
+  }
+
+  @Override
+  public KeyStroke[] getPasteKeyStrokes() {
+    return getKeyStrokesByActionId("$Paste");
+  }
+
+  @Override
+  public ColorPalette getTerminalColorPalette() {
+    return SystemInfo.isWindows ? ColorPalette.WINDOWS_PALETTE : ColorPalette.XTERM_PALETTE;
+  }
+
+  private KeyStroke[] getKeyStrokesByActionId(String actionId) {
+    List<KeyStroke> keyStrokes = new ArrayList<KeyStroke>();
+    Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(actionId);
+    for (Shortcut sc : shortcuts) {
+      if (sc instanceof KeyboardShortcut) {
+        KeyStroke ks = ((KeyboardShortcut)sc).getFirstKeyStroke();
+        keyStrokes.add(ks);
+      }
+    }
+
+    return keyStrokes.toArray(new KeyStroke[keyStrokes.size()]);
+  }
+
+  @Override
+  public boolean shouldCloseTabOnLogout(TtyConnector ttyConnector) {
+    return ttyConnector instanceof PtyProcessTtyConnector; //close tab only on logout of local pty, not remote
+  }
+
+  @Override
+  public float getLineSpace() {
+    return myColorScheme.getConsoleLineSpacing();
+  }
+
+  @Override
+  public boolean useInverseSelectionColor() {
+    return false;
+  }
+
+  @Override
+  public TextStyle getSelectionColor() {
+    return new TextStyle(TerminalColor.awt(myColorScheme.getColor(EditorColors.SELECTION_FOREGROUND_COLOR)),
+                         TerminalColor.awt(myColorScheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR)));
+  }
+
+  @Override
+  public TextStyle getDefaultStyle() {
+    return new TextStyle(TerminalColor.awt(myColorScheme.getDefaultForeground()), TerminalColor.awt(
+      myColorScheme.getDefaultBackground()));
+  }
+
+  @Override
+  public Font getTerminalFont() {
+    Font normalFont = Font.decode(getFontName());
+
+    if (normalFont == null) {
+      normalFont = super.getTerminalFont();
+    }
+
+    normalFont = normalFont.deriveFont(getTerminalFontSize());
+
+    return normalFont;
+  }
+
+  public String getFontName() {
+    List<String> fonts = myColorScheme.getConsoleFontPreferences().getEffectiveFontFamilies();
+
+    for (String font : fonts) {
+      if (isApplicable(font)) {
+        return font;
+      }
+    }
+    return "Monospaced-14";
+  }
+
+  private static boolean isApplicable(String font) {
+    if ("Source Code Pro".equals(font)) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public float getTerminalFontSize() {
+    return (float)myColorScheme.getConsoleFontSize();
+  }
+
+  public EditorColorsScheme getColorScheme() {
+    return createBoundColorSchemeDelegate(null);
+  }
+
+  @NotNull
+  public EditorColorsScheme createBoundColorSchemeDelegate(@Nullable final EditorColorsScheme customGlobalScheme) {
+    return new MyColorSchemeDelegate(customGlobalScheme);
+  }
+
+  private static class MyColorSchemeDelegate implements EditorColorsScheme {
+
+    private final FontPreferences myFontPreferences = new FontPreferences();
+    private final HashMap<TextAttributesKey, TextAttributes> myOwnAttributes = new HashMap<TextAttributesKey, TextAttributes>();
+    private final HashMap<ColorKey, Color> myOwnColors = new HashMap<ColorKey, Color>();
+    private final EditorColorsScheme myCustomGlobalScheme;
+    private Map<EditorFontType, Font> myFontsMap = null;
+    private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
+    private int myFontSize = -1;
+    private String myFaceName = null;
+    private EditorColorsScheme myGlobalScheme;
+
+    private MyColorSchemeDelegate(@Nullable final EditorColorsScheme globalScheme) {
+      myCustomGlobalScheme = globalScheme;
+      updateGlobalScheme();
+    }
+
+    private EditorColorsScheme getGlobal() {
+      return myGlobalScheme;
+    }
+
+    @Override
+    public String getName() {
+      return getGlobal().getName();
+    }
+
+
+    protected void initFonts() {
+      String editorFontName = getEditorFontName();
+      int editorFontSize = getEditorFontSize();
+      myFontPreferences.clear();
+      myFontPreferences.register(editorFontName, editorFontSize);
+
+      myFontsMap = new EnumMap<EditorFontType, Font>(EditorFontType.class);
+
+      Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
+      Font boldFont = new Font(editorFontName, Font.BOLD, editorFontSize);
+      Font italicFont = new Font(editorFontName, Font.ITALIC, editorFontSize);
+      Font boldItalicFont = new Font(editorFontName, Font.BOLD | Font.ITALIC, editorFontSize);
+
+      myFontsMap.put(EditorFontType.PLAIN, plainFont);
+      myFontsMap.put(EditorFontType.BOLD, boldFont);
+      myFontsMap.put(EditorFontType.ITALIC, italicFont);
+      myFontsMap.put(EditorFontType.BOLD_ITALIC, boldItalicFont);
+    }
+
+    @Override
+    public void setName(String name) {
+      getGlobal().setName(name);
+    }
+
+    @Override
+    public TextAttributes getAttributes(TextAttributesKey key) {
+      if (myOwnAttributes.containsKey(key)) return myOwnAttributes.get(key);
+      return getGlobal().getAttributes(key);
+    }
+
+    @Override
+    public void setAttributes(TextAttributesKey key, TextAttributes attributes) {
+      myOwnAttributes.put(key, attributes);
+    }
+
+    @NotNull
+    @Override
+    public Color getDefaultBackground() {
+      return getGlobal().getDefaultBackground();
+    }
+
+    @NotNull
+    @Override
+    public Color getDefaultForeground() {
+      return getGlobal().getDefaultForeground();
+    }
+
+    @Override
+    public Color getColor(ColorKey key) {
+      if (myOwnColors.containsKey(key)) return myOwnColors.get(key);
+      return getGlobal().getColor(key);
+    }
+
+    @Override
+    public void setColor(ColorKey key, Color color) {
+      myOwnColors.put(key, color);
+    }
+
+    @NotNull
+    @Override
+    public FontPreferences getFontPreferences() {
+      return myFontPreferences;
+    }
+
+    @Override
+    public void setFontPreferences(@NotNull FontPreferences preferences) {
+      preferences.copyTo(myFontPreferences);
+      initFonts();
+    }
+
+    @Override
+    public int getEditorFontSize() {
+      if (myFontSize == -1) {
+        return getGlobal().getEditorFontSize();
+      }
+      return myFontSize;
+    }
+
+    @Override
+    public void setEditorFontSize(int fontSize) {
+      if (fontSize < 8) fontSize = 8;
+      if (fontSize > myMaxFontSize) fontSize = myMaxFontSize;
+      myFontSize = fontSize;
+      initFonts();
+    }
+
+    @Override
+    public FontSize getQuickDocFontSize() {
+      return myGlobalScheme.getQuickDocFontSize();
+    }
+
+    @Override
+    public void setQuickDocFontSize(@NotNull FontSize fontSize) {
+      myGlobalScheme.setQuickDocFontSize(fontSize);
+    }
+
+    @Override
+    public String getEditorFontName() {
+      if (myFaceName == null) {
+        return getGlobal().getEditorFontName();
+      }
+      return myFaceName;
+    }
+
+    @Override
+    public void setEditorFontName(String fontName) {
+      myFaceName = fontName;
+      initFonts();
+    }
+
+    @Override
+    public Font getFont(EditorFontType key) {
+      if (myFontsMap != null) {
+        Font font = myFontsMap.get(key);
+        if (font != null) return font;
+      }
+      return getGlobal().getFont(key);
+    }
+
+    @Override
+    public void setFont(EditorFontType key, Font font) {
+      if (myFontsMap == null) {
+        initFonts();
+      }
+      myFontsMap.put(key, font);
+    }
+
+    @Override
+    public float getLineSpacing() {
+      return getGlobal().getLineSpacing();
+    }
+
+    @Override
+    public void setLineSpacing(float lineSpacing) {
+      getGlobal().setLineSpacing(lineSpacing);
+    }
+
+    @Override
+    @Nullable
+    public Object clone() {
+      return null;
+    }
+
+    @Override
+    public void readExternal(Element element) throws InvalidDataException {
+    }
+
+    @Override
+    public void writeExternal(Element element) throws WriteExternalException {
+    }
+
+    public void updateGlobalScheme() {
+      myGlobalScheme = myCustomGlobalScheme == null ? EditorColorsManager.getInstance().getGlobalScheme() : myCustomGlobalScheme;
+      int globalFontSize = getGlobal().getEditorFontSize();
+      myMaxFontSize = Math.max(OptionsConstants.MAX_EDITOR_FONT_SIZE, globalFontSize);
+    }
+
+    @NotNull
+    @Override
+    public FontPreferences getConsoleFontPreferences() {
+      return getGlobal().getConsoleFontPreferences();
+    }
+
+    @Override
+    public void setConsoleFontPreferences(@NotNull FontPreferences preferences) {
+      getGlobal().setConsoleFontPreferences(preferences);
+    }
+
+    @Override
+    public String getConsoleFontName() {
+      return getGlobal().getConsoleFontName();
+    }
+
+    @Override
+    public void setConsoleFontName(String fontName) {
+      getGlobal().setConsoleFontName(fontName);
+    }
+
+    @Override
+    public int getConsoleFontSize() {
+      return getGlobal().getConsoleFontSize();
+    }
+
+    @Override
+    public void setConsoleFontSize(int fontSize) {
+      getGlobal().setConsoleFontSize(fontSize);
+    }
+
+    @Override
+    public float getConsoleLineSpacing() {
+      return getGlobal().getConsoleLineSpacing();
+    }
+
+    @Override
+    public void setConsoleLineSpacing(float lineSpacing) {
+      getGlobal().setConsoleLineSpacing(lineSpacing);
+    }
+  }
+}
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java
index 6f2e49d..99a21e8 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java
@@ -14,7 +14,7 @@
 import com.jediterm.terminal.display.JediTerminal;
 import com.jediterm.terminal.display.StyleState;
 import com.jediterm.terminal.ui.JediTermWidget;
-import com.jediterm.terminal.ui.SystemSettingsProvider;
+import com.jediterm.terminal.ui.settings.SettingsProvider;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -26,17 +26,17 @@
 
 public class JBTerminalWidget extends JediTermWidget {
 
-  public JBTerminalWidget(SystemSettingsProvider settingsProvider) {
+  public JBTerminalWidget(SettingsProvider settingsProvider) {
     super(settingsProvider);
 
     JBTabbedTerminalWidget.convertActions(this, getActions());
   }
 
   @Override
-  protected JBTerminalPanel createTerminalPanel(@NotNull SystemSettingsProvider settingsProvider,
+  protected JBTerminalPanel createTerminalPanel(@NotNull SettingsProvider settingsProvider,
                                                 @NotNull StyleState styleState,
                                                 @NotNull BackBuffer backBuffer) {
-    return new JBTerminalPanel(settingsProvider, backBuffer, styleState, getColorScheme());
+    return new JBTerminalPanel(settingsProvider, backBuffer, styleState);
   }
 
   @Override
@@ -44,243 +44,10 @@
     return new JBTerminalStarter(terminal, connector);
   }
 
-  public EditorColorsScheme getColorScheme() {
-    return createBoundColorSchemeDelegate(null);
-  }
-
   @Override
   protected JScrollBar createScrollBar() {
     return new JBScrollBar();
   }
 
-  @NotNull
-  public EditorColorsScheme createBoundColorSchemeDelegate(@Nullable final EditorColorsScheme customGlobalScheme) {
-    return new MyColorSchemeDelegate(customGlobalScheme);
-  }
 
-  private static class MyColorSchemeDelegate implements EditorColorsScheme {
-
-    private final FontPreferences myFontPreferences = new FontPreferences();
-    private final HashMap<TextAttributesKey, TextAttributes> myOwnAttributes = new HashMap<TextAttributesKey, TextAttributes>();
-    private final HashMap<ColorKey, Color> myOwnColors = new HashMap<ColorKey, Color>();
-    private final EditorColorsScheme myCustomGlobalScheme;
-    private Map<EditorFontType, Font> myFontsMap = null;
-    private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
-    private int myFontSize = -1;
-    private String myFaceName = null;
-    private EditorColorsScheme myGlobalScheme;
-
-    private MyColorSchemeDelegate(@Nullable final EditorColorsScheme globalScheme) {
-      myCustomGlobalScheme = globalScheme;
-      updateGlobalScheme();
-    }
-
-    private EditorColorsScheme getGlobal() {
-      return myGlobalScheme;
-    }
-
-    @Override
-    public String getName() {
-      return getGlobal().getName();
-    }
-
-
-    protected void initFonts() {
-      String editorFontName = getEditorFontName();
-      int editorFontSize = getEditorFontSize();
-      myFontPreferences.clear();
-      myFontPreferences.register(editorFontName, editorFontSize);
-
-      myFontsMap = new EnumMap<EditorFontType, Font>(EditorFontType.class);
-
-      Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
-      Font boldFont = new Font(editorFontName, Font.BOLD, editorFontSize);
-      Font italicFont = new Font(editorFontName, Font.ITALIC, editorFontSize);
-      Font boldItalicFont = new Font(editorFontName, Font.BOLD | Font.ITALIC, editorFontSize);
-
-      myFontsMap.put(EditorFontType.PLAIN, plainFont);
-      myFontsMap.put(EditorFontType.BOLD, boldFont);
-      myFontsMap.put(EditorFontType.ITALIC, italicFont);
-      myFontsMap.put(EditorFontType.BOLD_ITALIC, boldItalicFont);
-    }
-
-    @Override
-    public void setName(String name) {
-      getGlobal().setName(name);
-    }
-
-    @Override
-    public TextAttributes getAttributes(TextAttributesKey key) {
-      if (myOwnAttributes.containsKey(key)) return myOwnAttributes.get(key);
-      return getGlobal().getAttributes(key);
-    }
-
-    @Override
-    public void setAttributes(TextAttributesKey key, TextAttributes attributes) {
-      myOwnAttributes.put(key, attributes);
-    }
-
-    @NotNull
-    @Override
-    public Color getDefaultBackground() {
-      return getGlobal().getDefaultBackground();
-    }
-
-    @NotNull
-    @Override
-    public Color getDefaultForeground() {
-      return getGlobal().getDefaultForeground();
-    }
-
-    @Override
-    public Color getColor(ColorKey key) {
-      if (myOwnColors.containsKey(key)) return myOwnColors.get(key);
-      return getGlobal().getColor(key);
-    }
-
-    @Override
-    public void setColor(ColorKey key, Color color) {
-      myOwnColors.put(key, color);
-    }
-
-    @NotNull
-    @Override
-    public FontPreferences getFontPreferences() {
-      return myFontPreferences;
-    }
-
-    @Override
-    public void setFontPreferences(@NotNull FontPreferences preferences) {
-      preferences.copyTo(myFontPreferences);
-      initFonts();
-    }
-
-    @Override
-    public int getEditorFontSize() {
-      if (myFontSize == -1) {
-        return getGlobal().getEditorFontSize();
-      }
-      return myFontSize;
-    }
-
-    @Override
-    public void setEditorFontSize(int fontSize) {
-      if (fontSize < 8) fontSize = 8;
-      if (fontSize > myMaxFontSize) fontSize = myMaxFontSize;
-      myFontSize = fontSize;
-      initFonts();
-    }
-
-    @Override
-    public FontSize getQuickDocFontSize() {
-      return myGlobalScheme.getQuickDocFontSize();
-    }
-
-    @Override
-    public void setQuickDocFontSize(@NotNull FontSize fontSize) {
-      myGlobalScheme.setQuickDocFontSize(fontSize);
-    }
-
-    @Override
-    public String getEditorFontName() {
-      if (myFaceName == null) {
-        return getGlobal().getEditorFontName();
-      }
-      return myFaceName;
-    }
-
-    @Override
-    public void setEditorFontName(String fontName) {
-      myFaceName = fontName;
-      initFonts();
-    }
-
-    @Override
-    public Font getFont(EditorFontType key) {
-      if (myFontsMap != null) {
-        Font font = myFontsMap.get(key);
-        if (font != null) return font;
-      }
-      return getGlobal().getFont(key);
-    }
-
-    @Override
-    public void setFont(EditorFontType key, Font font) {
-      if (myFontsMap == null) {
-        initFonts();
-      }
-      myFontsMap.put(key, font);
-    }
-
-    @Override
-    public float getLineSpacing() {
-      return getGlobal().getLineSpacing();
-    }
-
-    @Override
-    public void setLineSpacing(float lineSpacing) {
-      getGlobal().setLineSpacing(lineSpacing);
-    }
-
-    @Override
-    @Nullable
-    public Object clone() {
-      return null;
-    }
-
-    @Override
-    public void readExternal(Element element) throws InvalidDataException {
-    }
-
-    @Override
-    public void writeExternal(Element element) throws WriteExternalException {
-    }
-
-    public void updateGlobalScheme() {
-      myGlobalScheme = myCustomGlobalScheme == null ? EditorColorsManager.getInstance().getGlobalScheme() : myCustomGlobalScheme;
-      int globalFontSize = getGlobal().getEditorFontSize();
-      myMaxFontSize = Math.max(OptionsConstants.MAX_EDITOR_FONT_SIZE, globalFontSize);
-    }
-
-    @NotNull
-    @Override
-    public FontPreferences getConsoleFontPreferences() {
-      return getGlobal().getConsoleFontPreferences();
-    }
-
-    @Override
-    public void setConsoleFontPreferences(@NotNull FontPreferences preferences) {
-      getGlobal().setConsoleFontPreferences(preferences);
-    }
-
-    @Override
-    public String getConsoleFontName() {
-      return getGlobal().getConsoleFontName();
-    }
-
-    @Override
-    public void setConsoleFontName(String fontName) {
-      getGlobal().setConsoleFontName(fontName);
-    }
-
-    @Override
-    public int getConsoleFontSize() {
-      return getGlobal().getConsoleFontSize();
-    }
-
-    @Override
-    public void setConsoleFontSize(int fontSize) {
-      getGlobal().setConsoleFontSize(fontSize);
-    }
-
-    @Override
-    public float getConsoleLineSpacing() {
-      return getGlobal().getConsoleLineSpacing();
-    }
-
-    @Override
-    public void setConsoleLineSpacing(float lineSpacing) {
-      getGlobal().setConsoleLineSpacing(lineSpacing);
-    }
-  }
 }
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
index 203de24..8cb28ea 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
@@ -21,9 +21,8 @@
 
   @Override
   public void update(final AnActionEvent e) {
-    boolean enabled = SystemInfo.isUnix;
-    e.getPresentation().setVisible(enabled);
-    e.getPresentation().setEnabled(enabled);
+    e.getPresentation().setVisible(true);
+    e.getPresentation().setEnabled(true);
   }
 
   public void actionPerformed(final AnActionEvent e) {
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
index 7d57aac..271c8dc 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
@@ -9,6 +9,8 @@
  * @author traff
  */
 public class TerminalToolWindowFactory implements ToolWindowFactory, DumbAware {
+  public static final String TOOL_WINDOW_ID = "Terminal";
+  
   @Override
   public void createToolWindowContent(Project project, ToolWindow toolWindow) {
     TerminalView terminalView = TerminalView.getInstance();
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
index bd7cfd2..188be8f 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
@@ -9,15 +9,20 @@
 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.ui.content.Content;
 import com.intellij.ui.content.ContentFactory;
+import com.intellij.util.ui.UIUtil;
 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 javax.swing.*;
+import java.awt.*;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
 
@@ -29,25 +34,47 @@
   private JBTabbedTerminalWidget myTerminalWidget;
   private Project myProject;
 
-  public void initTerminal(Project project, final ToolWindow toolWindow) {
+  public void initTerminal(final Project project, final ToolWindow toolWindow) {
     myProject = project;
     LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(project);
-    
+
     toolWindow.setToHideOnEmptyContent(true);
-    
+
     if (terminalRunner != null) {
       myTerminalWidget = terminalRunner.createTerminalWidget();
       myTerminalWidget.addTabListener(new TabbedTerminalWidget.TabListener() {
         @Override
         public void tabClosed(JediTermWidget terminal) {
-          hideIfNoActiveSessions(toolWindow, myTerminalWidget);
+          UIUtil.invokeLaterIfNeeded(new Runnable() {
+            @Override
+            public void run() {
+              hideIfNoActiveSessions(toolWindow, myTerminalWidget);
+            }
+          });
         }
       });
     }
 
     Content content = createToolWindowContentPanel(terminalRunner, myTerminalWidget, toolWindow);
-    
+
     toolWindow.getContentManager().addContent(content);
+
+    ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerListener() {
+      @Override
+      public void toolWindowRegistered(@NotNull String id) {
+      }
+
+      @Override
+      public void stateChanged() {
+        ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(TerminalToolWindowFactory.TOOL_WINDOW_ID);
+        if (window != null) {
+          boolean visible = window.isVisible();
+          if (visible && toolWindow.getContentManager().getContentCount() == 0) {
+            initTerminal(project, window);
+          }
+        }
+      }
+    });
   }
 
   private Content createToolWindowContentPanel(@Nullable LocalTerminalDirectRunner terminalRunner,
@@ -59,6 +86,7 @@
         return PlatformDataKeys.HELP_ID.is(dataId) ? EventLog.HELP_ID : super.getData(dataId);
       }
     };
+
     if (terminalWidget != null) {
       panel.setContent(terminalWidget.getComponent());
 
@@ -73,9 +101,8 @@
     final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, "", false);
     content.setCloseable(true);
 
-    if (getComponentToFocus() != null) {
-      content.setPreferredFocusableComponent(getComponentToFocus());
-    }
+    content.setPreferredFocusableComponent(terminalWidget.getComponent());
+    
     return content;
   }
 
@@ -129,7 +156,7 @@
   }
 
   private ActionToolbar createToolbar(@Nullable final LocalTerminalDirectRunner terminalRunner,
-                                             final JBTabbedTerminalWidget terminal, ToolWindow toolWindow) {
+                                      final JBTabbedTerminalWidget terminal, ToolWindow toolWindow) {
     DefaultActionGroup group = new DefaultActionGroup();
 
     if (terminalRunner != null) {
@@ -151,16 +178,9 @@
     }, true);
   }
 
-  private void hideIfNoActiveSessions(final ToolWindow toolWindow, JBTabbedTerminalWidget terminal) {
+  private static void hideIfNoActiveSessions(final ToolWindow toolWindow, JBTabbedTerminalWidget terminal) {
     if (terminal.isNoActiveSessions()) {
       toolWindow.getContentManager().removeAllContents(true);
-
-      toolWindow.getActivation().doWhenDone(new Runnable() {
-        @Override
-        public void run() {
-          initTerminal(myProject, toolWindow);
-        }
-      });
     }
   }
 
diff --git a/plugins/terminal/terminal.iml b/plugins/terminal/terminal.iml
index 86f9059..59daabb 100644
--- a/plugins/terminal/terminal.iml
+++ b/plugins/terminal/terminal.iml
@@ -48,6 +48,7 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="library" name="Guava" level="project" />
   </component>
 </module>
 
diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
index f88daee..55a6a3d 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -177,7 +177,7 @@
   public String getGeneratedName(JavaRunConfigurationModule runconfigurationmodule) {
     if (TestType.PACKAGE.getType().equals(TEST_OBJECT)) if (getPackageName().length() == 0) return "<default>";
     else return getPackageName();
-    String name = JavaExecutionUtil.getPresentableClassName(getMainClassName(), runconfigurationmodule);
+    String name = JavaExecutionUtil.getPresentableClassName(getMainClassName());
     if (TestType.METHOD.getType().equals(TEST_OBJECT)) {
       return name + '.' + getMethodName();
     }
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 602a51e..10c0e8e 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -141,6 +141,8 @@
     <extensionPoint name="clsStubBuilderFactory" interface="com.intellij.psi.impl.compiled.ClsStubBuilderFactory"/>
     <extensionPoint name="javaMainMethodProvider" interface="com.intellij.codeInsight.runner.JavaMainMethodProvider"/>
 
+    <extensionPoint name="importFilter" interface="com.intellij.codeInsight.ImportFilter"/>
+
     <extensionPoint name="debuggerClassFilterProvider" interface="com.intellij.ui.classFilter.DebuggerClassFilterProvider"/>
     <extensionPoint name="topLevelClassProvider" interface="com.intellij.debugger.engine.TopLevelParentClassProvider"/>
 
diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml
index 0432ce6..1fd5f3d 100644
--- a/resources/src/idea/RichPlatformActions.xml
+++ b/resources/src/idea/RichPlatformActions.xml
@@ -408,7 +408,7 @@
     </group>
 
     <group>
-      <action id="MarkSourceRoot" class="com.intellij.ide.projectView.actions.MarkRootAction" icon="AllIcons.Modules.SourceRoot"/>
+      <action id="MarkSourceRoot" class="com.intellij.ide.projectView.actions.MarkJavaSourceRootAction" icon="AllIcons.Modules.SourceRoot"/>
       <action id="MarkTestSourceRoot" class="com.intellij.ide.projectView.actions.MarkTestSourceRootAction" icon="AllIcons.Modules.TestRoot"/>
       <action id="MarkExcludeRoot" class="com.intellij.ide.projectView.actions.MarkExcludeRootAction" icon="AllIcons.Modules.ExcludeRoot"/>
       <action id="UnmarkRoot" class="com.intellij.ide.projectView.actions.UnmarkRootAction"/>
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index 9e841a2..ba21d55 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -51,7 +51,7 @@
                     interface="com.intellij.compiler.DependencyProcessor"/>
 
     <extensionPoint name="compiler.optionsManager"
-                    interface="com.intellij.compiler.options.CompilerOptionsManager"/>
+                    interface="com.intellij.compiler.options.CompilerOptionsFilter"/>
 
     <extensionPoint name="compiler.resourceCompilerExtension"
                     interface="com.intellij.compiler.impl.resourceCompiler.ResourceCompilerExtension"/>
@@ -79,7 +79,7 @@
     <extensionPoint name="codeInsight.wordCompletionFilter" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
 
     <extensionPoint name="projectStructureConfigurableFilter" interface="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableFilter"/>
-    <extensionPoint name="projectStructureConfigurableAdder" interface="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableAdder"/>
+    <extensionPoint name="projectStructureConfigurableAdder" interface="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableContributor"/>
 
     <extensionPoint name="compiler" area="IDEA_PROJECT" interface="com.intellij.openapi.compiler.Compiler"/>
     <extensionPoint name="compilerFactory" area="IDEA_PROJECT" interface="com.intellij.openapi.compiler.CompilerFactory"/>
diff --git a/spellchecker/src/com/intellij/spellchecker/actions/SpellingPopupActionGroup.java b/spellchecker/src/com/intellij/spellchecker/actions/SpellingPopupActionGroup.java
index 96eea9a..a3639c9 100644
--- a/spellchecker/src/com/intellij/spellchecker/actions/SpellingPopupActionGroup.java
+++ b/spellchecker/src/com/intellij/spellchecker/actions/SpellingPopupActionGroup.java
@@ -16,7 +16,7 @@
 package com.intellij.spellchecker.actions;
 
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInspection.LocalQuickFix;
 import com.intellij.codeInspection.ex.QuickFixWrapper;
@@ -67,7 +67,7 @@
     Project project = e.getData(LangDataKeys.PROJECT);
     Editor editor = e.getData(LangDataKeys.EDITOR);
     if (psiFile != null && project != null && editor != null) {
-      List<HighlightInfo.IntentionActionDescriptor> quickFixes = QuickFixAction.getAvailableActions(editor, psiFile, -1);
+      List<HighlightInfo.IntentionActionDescriptor> quickFixes = ShowIntentionsPass.getAvailableActions(editor, psiFile, -1);
       Map<Anchor, List<AnAction>> children = new HashMap<Anchor, List<AnAction>>();
       ArrayList<AnAction> first = new ArrayList<AnAction>();
       children.put(Anchor.FIRST, first);
diff --git a/xml/dom-impl/src/META-INF/DomPlugin.xml b/xml/dom-impl/src/META-INF/DomPlugin.xml
index ae1e1b0..89dee6b 100644
--- a/xml/dom-impl/src/META-INF/DomPlugin.xml
+++ b/xml/dom-impl/src/META-INF/DomPlugin.xml
@@ -4,14 +4,21 @@
                     interface="com.intellij.util.xml.DomFileDescription"/>
 
     <extensionPoint name="dom.implementation"
-                    beanClass="com.intellij.util.xml.impl.DomImplementationClassEP"/>
+                    beanClass="com.intellij.util.xml.impl.DomImplementationClassEP">
+      <with attribute="interfaceName" implements="com.intellij.util.xml.DomElement"/>
+      <with attribute="implementationName" implements="com.intellij.util.xml.DomElement"/>
+    </extensionPoint>
 
     <extensionPoint name="dom.converter"
-                    beanClass="com.intellij.util.xml.impl.DomImplementationClassEP"/>
+                    beanClass="com.intellij.util.xml.impl.DomImplementationClassEP">
+      <with attribute="interfaceName" implements="com.intellij.util.xml.Converter"/>
+      <with attribute="implementationName" implements="com.intellij.util.xml.Converter"/>
+    </extensionPoint>
 
     <extensionPoint name="dom.extender"
                     beanClass="com.intellij.util.xml.reflect.DomExtenderEP">
-      <with attribute="myDomClass" implements="com.intellij.util.xml.reflect.DomExtender"/>
+      <with attribute="domClassName" implements="com.intellij.util.xml.DomElement"/>
+      <with attribute="extenderClassName" implements="com.intellij.util.xml.reflect.DomExtender"/>
     </extensionPoint>
 
     <extensionPoint name="dom.customAnnotationChecker"
diff --git a/xml/impl/resources/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java b/xml/impl/resources/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java
index 45220b0..a068f0f 100644
--- a/xml/impl/resources/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java
+++ b/xml/impl/resources/com/intellij/codeInsight/completion/TagNameReferenceCompletionProvider.java
@@ -29,7 +29,7 @@
 import com.intellij.util.Consumer;
 import com.intellij.util.PairConsumer;
 import com.intellij.util.ProcessingContext;
-import com.intellij.xml.XmlTagNameProvider;
+import com.intellij.xml.XmlCompletionExtension;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -41,8 +41,10 @@
 public class TagNameReferenceCompletionProvider extends CompletionProvider<CompletionParameters> {
   public static LookupElement[] getTagNameVariants(final @NotNull XmlTag tag, final String prefix) {
     List<LookupElement> elements = new ArrayList<LookupElement>();
-    for (XmlTagNameProvider tagNameProvider : XmlTagNameProvider.EP_NAME.getExtensions()) {
-      tagNameProvider.addTagNameVariants(elements, tag, prefix);
+    for (XmlCompletionExtension tagNameProvider : XmlCompletionExtension.EP_NAME.getExtensions()) {
+      if (tagNameProvider.isMyContext(tag)) {
+        tagNameProvider.addTagNameVariants(elements, tag, prefix);
+      }
     }
     return elements.toArray(new LookupElement[elements.size()]);
   }
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java
index 6b0debb..b7710d6 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java
@@ -27,14 +27,14 @@
 import com.intellij.psi.xml.XmlFile;
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.util.ProcessingContext;
-import com.intellij.xml.NamespaceAwareXmlAttributeDescriptor;
-import com.intellij.xml.XmlAttributeDescriptor;
-import com.intellij.xml.XmlElementDescriptor;
-import com.intellij.xml.XmlExtension;
+import com.intellij.xml.*;
 import com.intellij.xml.util.HtmlUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import static com.intellij.codeInsight.completion.CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED;
 
 public class XmlAttributeReferenceCompletionProvider extends CompletionProvider<CompletionParameters> {
@@ -81,9 +81,18 @@
       completionData = CompletionUtil.getCompletionDataByElement(attribute, attribute.getContainingFile().getOriginalFile());
     boolean caseSensitive = !(completionData instanceof HtmlCompletionData) || ((HtmlCompletionData)completionData).isCaseSensitive();
 
+    final List<XmlCompletionExtension> completionExtensions = new ArrayList<XmlCompletionExtension>();
+
+    for (XmlCompletionExtension completionExtension : XmlCompletionExtension.EP_NAME.getExtensions()) {
+      if (completionExtension.isMyContext(tag)) {
+        completionExtensions.add(completionExtension);
+      }
+    }
+
     for (XmlAttributeDescriptor descriptor : descriptors) {
       if (isValidVariant(attribute, descriptor, attributes, extension)) {
-        String name = descriptor.getName(tag);
+        final String fullAttrName = descriptor.getName(tag);
+        String name = fullAttrName;
 
         InsertHandler<LookupElement> insertHandler = XmlAttributeInsertHandler.INSTANCE;
 
@@ -103,7 +112,7 @@
         }
         if (prefix == null || name.startsWith(prefix)) {
           if (prefix != null && name.length() > prefix.length()) {
-            name = descriptor.getName(tag).substring(prefix.length());
+            name = fullAttrName.substring(prefix.length());
           }
           LookupElementBuilder element = LookupElementBuilder.create(name);
           if (descriptor instanceof PsiPresentableMetaData) {
@@ -116,8 +125,21 @@
           element = element
             .withCaseSensitivity(caseSensitive)
             .withInsertHandler(insertHandler);
-          result.addElement(
-            descriptor.isRequired() ? PrioritizedLookupElement.withPriority(element.appendTailText("(required)", true), 100) : element);
+          LookupElement e = null;
+
+          for (XmlCompletionExtension tagNameProvider : completionExtensions) {
+            e = tagNameProvider.setupAttributeLookupElement(tag, descriptor, fullAttrName, element);
+            
+            if (e != null) {
+              break;
+            }
+          }
+          if (e == null) {
+            e = descriptor.isRequired()
+                ? PrioritizedLookupElement.withPriority(element.appendTailText("(required)", true), 100)
+                : element; 
+          }
+          result.addElement(e);
         }
       }
     }
diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java
new file mode 100644
index 0000000..0062567
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java
@@ -0,0 +1,123 @@
+/*
+ * 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.intellij.ide.browsers;
+
+import com.intellij.ide.BrowserUtil;
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.HtmlUtil;
+
+import java.awt.event.InputEvent;
+
+public class OpenFileInDefaultBrowserAction extends DumbAwareAction {
+  private static final Logger LOG = Logger.getInstance(OpenFileInDefaultBrowserAction.class);
+
+  @Override
+  public void update(AnActionEvent e) {
+    final DataContext dataContext = e.getDataContext();
+    final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
+    final Presentation presentation = e.getPresentation();
+
+    if (file == null || file.getVirtualFile() == null) {
+      presentation.setVisible(false);
+      presentation.setEnabled(false);
+      return;
+    }
+
+    Pair<WebBrowserUrlProvider, Url> browserUrlProvider = WebBrowserServiceImpl.getProvider(file);
+    final boolean isHtmlFile = HtmlUtil.isHtmlFile(file);
+    if (browserUrlProvider == null) {
+      if (file.getVirtualFile() instanceof LightVirtualFile) {
+        presentation.setVisible(false);
+        presentation.setEnabled(false);
+        return;
+      }
+      else {
+        presentation.setEnabled(isHtmlFile);
+      }
+    }
+    else {
+      presentation.setEnabled(true);
+    }
+    presentation.setVisible(true);
+
+    String text = getTemplatePresentation().getText();
+    String description = getTemplatePresentation().getDescription();
+
+    if (browserUrlProvider != null) {
+      final String customText = browserUrlProvider.first.getOpenInBrowserActionText(file);
+      if (customText != null) {
+        text = customText;
+      }
+      final String customDescription = browserUrlProvider.first.getOpenInBrowserActionDescription(file);
+      if (customDescription != null) {
+        description = customDescription;
+      }
+      if (isHtmlFile) {
+        description += " (hold Shift to open URL of local file)";
+      }
+    }
+
+    presentation.setText(text);
+    presentation.setDescription(description);
+
+    GeneralSettings settings = GeneralSettings.getInstance();
+    if (!settings.isUseDefaultBrowser()) {
+      BrowsersConfiguration.BrowserFamily family = BrowsersConfiguration.getInstance().findFamilyByPath(settings.getBrowserPath());
+      if (family != null) {
+        presentation.setIcon(family.getIcon());
+      }
+    }
+
+    if (ActionPlaces.isPopupPlace(e.getPlace())) {
+      presentation.setVisible(presentation.isEnabled());
+    }
+  }
+
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    DataContext dataContext = e.getDataContext();
+    PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext);
+    LOG.assertTrue(psiFile != null);
+    InputEvent event = e.getInputEvent();
+    doOpen(psiFile, event != null && event.isShiftDown());
+  }
+
+  static void doOpen(PsiFile psiFile, boolean preferLocalUrl) {
+    try {
+      Url url = WebBrowserService.getInstance().getUrlToOpen(psiFile, preferLocalUrl);
+      if (url != null) {
+        ApplicationManager.getApplication().saveAll();
+        BrowserUtil.launchBrowser(url.toExternalForm());
+      }
+    }
+    catch (WebBrowserUrlProvider.BrowserException e1) {
+      Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error"));
+    }
+    catch (Exception e1) {
+      LOG.error(e1);
+    }
+  }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java b/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java
index e223ee3..3114bb8 100644
--- a/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java
+++ b/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java
@@ -15,14 +15,11 @@
  */
 package com.intellij.ide.browsers;
 
-import com.intellij.ide.BrowserUtil;
 import com.intellij.ide.SelectInContext;
 import com.intellij.ide.SelectInTargetBase;
 import com.intellij.ide.StandardTargetWeights;
 import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -72,19 +69,7 @@
     LOG.assertTrue(psiElement != null);
     PsiFile psiFile = psiElement.getContainingFile();
     LOG.assertTrue(psiFile != null);
-    try {
-      Url url = WebBrowserService.getInstance().getUrlToOpen(psiFile, false);
-      if (url != null) {
-        ApplicationManager.getApplication().saveAll();
-        BrowserUtil.launchBrowser(url.toExternalForm());
-      }
-    }
-    catch (WebBrowserUrlProvider.BrowserException e1) {
-      Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error"));
-    }
-    catch (Exception e1) {
-      LOG.error(e1);
-    }
+    OpenFileInDefaultBrowserAction.doOpen(psiFile, false);
   }
 
   @Override
diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlTagNameProvider.java b/xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlCompletionExtension.java
similarity index 95%
rename from xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlTagNameProvider.java
rename to xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlCompletionExtension.java
index 0601b92..7fca24b 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlTagNameProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/xml/DefaultXmlCompletionExtension.java
@@ -23,7 +23,7 @@
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.xml.XmlElementDescriptor;
 import com.intellij.xml.XmlExtension;
-import com.intellij.xml.XmlTagNameProvider;
+import com.intellij.xml.XmlCompletionExtension;
 import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.NotNull;
 
@@ -32,7 +32,7 @@
 import java.util.Collections;
 import java.util.List;
 
-public class DefaultXmlTagNameProvider implements XmlTagNameProvider {
+public class DefaultXmlCompletionExtension extends XmlCompletionExtension {
   @Override
   public void addTagNameVariants(List<LookupElement> elements, @NotNull XmlTag tag, String prefix) {
     final List<String> namespaces;
diff --git a/xml/impl/src/com/intellij/xml/XmlCompletionExtension.java b/xml/impl/src/com/intellij/xml/XmlCompletionExtension.java
new file mode 100644
index 0000000..01aea03
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlCompletionExtension.java
@@ -0,0 +1,49 @@
+/*
+ * 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.intellij.xml;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * Provides custom tag names.
+ *
+ * @see HtmlCustomTagNameProvider
+ */
+public abstract class XmlCompletionExtension {
+  public static final ExtensionPointName<XmlCompletionExtension> EP_NAME = new ExtensionPointName<XmlCompletionExtension>("com.intellij.xml.completionExtension");
+
+  public void addTagNameVariants(List<LookupElement> elements, @NotNull XmlTag tag, String prefix) {
+  }
+
+  @Nullable
+  public LookupElement setupAttributeLookupElement(@NotNull XmlTag contextTag,
+                                                   @NotNull XmlAttributeDescriptor descriptor,
+                                                   @NotNull String name,
+                                                   @NotNull LookupElementBuilder elementBuilder) {
+    return null;
+  }
+
+  public boolean isMyContext(@NotNull XmlTag context) {
+    return true;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/XmlTagNameProvider.java b/xml/impl/src/com/intellij/xml/XmlTagNameProvider.java
deleted file mode 100644
index a0b5809..0000000
--- a/xml/impl/src/com/intellij/xml/XmlTagNameProvider.java
+++ /dev/null
@@ -1,34 +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 com.intellij.xml;
-
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.psi.xml.XmlTag;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-/**
- * Provides custom tag names.
- *
- * @see HtmlCustomTagNameProvider
- */
-public interface XmlTagNameProvider {
-  ExtensionPointName<XmlTagNameProvider> EP_NAME = new ExtensionPointName<XmlTagNameProvider>("com.intellij.xml.tagNameProvider");
-
-  void addTagNameVariants(List<LookupElement> elements, @NotNull XmlTag tag, String prefix);
-}
diff --git a/xml/impl/src/com/intellij/xml/util/UserColorLookup.java b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
index dbc2480..1f39b91 100644
--- a/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
+++ b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
@@ -54,13 +54,17 @@
   }
 
   public UserColorLookup(final Function<Color, String> colorToStringConverter) {
+    this(colorToStringConverter, LookupValueWithPriority.HIGH);
+  }
+
+  public UserColorLookup(final Function<Color, String> colorToStringConverter, int priority) {
     super(PrioritizedLookupElement.withPriority(LookupElementBuilder.create(COLOR_STRING).withInsertHandler(
       new InsertHandler<LookupElement>() {
         @Override
         public void handleInsert(InsertionContext context, LookupElement item) {
           handleUserSelection(context, colorToStringConverter);
         }
-      }), LookupValueWithPriority.HIGH));
+      }), priority));
   }
 
   private static void handleUserSelection(InsertionContext context, @NotNull Function<Color, String> colorToStringConverter) {
diff --git a/xml/impl/src/com/intellij/xml/util/XmlEnumeratedValueReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlEnumeratedValueReferenceProvider.java
index 590ae53..c1309a5 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlEnumeratedValueReferenceProvider.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlEnumeratedValueReferenceProvider.java
@@ -17,15 +17,11 @@
 
 import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
 import com.intellij.openapi.util.Key;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLanguageInjectionHost;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.*;
 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
-import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.*;
+import com.intellij.util.ArrayUtil;
 import com.intellij.util.ProcessingContext;
-import com.intellij.xml.XmlAttributeDescriptor;
 import com.intellij.xml.impl.XmlEnumerationDescriptor;
 import com.intellij.xml.impl.schema.XmlSchemaTagsProcessor;
 import org.jetbrains.annotations.NotNull;
@@ -34,7 +30,7 @@
  * @author Dmitry Avdeev
  *         Date: 15.08.13
  */
-public class XmlEnumeratedValueReferenceProvider extends PsiReferenceProvider {
+public class XmlEnumeratedValueReferenceProvider<T extends PsiElement> extends PsiReferenceProvider {
 
   public final static Key<Boolean> SUPPRESS = Key.create("suppress attribute value references");
 
@@ -45,22 +41,49 @@
     if (XmlSchemaTagsProcessor.PROCESSING_FLAG.get() != null || context.get(SUPPRESS) != null) {
       return PsiReference.EMPTY_ARRAY;
     }
-    XmlAttributeValue value = (XmlAttributeValue)element;
-    if (value instanceof PsiLanguageInjectionHost && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)value)) {
+    @SuppressWarnings("unchecked") PsiElement host = getHost((T)element);
+    if (host instanceof PsiLanguageInjectionHost && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)host)) {
       return PsiReference.EMPTY_ARRAY;
     }
-    String unquotedValue = value.getValue();
-    if (unquotedValue == null || XmlHighlightVisitor.skipValidation(value) || !XmlUtil.isSimpleXmlAttributeValue(unquotedValue, value)) {
+    String unquotedValue = ElementManipulators.getValueText(element);
+    if (XmlHighlightVisitor.skipValidation(element) || !XmlUtil.isSimpleValue(unquotedValue, element)) {
       return PsiReference.EMPTY_ARRAY;
     }
-    PsiElement parent = value.getParent();
-    if (parent instanceof XmlAttribute) {
-      final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
-      if (descriptor instanceof XmlEnumerationDescriptor &&
-          (descriptor.isFixed() || descriptor.isEnumerated() || unquotedValue.equals(descriptor.getDefaultValue()))) { // todo case insensitive
-        return ((XmlEnumerationDescriptor)descriptor).getValueReferences(value);
+    @SuppressWarnings("unchecked") final Object descriptor = getDescriptor((T)element);
+    if (descriptor instanceof XmlEnumerationDescriptor) {
+      XmlEnumerationDescriptor enumerationDescriptor = (XmlEnumerationDescriptor)descriptor;
+      if (enumerationDescriptor.isFixed() ||
+          enumerationDescriptor.isEnumerated((XmlElement)element) ||
+          unquotedValue.equals(enumerationDescriptor.getDefaultValue())) { // todo case insensitive
+        //noinspection unchecked
+        return enumerationDescriptor.getValueReferences((XmlElement)element, unquotedValue);
       }
     }
     return PsiReference.EMPTY_ARRAY;
   }
+
+  protected PsiElement getHost(T element) {
+    return element;
+  }
+
+  protected Object getDescriptor(T element) {
+    PsiElement parent = element.getParent();
+    return parent instanceof XmlAttribute ? ((XmlAttribute)parent).getDescriptor() : null;
+  }
+
+  public static XmlEnumeratedValueReferenceProvider forTags() {
+    return new XmlEnumeratedValueReferenceProvider<XmlTag>() {
+
+      @Override
+      protected Object getDescriptor(XmlTag element) {
+        return element.getDescriptor();
+      }
+
+      @Override
+      protected PsiElement getHost(XmlTag element) {
+        XmlText[] textElements = element.getValue().getTextElements();
+        return ArrayUtil.getFirstElement(textElements);
+      }
+    };
+  }
 }
diff --git a/xml/impl/src/com/intellij/xml/util/XmlInvalidIdInspection.java b/xml/impl/src/com/intellij/xml/util/XmlInvalidIdInspection.java
index afe28ed..6f8a17a 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlInvalidIdInspection.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlInvalidIdInspection.java
@@ -40,7 +40,7 @@
       idRef = idRef.toLowerCase();
     }
 
-    if (XmlUtil.isSimpleXmlAttributeValue(idRef, value) && refHolder.isIdReferenceValue(value)) {
+    if (XmlUtil.isSimpleValue(idRef, value) && refHolder.isIdReferenceValue(value)) {
       boolean hasIdDeclaration = refHolder.hasIdDeclaration(idRef);
       if (!hasIdDeclaration && tag instanceof HtmlTag) {
         hasIdDeclaration = refHolder.hasIdDeclaration(value.getValue());
diff --git a/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java
index f1b8294..a740db0 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java
@@ -23,6 +23,10 @@
   @Override
   public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
     XmlAttributeValue attributeValue = (XmlAttributeValue)element;
+    String value = attributeValue.getValue();
+    if (value == null) return PsiReference.EMPTY_ARRAY;
+    int i = value.indexOf(':');
+    if (i <= 0) return PsiReference.EMPTY_ARRAY;
     PsiElement parent = attributeValue.getParent();
     if (parent instanceof XmlAttribute && !XmlNSDescriptorImpl.checkSchemaNamespace(((XmlAttribute)parent).getParent())) {
       XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
@@ -32,15 +36,9 @@
           String prefix = XmlUtil.findPrefixByQualifiedName(type);
           String ns = ((XmlTag)descriptor.getDeclaration()).getNamespaceByPrefix(prefix);
           if (XmlNSDescriptorImpl.checkSchemaNamespace(ns)) {
-            String value = attributeValue.getValue();
-            if (value != null) {
-              int i = value.indexOf(':');
-              if (i > 0) {
-                return new PsiReference[] {
-                  new SchemaPrefixReference(attributeValue, TextRange.from(1, i), value.substring(0, i), null)
-                };
-              }
-            }
+            return new PsiReference[] {
+              new SchemaPrefixReference(attributeValue, TextRange.from(1, i), value.substring(0, i), null)
+            };
           }
         }
       }
diff --git a/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java b/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java
index 023e3a9..3d47549 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlRefCountHolder.java
@@ -266,7 +266,7 @@
 
     private void updateMap(@NotNull final XmlAttribute attribute, @NotNull final XmlAttributeValue value, final boolean soft) {
       final String id = XmlHighlightVisitor.getUnquotedValue(value, attribute.getParent());
-      if (XmlUtil.isSimpleXmlAttributeValue(id, value) &&
+      if (XmlUtil.isSimpleValue(id, value) &&
           PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
         myHolder.registerId(id, value, soft);
       }
diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
index ae58862..fa04ab0 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
@@ -4,16 +4,18 @@
 import com.intellij.html.impl.providers.MicrodataReferenceProvider;
 import com.intellij.html.impl.util.MicrodataUtil;
 import com.intellij.patterns.PlatformPatterns;
-import com.intellij.psi.PsiReferenceContributor;
-import com.intellij.psi.PsiReferenceRegistrar;
+import com.intellij.psi.*;
 import com.intellij.psi.filters.*;
 import com.intellij.psi.filters.position.NamespaceFilter;
 import com.intellij.psi.filters.position.ParentElementFilter;
+import com.intellij.psi.impl.UrlPsiReference;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.DtdReferencesProvider;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.IdReferenceProvider;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider;
 import com.intellij.psi.xml.*;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
 
 import static com.intellij.patterns.XmlPatterns.*;
 
@@ -90,5 +92,17 @@
 
     registrar.registerReferenceProvider(xmlAttributeValue(), new XmlPrefixReferenceProvider());
     registrar.registerReferenceProvider(xmlAttributeValue(), new XmlEnumeratedValueReferenceProvider(), PsiReferenceRegistrar.LOWER_PRIORITY);
+    registrar.registerReferenceProvider(xmlTag(), XmlEnumeratedValueReferenceProvider.forTags(), PsiReferenceRegistrar.LOWER_PRIORITY);
+
+    registrar.registerReferenceProvider(xmlAttributeValue().withLocalName("source")
+                                          .withSuperParent(2, xmlTag().withLocalName("documentation").withNamespace(XmlUtil.SCHEMA_URIS)),
+                                        new PsiReferenceProvider() {
+                                          @NotNull
+                                          @Override
+                                          public PsiReference[] getReferencesByElement(@NotNull PsiElement element,
+                                                                                       @NotNull ProcessingContext context) {
+                                            return new PsiReference[] { new UrlPsiReference(element) };
+                                          }
+                                        });
   }
 }
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
index 94c2e45..de3dbab 100644
--- a/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
+++ b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
@@ -1,4 +1,12 @@
 <html-property-table baseHelpRef="http://dev.w3.org/html5/spec/">
+<tag name        = "main"
+     helpref     = "grouping-content.html#the-main-element"
+     description = "represents the main content of the body of a document or application"
+     startTag    = "true"
+     endTag      = "true"
+     empty       = "false"
+     dtd         = ""
+/>
 <tag name        = "section"
      helpref     = "sections.html#the-section-element"
      description = "generic document or application section"
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
index f9d9f7c..b05794e 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
@@ -21,7 +21,6 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiReference;
 import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.xml.XmlAttributeValue;
 import com.intellij.psi.xml.XmlElement;
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.util.ArrayUtil;
@@ -32,6 +31,7 @@
 import gnu.trove.THashSet;
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.kohsuke.rngom.digested.DAttributePattern;
 import org.xml.sax.Locator;
@@ -206,10 +206,8 @@
   }
 
   @Override
-  public PsiReference[] getValueReferences(final XmlAttributeValue value) {
-    String text = value.getValue();
-    if (text == null) return PsiReference.EMPTY_ARRAY;
-    return new PsiReference[] { new XmlEnumeratedValueReference(value, this) {
+  public PsiReference[] getValueReferences(final XmlElement element, @NotNull String text) {
+    return new PsiReference[] { new XmlEnumeratedValueReference(element, this) {
       @Nullable
       @Override
       public PsiElement resolve() {
diff --git a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
index b054b7f..7d6df70 100644
--- a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
@@ -670,5 +670,11 @@
     myFixture.configureByFiles("Substitute/schema-a.xsd", "Substitute/schema-b.xsd");
     myFixture.testCompletionVariants("Substitute/test.xml", "b:instance", "instance");
   }
+
+  public void testEnumeratedTagValue() throws Exception {
+    myFixture.configureByFile("tagValue/enumerated.xsd");
+    myFixture.testCompletionVariants("tagValue/completeEnum.xml", "none", "standard");
+    myFixture.testCompletionVariants("tagValue/completeBoolean.xml", "false", "true");
+  }
 }
 
diff --git a/xml/tests/testData/completion/tagValue/completeBoolean.xml b/xml/tests/testData/completion/tagValue/completeBoolean.xml
new file mode 100644
index 0000000..7e8479f
--- /dev/null
+++ b/xml/tests/testData/completion/tagValue/completeBoolean.xml
@@ -0,0 +1 @@
+<bar xmlns="foo.bar"><caret></bar>
\ No newline at end of file
diff --git a/xml/tests/testData/completion/tagValue/completeEnum.xml b/xml/tests/testData/completion/tagValue/completeEnum.xml
new file mode 100644
index 0000000..4926a63
--- /dev/null
+++ b/xml/tests/testData/completion/tagValue/completeEnum.xml
@@ -0,0 +1 @@
+<foo xmlns="foo.bar"><caret></foo>
\ No newline at end of file
diff --git a/xml/tests/testData/completion/tagValue/enumerated.xsd b/xml/tests/testData/completion/tagValue/enumerated.xsd
new file mode 100644
index 0000000..fc0a4d8
--- /dev/null
+++ b/xml/tests/testData/completion/tagValue/enumerated.xsd
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+        targetNamespace="foo.bar">
+    <xs:element name="foo">
+        <xs:simpleType>
+          <xs:restriction base="xs:string">
+            <xs:enumeration value="none"/>
+            <xs:enumeration value="standard"/>
+          </xs:restriction>
+        </xs:simpleType>
+    </xs:element>
+
+    <xs:element name="bar" type="xs:boolean"/>
+    
+    <xs:element name="def" type="xs:string" default="my default"/>
+</xs:schema>
diff --git a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
index 8ab43e2..166a0b8 100644
--- a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
+++ b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
@@ -20,7 +20,7 @@
 invalid.id.reference=Invalid id reference
 uri.is.not.registered=URI is not registered (Settings | Project Settings | Schemas and DTDs)
 registered.resource.is.not.recognized=Resource registered by this uri is not recognized (Settings | Project Settings | Schemas and DTDs)
-attribute.should.have.fixed.value=Attribute should have fixed value {0}
+should.have.fixed.value={0} should have fixed value {1}
 
 #quickfixes
 insert.required.attribute.quickfix.text=Insert Required Attribute {0}
@@ -44,7 +44,7 @@
 unescaped.ampersand.or.nonterminated.character.entity.reference=Unescaped \\& or nonterminated character/entity reference
 expected.prologue.tag.termination.expected='?>' expected
 expected.whitespace=Whitespace expected
-wrong.attribute.value=Wrong attribute value
+wrong.value=Wrong {0} value
 way.too.unbalanced=Way too unbalanced. Stopping attempt to balance tags properly at this point
 
 cannot.resolve.taglib.uri=Cannot resolve taglib with uri {0}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
index 674ad16..7204bf7 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
@@ -20,6 +20,7 @@
 import com.intellij.util.ArrayUtil;
 import com.intellij.xml.XmlAttributeDescriptor;
 import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import com.intellij.xml.impl.XmlEnumerationDescriptor;
 
 /**
  * @author Maxim.Mossienko
@@ -95,8 +96,8 @@
   @Override
   public PsiElement getValueDeclaration(XmlElement attributeValue, String value) {
     String s = myCaseSensitive ? value : value.toLowerCase();
-    return delegate instanceof BasicXmlAttributeDescriptor ?
-           ((BasicXmlAttributeDescriptor)delegate).getValueDeclaration(attributeValue, s) :
+    return delegate instanceof XmlEnumerationDescriptor ?
+           ((XmlEnumerationDescriptor)delegate).getValueDeclaration(attributeValue, s) :
            super.getValueDeclaration(attributeValue, value);
   }
 }
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
index 8862ac8..cd1f672d 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
@@ -410,7 +410,11 @@
     class CompletionProcessor implements PsiElementProcessor<XmlTag> {
       List<String> myElements = new ArrayList<String>(1);
       String namespace;
-      XmlTag tag;
+      final XmlTag tag;
+
+      CompletionProcessor(XmlTag tag) {
+        this.tag = tag;
+      }
 
       public boolean execute(@NotNull final XmlTag element) {
         String name = element.getAttributeValue(NAME_ATTR_NAME);
@@ -448,8 +452,7 @@
           break;
       }
 
-      CompletionProcessor processor = new CompletionProcessor();
-      processor.tag = tag;
+      CompletionProcessor processor = new CompletionProcessor(tag);
 
       final XmlElement context = PsiTreeUtil.getContextOfType(myElement, XmlElement.class, false);
       if (context == null) {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java
index 2c963a9..4d4c3aa 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java
@@ -47,7 +47,7 @@
    * @param name
    * @param reference
    */
-  public SchemaPrefixReference(XmlElement element, TextRange range, String name, TagNameReference reference) {
+  public SchemaPrefixReference(XmlElement element, TextRange range, String name, @Nullable TagNameReference reference) {
     super(element, range);
     myName = name;
     myTagNameReference = reference;
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
index fba46a2..4e2055d 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
@@ -45,6 +45,11 @@
   }
 
   @Override
+  public boolean isEnumerated(XmlElement context) {
+    return isEnumerated();
+  }
+
+  @Override
   public String toString() {
     return getName();
   }
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/XmlEnumerationDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/XmlEnumerationDescriptor.java
index bf7b988..b77ed3a 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/XmlEnumerationDescriptor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/XmlEnumerationDescriptor.java
@@ -3,20 +3,23 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
-import com.intellij.psi.xml.XmlAttributeValue;
 import com.intellij.psi.xml.XmlElement;
 import com.intellij.xml.util.XmlEnumeratedValueReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author Dmitry Avdeev
  *         Date: 22.08.13
  */
-public abstract class XmlEnumerationDescriptor {
+public abstract class XmlEnumerationDescriptor<T extends XmlElement> {
 
   public abstract boolean isFixed();
 
   public abstract String getDefaultValue();
 
+  public abstract boolean isEnumerated(@Nullable XmlElement context);
+
   public abstract String[] getEnumeratedValues();
 
   public PsiElement getValueDeclaration(XmlElement attributeValue, String value) {
@@ -31,8 +34,7 @@
 
   protected abstract PsiElement getDefaultValueDeclaration();
 
-  public PsiReference[] getValueReferences(XmlAttributeValue value) {
-    return new PsiReference[] { new XmlEnumeratedValueReference(value, this)};
+  public PsiReference[] getValueReferences(T element, @NotNull String text) {
+    return new PsiReference[] { new XmlEnumeratedValueReference(element, this)};
   }
-
 }
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
index 61c33c0..3d3cab7 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
@@ -16,14 +16,17 @@
 package com.intellij.xml.impl.schema;
 
 import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.psi.ElementManipulators;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
 import com.intellij.psi.meta.PsiWritableMetaData;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.xml.*;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.xml.*;
+import com.intellij.xml.util.XmlEnumeratedValueReference;
 import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -36,7 +39,7 @@
 /**
  * @author Mike
  */
-public class XmlElementDescriptorImpl extends XsdEnumerationDescriptor
+public class XmlElementDescriptorImpl extends XsdEnumerationDescriptor<XmlTag>
   implements XmlElementDescriptor, PsiWritableMetaData, Validator<XmlTag>,
                                                  XmlElementDescriptorAwareAboutChildren {
   protected XmlTag myDescriptorTag;
@@ -473,8 +476,9 @@
   }
 
   public String getQualifiedName() {
-    if (!"".equals(getNS())) {
-      return getNS() + ":" + getName();
+    String ns = getNS();
+    if (ns != null && !ns.isEmpty()) {
+      return ns + ":" + getName();
     }
 
     return getName();
@@ -519,6 +523,16 @@
     }
   }
 
+  @Override
+  public PsiReference[] getValueReferences(XmlTag xmlTag, @NotNull String text) {
+    XmlTagValue value = xmlTag.getValue();
+    XmlText[] elements = value.getTextElements();
+    if (elements.length == 0 || xmlTag.getSubTags().length > 0) return PsiReference.EMPTY_ARRAY;
+    return new PsiReference[] {
+      new XmlEnumeratedValueReference(xmlTag, this, ElementManipulators.getValueTextRange(xmlTag))
+    };
+  }
+
   public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
     final TypeDescriptor type = getType(context);
     
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XsdEnumerationDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XsdEnumerationDescriptor.java
index 0a1c341..26600b7 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XsdEnumerationDescriptor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XsdEnumerationDescriptor.java
@@ -21,7 +21,7 @@
  * @author Dmitry Avdeev
  *         Date: 22.08.13
  */
-public abstract class XsdEnumerationDescriptor extends XmlEnumerationDescriptor {
+public abstract class XsdEnumerationDescriptor<T extends XmlElement> extends XmlEnumerationDescriptor<T> {
 
   private boolean myExhaustiveEnum;
 
@@ -60,7 +60,7 @@
   }
 
   private boolean processEnumeration(XmlElement context, PairProcessor<PsiElement, String> processor) {
-    XmlTag contextTag = context != null ? PsiTreeUtil.getContextOfType(context, XmlTag.class, true) : null;
+    XmlTag contextTag = context != null ? PsiTreeUtil.getContextOfType(context, XmlTag.class, false) : null;
     final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(getDeclaration(), contextTag);
 
     if (elementDescriptor!=null && elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java
index a25f605..ac01d81 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java
@@ -139,7 +139,8 @@
 
   @NonNls private static final String[] HTML5_TAGS = {
     "article", "aside", "audio", "canvas", "command", "datalist", "details", "embed", "figcaption", "figure", "footer", "header", "hgroup",
-    "keygen", "mark", "meter", "nav", "output", "progress", "rp", "rt", "ruby", "section", "source", "summary", "time", "video", "wbr"
+    "keygen", "mark", "meter", "nav", "output", "progress", "rp", "rt", "ruby", "section", "source", "summary", "time", "video", "wbr",
+    "main"
   };
   private static final Set<String> HTML5_TAGS_SET = new THashSet<String>();
 
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlEnumeratedValueReference.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlEnumeratedValueReference.java
index 5cf994a..6b1bdf4 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlEnumeratedValueReference.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlEnumeratedValueReference.java
@@ -17,9 +17,12 @@
 
 import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
 import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReferenceBase;
-import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
 import com.intellij.util.ArrayUtil;
 import com.intellij.xml.impl.XmlEnumerationDescriptor;
 import org.jetbrains.annotations.NotNull;
@@ -29,14 +32,19 @@
 * @author Dmitry Avdeev
 *         Date: 16.08.13
 */
-public class XmlEnumeratedValueReference extends PsiReferenceBase<XmlAttributeValue> implements EmptyResolveMessageProvider {
+public class XmlEnumeratedValueReference extends PsiReferenceBase<XmlElement> implements EmptyResolveMessageProvider {
   private final XmlEnumerationDescriptor myDescriptor;
 
-  public XmlEnumeratedValueReference(XmlAttributeValue value, XmlEnumerationDescriptor descriptor) {
+  public XmlEnumeratedValueReference(XmlElement value, XmlEnumerationDescriptor descriptor) {
     super(value);
     myDescriptor = descriptor;
   }
 
+  public XmlEnumeratedValueReference(XmlElement value, XmlEnumerationDescriptor descriptor, TextRange range) {
+    super(value, range);
+    myDescriptor = descriptor;
+  }
+
   @Nullable
   @Override
   public PsiElement resolve() {
@@ -59,8 +67,9 @@
   @NotNull
   @Override
   public String getUnresolvedMessagePattern() {
+    String name = getElement() instanceof XmlTag ? "tag" : "attribute";
     return myDescriptor.isFixed()
-           ? XmlErrorMessages.message("attribute.should.have.fixed.value", myDescriptor.getDefaultValue())
-           : XmlErrorMessages.message("wrong.attribute.value");
+           ? XmlErrorMessages.message("should.have.fixed.value", StringUtil.capitalize(name), myDescriptor.getDefaultValue())
+           : XmlErrorMessages.message("wrong.value", name);
   }
 }
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
index e8bb8f4..abbddfcf 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
@@ -933,6 +933,8 @@
     });
   }
 
+  private final static Set<String> doNotVisitTags = new HashSet<String>(Arrays.asList("annotation", "element", "attribute"));
+
   /**
    * @return true if enumeration is exhaustive
    */
@@ -954,7 +956,7 @@
         exhaustiveEnum = false;
         processEnumerationValues(tag, tagProcessor);
       }
-      else if (!localName.equals("annotation")) {
+      else if (!doNotVisitTags.contains(localName)) {
         // don't go into annotation
         exhaustiveEnum &= processEnumerationValues(tag, tagProcessor);
       }
@@ -1070,7 +1072,7 @@
     return new Pair<XmlTagChild, XmlTagChild>(first, last);
   }
 
-  public static boolean isSimpleXmlAttributeValue(@NotNull final String unquotedValue, final XmlAttributeValue context) {
+  public static boolean isSimpleValue(@NotNull final String unquotedValue, final PsiElement context) {
     for (int i = 0; i < unquotedValue.length(); ++i) {
       final char ch = unquotedValue.charAt(i);
       if (!Character.isJavaIdentifierPart(ch) && ch != ':' && ch != '-') {