Merge "Merge remote-tracking branch 'aosp/snapshot-master' into merge"
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 0b13401..d8fe919 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -90,9 +90,6 @@
         <XML>
           <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
         </XML>
-        <ADDITIONAL_INDENT_OPTIONS fileType="rb">
-          <option name="INDENT_SIZE" value="2" />
-        </ADDITIONAL_INDENT_OPTIONS>
         <codeStyleSettings language="CFML">
           <option name="KEEP_LINE_BREAKS" value="false" />
           <option name="ELSE_ON_NEW_LINE" value="true" />
@@ -265,6 +262,15 @@
             <option name="TAB_SIZE" value="8" />
           </indentOptions>
         </codeStyleSettings>
+        <codeStyleSettings language="ruby">
+          <option name="KEEP_LINE_BREAKS" value="false" />
+          <option name="PARENT_SETTINGS_INSTALLED" value="true" />
+          <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="8" />
+            <option name="TAB_SIZE" value="4" />
+            <option name="USE_RELATIVE_INDENTS" value="false" />
+          </indentOptions>
+        </codeStyleSettings>
       </value>
     </option>
     <option name="USE_PER_PROJECT_SETTINGS" value="true" />
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 25d4282..0e88b0f 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -26,6 +26,7 @@
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel target="1.6">
+      <module name="annotations" target="1.5" />
       <module name="groovy-rt-constants" target="1.5" />
       <module name="groovy_rt" target="1.5" />
       <module name="java-runtime" target="1.3" />
diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml
index 7cbf9804..3fbc531 100644
--- a/.idea/libraries/Netty.xml
+++ b/.idea/libraries/Netty.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Netty">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/lib/netty-3.6.6.Final.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/netty-all.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/lib/src/netty-3.6.6.Final-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/src/netty-all-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 33ad474..dfa52fc 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -116,6 +116,7 @@
       <module fileurl="file://$PROJECT_DIR$/../base/lint/cli/lint-cli.iml" filepath="$PROJECT_DIR$/../base/lint/cli/lint-cli.iml" group="plugins/Android/android-sdk/lint" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" filepath="$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/../base/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/../base/manifest-merger/manifest-merger.iml" group="plugins/Android/android-sdk" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
       <module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
@@ -138,6 +139,7 @@
       <module fileurl="file://$PROJECT_DIR$/xml/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/xml/relaxng/relaxng.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/platform/remote-servers/api/remote-servers-api.iml" filepath="$PROJECT_DIR$/platform/remote-servers/api/remote-servers-api.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/platform/remote-servers/impl/remote-servers-impl.iml" filepath="$PROJECT_DIR$/platform/remote-servers/impl/remote-servers-impl.iml" group="platform" />
+      <module fileurl="file://$PROJECT_DIR$/java/remote-servers/remote-servers-java.iml" filepath="$PROJECT_DIR$/java/remote-servers/remote-servers-java.iml" />
       <module fileurl="file://$PROJECT_DIR$/resources/resources.iml" filepath="$PROJECT_DIR$/resources/resources.iml" />
       <module fileurl="file://$PROJECT_DIR$/resources-en/resources-en.iml" filepath="$PROJECT_DIR$/resources-en/resources-en.iml" />
       <module fileurl="file://$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" filepath="$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" group="plugins/Android/android-sdk" />
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
index cb8806f..ec8ce05 100644
--- a/.idea/uiDesigner.xml
+++ b/.idea/uiDesigner.xml
@@ -138,9 +138,6 @@
       <item class="com.intellij.ui.ReferenceEditorComboWithBrowseButton" icon="/com/intellij/uiDesigner/icons/panel.png" removable="true" auto-create-binding="true" can-attach-label="true">
         <default-constraints vsize-policy="0" hsize-policy="7" anchor="0" fill="1" />
       </item>
-      <item class="com.intellij.ui.HyperlinkLabel" icon="" removable="true" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="0" />
-      </item>
     </group>
   </component>
   <component name="uidesigner-configuration">
diff --git a/build/conf/classVersions.txt b/build/conf/classVersions.txt
index f2a055b..7ccac5c 100644
--- a/build/conf/classVersions.txt
+++ b/build/conf/classVersions.txt
@@ -31,7 +31,8 @@
 1.3 => lib/idea_rt.jar
 
 1.7 => lib/fxHelpBrowser.jar
-- => lib/optimizedFileManager.jar
+1.7 => lib/optimizedFileManager.jar
 
 1.5 => plugins/Groovy/lib/groovy_rt.jar
+1.5 => lib/annotations.jar
 
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index b7475ea..37504c4 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -66,6 +66,7 @@
   List<String> implementationModules = [platformImplementationModules,
     "compiler-impl",
     "remote-servers-impl",
+    "remote-servers-java",
     "debugger-impl",
     "dom-impl",
     "execution-impl",
@@ -77,10 +78,10 @@
     "java-impl",
     "java-psi-impl",
     "jsp-spi",
+    "manifest",
     "platform-main",
     "testFramework",
-    "tests_bootstrap",
-          ].flatten()
+    "tests_bootstrap"].flatten()
 
   ant.patternset(id: "resources.included") {
     include(name: "**/*.properties")
@@ -466,6 +467,11 @@
       }
       fileset(dir: "$home/plugins/terminal/lib") {
         include(name: "*.jar")
+        include(name: "*.in")
+        include(name: "**/*.dll")
+        include(name: "**/*.exe")
+        include(name: "**/*.dylib")
+        include(name: "**/*.so")
       }
     }
   }
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index c099600..b4fd69a 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: "3.6.6", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
+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: "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")
@@ -265,6 +265,8 @@
 libraryLicense(name: "bouncy-castle", version: "1.48", license: "MIT License", url: "http://bouncycastle.org", licenseUrl: "http://bouncycastle.org/licence.html")
 libraryLicense(name: "kXML2", libraryName: "kxml2", version: "2.3.0", license: "BSD", url: "http://sourceforge.net/projects/kxml/")
 libraryLicense(name: "Lombok AST", libraryName: "lombok-ast", version: "0.2.1", license: "MIT", url: "http://projectlombok.org/", licenseUrl: "http://opensource.org/licenses/mit-license.php")
+libraryLicense(name: "json-path", libraryName: "json-path-0.8.0.jar", version: "0.8.0", license: "Apache 2.0", url: "http://code.google.com/p/json-path/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
+libraryLicense(name: "json-smart", libraryName: "json-smart-1.1.1.jar", version: "1.1.1", license: "Apache 2.0", url: "http://code.google.com/p/json-smart/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
 libraryLicense(name: "fxg-utils", libraryName: "fxg-utils", version: "4.9.1", license: "Apache 2.0", url: "http://flex.apache.org", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
 libraryLicense(name: "jayatana", libraryName: "jayatana", version: "1.2.4", license: "MIT License", url: "https://code.google.com/p/java-swing-ayatana/", licenseUrl: "http://opensource.org/licenses/mit-license.php")
 jetbrainsLibrary("JPS")
diff --git a/community-main.iml b/community-main.iml
index 9e92fe4..06e2a0a 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -61,11 +61,8 @@
     <orderEntry type="module" module-name="ui-designer" />
     <orderEntry type="module" module-name="devkit" />
     <orderEntry type="module" module-name="eclipse" />
-    <orderEntry type="module" module-name="generate-tostring" />
     <orderEntry type="module" module-name="git4idea" />
     <orderEntry type="module" module-name="images" />
-    <orderEntry type="module" module-name="InspectionGadgetsPlugin" />
-    <orderEntry type="module" module-name="IntentionPowerPackPlugin" />
     <orderEntry type="module" module-name="jetgroovy" />
     <orderEntry type="module" module-name="junit" />
     <orderEntry type="module" module-name="maven" />
@@ -91,16 +88,17 @@
     <orderEntry type="module" module-name="relaxng" />
     <orderEntry type="module" module-name="gradle" />
     <orderEntry type="module" module-name="remote-servers-impl" />
-    <orderEntry type="module" module-name="xml-tests" scope="TEST" />
     <orderEntry type="module" module-name="dom-tests" />
-    <orderEntry type="module" module-name="devkit-jps-plugin" scope="TEST" />
-    <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="colorSchemes" />
     <orderEntry type="module" module-name="javaFX-CE" />
     <orderEntry type="module" module-name="javaFX-jps-plugin" />
+    <orderEntry type="module" module-name="IntelliLang-tests" />
+    <orderEntry type="module" module-name="manifest" />
+    <orderEntry type="module" module-name="xml-tests" scope="TEST" />
+    <orderEntry type="module" module-name="devkit-jps-plugin" scope="TEST" />
+    <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="java-tests" scope="TEST" />
     <orderEntry type="module" module-name="community-tests" scope="TEST" />
-    <orderEntry type="module" module-name="IntelliLang-tests" />
   </component>
 </module>
 
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
index 27f61c4..810ce71 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java
@@ -47,7 +47,7 @@
   private static final String PROBLEMS_TOOLWINDOW_ID = "Problems";
   
   private final ProblemsViewPanel myPanel;
-  private final SequentialTaskExecutor myViewUpdater = new SequentialTaskExecutor(new PooledThreadExecutor());
+  private final SequentialTaskExecutor myViewUpdater = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
 
   public ProblemsViewImpl(final Project project, final ToolWindowManager wm) {
     super(project);
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index e885a16..1db0ada 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -80,20 +80,20 @@
 import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.net.NetUtils;
 import gnu.trove.THashSet;
-import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.channel.group.ChannelGroupFuture;
-import org.jboss.netty.channel.group.DefaultChannelGroup;
-import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
-import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.ide.PooledThreadExecutor;
+import org.jetbrains.io.ChannelRegistrar;
+import org.jetbrains.io.NettyUtil;
 import org.jetbrains.jps.api.*;
 import org.jetbrains.jps.cmdline.BuildMain;
 import org.jetbrains.jps.cmdline.ClasspathBootstrap;
@@ -106,7 +106,6 @@
 import java.net.InetSocketAddress;
 import java.nio.charset.Charset;
 import java.util.*;
-import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -117,7 +116,8 @@
  * @author Eugene Zhuravlev
  *         Date: 9/6/11
  */
-public class BuildManager implements ApplicationComponent{
+public class
+  BuildManager implements ApplicationComponent{
   public static final Key<Boolean> ALLOW_AUTOMAKE = Key.create("_allow_automake_when_process_is_active_");
   private static final Key<String> FORCE_MODEL_LOADING_PARAMETER = Key.create(BuildParametersKeys.FORCE_MODEL_LOADING);
 
@@ -152,8 +152,7 @@
   private final Map<RequestFuture, Project> myAutomakeFutures = new HashMap<RequestFuture, Project>();
   private final Map<String, RequestFuture> myBuildsInProgress = Collections.synchronizedMap(new HashMap<String, RequestFuture>());
   private final BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager();
-  private final Executor myPooledThreadExecutor = new PooledThreadExecutor();
-  private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(myPooledThreadExecutor);
+  private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
   private final Map<String, ProjectData> myProjectDataMap = Collections.synchronizedMap(new HashMap<String, ProjectData>());
 
   private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask() {
@@ -206,7 +205,8 @@
     }
   };
 
-  private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("build-manager");
+  private final ChannelRegistrar myChannelRegistrar = new ChannelRegistrar();
+
   private final BuildMessageDispatcher myMessageDispatcher = new BuildMessageDispatcher();
   private volatile int myListenPort = -1;
   @Nullable
@@ -354,7 +354,7 @@
                 final CmdlineRemoteProto.Message.ControllerMessage message =
                   CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
                     CmdlineRemoteProto.Message.ControllerMessage.Type.FS_EVENT).setFsEvent(data.createNextEvent()).build();
-                Channels.write(channel, CmdlineProtoUtil.toMessage(sessionId, message));
+                channel.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, message));
               }
             }
           }
@@ -574,7 +574,7 @@
           synchronized (myProjectDataMap) {
             ProjectData data = myProjectDataMap.get(projectPath);
             if (data == null) {
-              data = new ProjectData(new SequentialTaskExecutor(myPooledThreadExecutor));
+              data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
               myProjectDataMap.put(projectPath, data);
             }
             if (isRebuild) {
@@ -951,46 +951,25 @@
   }
 
   public void stopListening() {
-    final ChannelGroupFuture closeFuture = myAllOpenChannels.close();
-    closeFuture.awaitUninterruptibly();
+    myChannelRegistrar.close();
   }
 
   private int startListening() throws Exception {
-    final ChannelFactory channelFactory = new NioServerSocketChannelFactory(myPooledThreadExecutor, myPooledThreadExecutor, 1);
-    final SimpleChannelUpstreamHandler channelRegistrar = new SimpleChannelUpstreamHandler() {
+    final ServerBootstrap bootstrap = NettyUtil.nioServerBootstrap(new NioEventLoopGroup(1, PooledThreadExecutor.INSTANCE));
+    bootstrap.childHandler(new ChannelInitializer() {
       @Override
-      public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-        myAllOpenChannels.add(e.getChannel());
-        super.channelOpen(ctx, e);
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(myChannelRegistrar,
+                                   new ProtobufVarint32FrameDecoder(),
+                                   new ProtobufDecoder(CmdlineRemoteProto.Message.getDefaultInstance()),
+                                   new ProtobufVarint32LengthFieldPrepender(),
+                                   new ProtobufEncoder(),
+                                   myMessageDispatcher);
       }
-
-      @Override
-      public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-        myAllOpenChannels.remove(e.getChannel());
-        super.channelClosed(ctx, e);
-      }
-    };
-    ChannelPipelineFactory pipelineFactory = new ChannelPipelineFactory() {
-      @Override
-      public ChannelPipeline getPipeline() throws Exception {
-        return Channels.pipeline(
-          channelRegistrar,
-          new ProtobufVarint32FrameDecoder(),
-          new ProtobufDecoder(CmdlineRemoteProto.Message.getDefaultInstance()),
-          new ProtobufVarint32LengthFieldPrepender(),
-          new ProtobufEncoder(),
-          myMessageDispatcher
-        );
-      }
-    };
-    final ServerBootstrap bootstrap = new ServerBootstrap(channelFactory);
-    bootstrap.setPipelineFactory(pipelineFactory);
-    bootstrap.setOption("child.tcpNoDelay", true);
-    bootstrap.setOption("child.keepAlive", true);
-    final int listenPort = NetUtils.findAvailableSocketPort();
-    final Channel serverChannel = bootstrap.bind(new InetSocketAddress(NetUtils.getLoopbackAddress(), listenPort));
-    myAllOpenChannels.add(serverChannel);
-    return listenPort;
+    });
+    Channel serverChannel = bootstrap.bind(NetUtils.getLoopbackAddress(), 0).syncUninterruptibly().channel();
+    myChannelRegistrar.add(serverChannel);
+    return ((InetSocketAddress)serverChannel.localAddress()).getPort();
   }
 
   @TestOnly
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
index 0c49759..135b154 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
@@ -15,10 +15,13 @@
  */
 package com.intellij.compiler.server;
 
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.util.containers.ConcurrentHashSet;
-import org.jboss.netty.channel.*;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.util.AttributeKey;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.api.CmdlineProtoUtil;
 import org.jetbrains.jps.api.CmdlineRemoteProto;
@@ -32,8 +35,12 @@
 * @author Eugene Zhuravlev
 *         Date: 4/25/12
 */
-class BuildMessageDispatcher extends SimpleChannelHandler {
+@ChannelHandler.Sharable
+class BuildMessageDispatcher extends SimpleChannelInboundHandler<CmdlineRemoteProto.Message> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.server.BuildMessageDispatcher");
+
+  private static final AttributeKey<SessionData> SESSION_DATA = new AttributeKey<SessionData>("BuildMessageDispatcher.sessionData");
+
   private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>();
   private final Set<UUID> myCanceledSessions = new ConcurrentHashSet<UUID>();
 
@@ -54,7 +61,7 @@
     if (myCanceledSessions.add(sessionId)) {
       final Channel channel = getConnectedChannel(sessionId);
       if (channel != null) {
-        Channels.write(channel, CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createCancelCommand()));
+        channel.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createCancelCommand()));
       }
     }
   }
@@ -62,7 +69,7 @@
   @Nullable
   public Channel getConnectedChannel(final UUID sessionId) {
     final Channel channel = getAssociatedChannel(sessionId);
-    return channel != null && channel.isConnected()? channel : null;
+    return channel != null && channel.isActive()? channel : null;
   }
 
   @Nullable
@@ -73,10 +80,8 @@
 
 
   @Override
-  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-    final CmdlineRemoteProto.Message message = (CmdlineRemoteProto.Message)e.getMessage();
-
-    SessionData sessionData = (SessionData)ctx.getAttachment();
+  protected void channelRead0(ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
+    SessionData sessionData = context.attr(SESSION_DATA).get();
 
     UUID sessionId;
     if (sessionData == null) {
@@ -86,11 +91,11 @@
 
       sessionData = myMessageHandlers.get(sessionId);
       if (sessionData != null) {
-        sessionData.channel = ctx.getChannel();
-        ctx.setAttachment(sessionData);
+        sessionData.channel = context.channel();
+        context.attr(SESSION_DATA).set(sessionData);
       }
       if (myCanceledSessions.contains(sessionId)) {
-        Channels.write(ctx.getChannel(), CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createCancelCommand()));
+        context.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createCancelCommand()));
       }
     }
     else {
@@ -118,14 +123,14 @@
           if (params != null) {
             handler.buildStarted(sessionId);
             sessionData.params = null;
-            Channels.write(ctx.getChannel(), CmdlineProtoUtil.toMessage(sessionId, params));
+            context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params));
           }
           else {
             cancelSession(sessionId);
           }
         }
         else {
-          handler.handleBuildMessage(ctx.getChannel(), sessionId, builderMessage);
+          handler.handleBuildMessage(context.channel(), sessionId, builderMessage);
         }
         break;
 
@@ -136,12 +141,12 @@
   }
 
   @Override
-  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+  public void channelInactive(ChannelHandlerContext context) throws Exception {
     try {
-      super.channelClosed(ctx, e);
+      super.channelInactive(context);
     }
     finally {
-      final SessionData sessionData = (SessionData)ctx.getAttachment();
+      final SessionData sessionData = context.attr(SESSION_DATA).get();
       if (sessionData != null) {
         final BuilderMessageHandler handler = unregisterBuildMessageHandler(sessionData.sessionId);
         if (handler != null) {
@@ -153,31 +158,10 @@
   }
 
   @Override
-  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
-    final Throwable cause = e.getCause();
+  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
     if (cause != null) {
       LOG.info(cause);
     }
-    ctx.sendUpstream(e);
-  }
-
-  @Override
-  public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-    try {
-      super.channelDisconnected(ctx, e);
-    }
-    finally {
-      final SessionData sessionData = (SessionData)ctx.getAttachment();
-      if (sessionData != null) { // this is the context corresponding to some session
-        final Channel channel = e.getChannel();
-        ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
-          @Override
-          public void run() {
-            channel.close();
-          }
-        });
-      }
-    }
   }
 
   private static final class SessionData {
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuilderMessageHandler.java b/java/compiler/impl/src/com/intellij/compiler/server/BuilderMessageHandler.java
index fadf63b..4681f85 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuilderMessageHandler.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuilderMessageHandler.java
@@ -15,7 +15,7 @@
  */
 package com.intellij.compiler.server;
 
-import org.jboss.netty.channel.Channel;
+import io.netty.channel.Channel;
 import org.jetbrains.jps.api.CmdlineRemoteProto;
 
 import java.util.UUID;
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java b/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
index 35091f7..3cb1260 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
@@ -16,7 +16,7 @@
 package com.intellij.compiler.server;
 
 import com.intellij.compiler.make.CachingSearcher;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.ProcessCanceledException;
@@ -30,8 +30,7 @@
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.cls.ClsUtil;
 import com.intellij.util.concurrency.SequentialTaskExecutor;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.Channels;
+import io.netty.channel.Channel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.ide.PooledThreadExecutor;
@@ -50,7 +49,7 @@
   private final Project myProject;
   private int myConstantSearchesCount = 0;
   private final CachingSearcher mySearcher;
-  private final SequentialTaskExecutor myTaskExecutor = new SequentialTaskExecutor(new PooledThreadExecutor());
+  private final SequentialTaskExecutor myTaskExecutor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
 
   protected DefaultMessageHandler(Project project) {
     myProject = project;
@@ -102,6 +101,7 @@
       }
       else {
         ApplicationManager.getApplication().runReadAction(new Runnable() {
+          @Override
           public void run() {
             try {
               String qualifiedName = ownerClassName.replace('$', '.');
@@ -137,8 +137,8 @@
                       continue;
                     }
                     foundAtLeastOne = true;
-                    final boolean sucess = performChangedConstantSearch(aClass, changedField, accessFlags, accessChanged, affectedPaths);
-                    if (!sucess) {
+                    final boolean success = performChangedConstantSearch(aClass, changedField, accessFlags, accessChanged, affectedPaths);
+                    if (!success) {
                       isSuccess.set(Boolean.FALSE);
                       break;
                     }
@@ -175,7 +175,7 @@
         builder.setIsSuccess(false);
         LOG.debug("Constant search task: unsuccessful");
       }
-      Channels.write(channel, CmdlineProtoUtil.toMessage(sessionId, CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
+      channel.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
         CmdlineRemoteProto.Message.ControllerMessage.Type.CONSTANT_SEARCH_RESULT).setConstantSearchResult(builder.build()).build()
       ));
     }
@@ -219,11 +219,11 @@
         //}
       }
     }
-    catch (PsiInvalidElementAccessException e) {
+    catch (PsiInvalidElementAccessException ignored) {
       LOG.debug("Constant search task: PIEAE thrown while searching of usages of changed constant");
       return false;
     }
-    catch (ProcessCanceledException e) {
+    catch (ProcessCanceledException ignored) {
       LOG.debug("Constant search task: PCE thrown while searching of usages of changed constant");
       return false;
     }
@@ -262,7 +262,7 @@
           }
           return true;
         }
-        catch (PsiInvalidElementAccessException e) {
+        catch (PsiInvalidElementAccessException ignored) {
           result.set(Boolean.FALSE);
           LOG.debug("Constant search task: PIEAE thrown while searching of usages of removed constant");
           return false;
@@ -285,6 +285,7 @@
 
   private static boolean processIdentifiers(PsiSearchHelper helper, @NotNull final PsiElementProcessor<PsiIdentifier> processor, @NotNull final String identifier, @NotNull SearchScope searchScope, short searchContext) {
     TextOccurenceProcessor processor1 = new TextOccurenceProcessor() {
+      @Override
       public boolean execute(PsiElement element, int offsetInElement) {
         return !(element instanceof PsiIdentifier) || processor.execute((PsiIdentifier)element);
       }
@@ -332,7 +333,7 @@
         if (containingFile == null) {
           return null;
         }
-        return StdLanguages.JAVA.equals(containingFile.getLanguage())? psiClass : null;
+        return JavaLanguage.INSTANCE.equals(containingFile.getLanguage())? psiClass : null;
       }
       element = element.getParent();
     }
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java
index a90ff9b..68b5d5c 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/MessageHandlerWrapper.java
@@ -1,6 +1,6 @@
 package com.intellij.compiler.server;
 
-import org.jboss.netty.channel.Channel;
+import io.netty.channel.Channel;
 import org.jetbrains.jps.api.CmdlineRemoteProto;
 
 import java.util.UUID;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java
index 7476456..0b1fc42 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java
@@ -146,7 +146,11 @@
 
   private void updateOutputPathPresentation() {
     if (getCompilerExtension().isCompilerOutputPathInherited()) {
-      final String baseUrl = ProjectStructureConfigurable.getInstance(myProject).getProjectConfig().getCompilerOutputUrl();
+      ProjectConfigurable projectConfig = ProjectStructureConfigurable.getInstance(myProject).getProjectConfig();
+      if (projectConfig == null) {
+        return;
+      }
+      final String baseUrl = projectConfig.getCompilerOutputUrl();
       moduleCompileOutputChanged(baseUrl, getModel().getModule().getName());
     } else {
       final VirtualFile compilerOutputPath = getCompilerExtension().getCompilerOutputPath();
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 fd855a7..9c6343a 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
@@ -60,6 +60,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableFilter.ConfigurableId;
+
 public class ProjectStructureConfigurable extends BaseConfigurable implements SearchableConfigurable, Place.Navigator {
 
   public static final DataKey<ProjectStructureConfigurable> KEY = DataKey.create("ProjectStructureConfiguration");
@@ -220,13 +222,40 @@
       addFacetsConfig();
       addArtifactsConfig();
     }
+
+    ProjectStructureConfigurableAdder[] adders = ProjectStructureConfigurableAdder.EP_NAME.getExtensions();
+    for (ProjectStructureConfigurableAdder adder : adders) {
+      for (Configurable configurable : adder.getExtraProjectConfigurables(myProject, myContext)) {
+        addConfigurable(configurable, true);
+      }
+    }
+
     mySidePanel.addSeparator("Platform Settings");
     addJdkListConfig();
     addGlobalLibrariesConfig();
+
+    for (ProjectStructureConfigurableAdder adder : adders) {
+      for (Configurable configurable : adder.getExtraPlatformConfigurables(myProject, myContext)) {
+        addConfigurable(configurable, true);
+      }
+    }
   }
 
   private void addArtifactsConfig() {
-    addConfigurable(myArtifactsStructureConfigurable);
+    addConfigurable(myArtifactsStructureConfigurable, ConfigurableId.ARTIFACTS);
+  }
+
+  private void addConfigurable(final Configurable configurable, final ConfigurableId configurableId) {
+    addConfigurable(configurable, isAvailable(configurableId));
+  }
+
+  private boolean isAvailable(ConfigurableId id) {
+    for (ProjectStructureConfigurableFilter filter : ProjectStructureConfigurableFilter.EP_NAME.getExtensions()) {
+      if (!filter.isAvailable(id, myProject)) {
+        return false;
+      }
+    }
+    return true;
   }
 
   public ArtifactsStructureConfigurable getArtifactsStructureConfigurable() {
@@ -235,7 +264,7 @@
 
   private void addFacetsConfig() {
     if (myFacetStructureConfigurable.isVisible()) {
-      addConfigurable(myFacetStructureConfigurable);
+      addConfigurable(myFacetStructureConfigurable, ConfigurableId.FACETS);
     }
   }
 
@@ -244,25 +273,25 @@
       myJdkListConfig = JdkListConfigurable.getInstance(myProject);
       myJdkListConfig.init(myContext);
     }
-    addConfigurable(myJdkListConfig);
+    addConfigurable(myJdkListConfig, ConfigurableId.JDK_LIST);
   }
 
   private void addProjectConfig() {
     myProjectConfig = new ProjectConfigurable(myProject, myContext, myModuleConfigurator, myProjectJdksModel);
-    addConfigurable(myProjectConfig);
+    addConfigurable(myProjectConfig, ConfigurableId.PROJECT);
   }
 
   private void addProjectLibrariesConfig() {
-    addConfigurable(myProjectLibrariesConfig);
+    addConfigurable(myProjectLibrariesConfig, ConfigurableId.PROJECT_LIBRARIES);
   }
 
   private void addGlobalLibrariesConfig() {
-    addConfigurable(myGlobalLibrariesConfig);
+    addConfigurable(myGlobalLibrariesConfig, ConfigurableId.GLOBAL_LIBRARIES);
   }
 
   private void addModulesConfig() {
     myModulesConfig = ModuleStructureConfigurable.getInstance(myProject);
-    addConfigurable(myModulesConfig);
+    addConfigurable(myModulesConfig, ConfigurableId.MODULES);
   }
 
   @Override
@@ -579,10 +608,12 @@
     return myProjectConfig;
   }
 
-  private void addConfigurable(Configurable configurable) {
+  private void addConfigurable(Configurable configurable, boolean addToSidePanel) {
     myName2Config.add(configurable);
 
-    mySidePanel.addPlace(createPlaceFor(configurable), new Presentation(configurable.getDisplayName()));
+    if (addToSidePanel) {
+      mySidePanel.addPlace(createPlaceFor(configurable), new Presentation(configurable.getDisplayName()));
+    }
   }
 
   private static Place createPlaceFor(final Configurable configurable) {
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/ProjectStructureConfigurableAdder.java
new file mode 100644
index 0000000..4a79ada
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableAdder.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 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.extensions.ExtensionPointName;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class ProjectStructureConfigurableAdder {
+  public static final ExtensionPointName<ProjectStructureConfigurableAdder> EP_NAME = ExtensionPointName.create("com.intellij.projectStructureConfigurableAdder");
+
+  @NotNull
+  public List<? extends Configurable> getExtraProjectConfigurables(@NotNull Project project, @NotNull StructureConfigurableContext context) {
+    return Collections.emptyList();
+  }
+
+  @NotNull
+  public List<? extends Configurable> getExtraPlatformConfigurables(@NotNull Project project, @NotNull StructureConfigurableContext context) {
+    return Collections.emptyList();
+  }
+
+}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableFilter.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableFilter.java
new file mode 100644
index 0000000..9866675
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurableFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class ProjectStructureConfigurableFilter {
+  public static final ExtensionPointName<ProjectStructureConfigurableFilter> EP_NAME = ExtensionPointName.create("com.intellij.projectStructureConfigurableFilter");
+
+  public enum ConfigurableId {
+    PROJECT, MODULES, PROJECT_LIBRARIES, FACETS, ARTIFACTS, JDK_LIST, GLOBAL_LIBRARIES
+  }
+
+  public abstract boolean isAvailable(@NotNull ConfigurableId id, @NotNull Project project);
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
index d803b32..987f02d 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
@@ -121,17 +121,9 @@
     else {
       final PsiFile containingFile = myModifierListOwner.getContainingFile();
       if (!FileModificationService.getInstance().preparePsiElementForWrite(containingFile)) return;
-      for (String fqn : myAnnotationsToRemove) {
-        PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn);
-        if (annotation != null) {
-          annotation.delete();
-        }
-      }
+      removePhysicalAnnotations(myModifierListOwner, myAnnotationsToRemove);
 
-      PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation);
-      for (PsiNameValuePair pair : myPairs) {
-        inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
-      }
+      PsiAnnotation inserted = addPhysicalAnnotation(myAnnotation, myPairs, modifierList);
       JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
       if (containingFile != file) {
         UndoUtil.markPsiFileForUndo(file);
@@ -139,6 +131,23 @@
     }
   }
 
+  public static PsiAnnotation addPhysicalAnnotation(String fqn, PsiNameValuePair[] pairs, PsiModifierList modifierList) {
+    PsiAnnotation inserted = modifierList.addAnnotation(fqn);
+    for (PsiNameValuePair pair : pairs) {
+      inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
+    }
+    return inserted;
+  }
+
+  public static void removePhysicalAnnotations(PsiModifierListOwner owner, String... fqns) {
+    for (String fqn : fqns) {
+      PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, fqn);
+      if (annotation != null) {
+        annotation.delete();
+      }
+    }
+  }
+
   @NotNull
   public String[] getAnnotationsToRemove() {
     return myAnnotationsToRemove;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
index ee7a96a..144be8a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
@@ -26,6 +26,7 @@
 import com.intellij.openapi.util.Key;
 import com.intellij.psi.*;
 import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.psi.util.MethodSignature;
 import com.intellij.psi.util.PsiFormatUtil;
 import com.intellij.psi.util.PsiFormatUtilBase;
 import com.intellij.ui.RowIcon;
@@ -35,6 +36,7 @@
 import javax.swing.*;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
 import static com.intellij.patterns.PlatformPatterns.psiElement;
 
@@ -55,15 +57,16 @@
       andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
       final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
       if (parent != null) {
-        addGetterSetterElements(result, parent);
-        addSuperSignatureElements(parent, true, result);
-        addSuperSignatureElements(parent, false, result);
+        Set<MethodSignature> addedSignatures = ContainerUtil.newHashSet();
+        addGetterSetterElements(result, parent, addedSignatures);
+        addSuperSignatureElements(parent, true, result, addedSignatures);
+        addSuperSignatureElements(parent, false, result, addedSignatures);
       }
     }
 
   }
 
-  private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent) {
+  private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent, Set<MethodSignature> addedSignatures) {
     List<PsiMethod> prototypes = ContainerUtil.newArrayList();
     for (PsiField field : parent.getFields()) {
       if (!(field instanceof PsiEnumConstant)) {
@@ -72,7 +75,7 @@
       }
     }
     for (final PsiMethod prototype : prototypes) {
-      if (parent.findMethodBySignature(prototype, false) == null) {
+      if (parent.findMethodBySignature(prototype, false) == null && addedSignatures.add(prototype.getSignature(PsiSubstitutor.EMPTY))) {
         Icon icon = prototype.getIcon(Iconable.ICON_FLAG_VISIBILITY);
         result.addElement(createGenerateMethodElement(prototype, PsiSubstitutor.EMPTY, icon, "", new InsertHandler<LookupElement>() {
           @Override
@@ -91,13 +94,14 @@
     context.commitDocument();
   }
 
-  private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
+  private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result, Set<MethodSignature> addedSignatures) {
     for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
       PsiMethod baseMethod = (PsiMethod)candidate.getElement();
       assert baseMethod != null;
       PsiClass baseClass = baseMethod.getContainingClass();
-      if (!baseMethod.isConstructor() && baseClass != null) {
-        result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor()));
+      PsiSubstitutor substitutor = candidate.getSubstitutor();
+      if (!baseMethod.isConstructor() && baseClass != null && addedSignatures.add(baseMethod.getSignature(substitutor))) {
+        result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, substitutor));
       }
     }
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
index 6d03085..73a9e5e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
@@ -130,16 +130,21 @@
 
     if (myExpectedInfos != null) {
       final PsiType itemType = JavaCompletionUtil.getLookupElementType(element);
-      for (final ExpectedTypeInfo expectedInfo : myExpectedInfos) {
-        PsiMethod calledMethod = expectedInfo.getCalledMethod();
-        if (itemType != null &&
-            calledMethod != null &&
-            calledMethod.equals(myPositionMethod) &&
-            expectedInfo.getType().isAssignableFrom(itemType)) {
-          return myDelegate ? Result.delegation : Result.recursive;
+      if (itemType != null) {
+        boolean hasRecursiveInvocations = false;
+        boolean hasOtherInvocations = false;
+
+        for (final ExpectedTypeInfo expectedInfo : myExpectedInfos) {
+          PsiMethod calledMethod = expectedInfo.getCalledMethod();
+          if (!expectedInfo.getType().isAssignableFrom(itemType)) continue;
+
+          if (calledMethod != null && calledMethod.equals(myPositionMethod) || isGetterSetterAssignment(object, calledMethod)) {
+            hasRecursiveInvocations = true;
+          } else if (calledMethod != null) {
+            hasOtherInvocations = true;
+          }
         }
-        String propertyName = getSetterPropertyName(calledMethod);
-        if (propertyName != null && isGetterSetterAssignment(object, propertyName)) {
+        if (hasRecursiveInvocations && !hasOtherInvocations) {
           return myDelegate ? Result.delegation : Result.recursive;
         }
       }
@@ -178,7 +183,10 @@
     return null;
   }
 
-  private static boolean isGetterSetterAssignment(Object lookupObject, String prop) {
+  private boolean isGetterSetterAssignment(Object lookupObject, @Nullable PsiMethod calledMethod) {
+    String prop = getSetterPropertyName(calledMethod);
+    if (prop == null) return false;
+
     if (lookupObject instanceof PsiField &&
         prop.equals(PropertyUtil.suggestPropertyName((PsiField)lookupObject))) {
       return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
index 10de8bf..8af7f8b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
@@ -806,7 +806,7 @@
     DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(myProject);
     PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
     // dont optimize out imports in JSP since it can be included in other JSP
-    if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof JspFile) return false;
+    if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
 
     if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
     boolean errors = containsErrorsPreventingOptimize(file);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 2cbde60..ac90dce 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -252,14 +252,14 @@
                                                        referenceClass != null ? HighlightUtil.formatClass(referenceClass) : type.getPresentableText(),
                                                        JavaHighlightUtil.formatType(bound));
 
-        final HighlightInfo highlightInfo =
+        final HighlightInfo info =
           HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement2Highlight).descriptionAndTooltip(description).create();
-        if (bound instanceof PsiClassType && referenceClass != null) {
+        if (bound instanceof PsiClassType && referenceClass != null && info != null) {
           QuickFixAction
-            .registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(referenceClass, (PsiClassType)bound, true),
+            .registerQuickFixAction(info, QUICK_FIX_FACTORY.createExtendsListFix(referenceClass, (PsiClassType)bound, true),
                                     null);
         }
-        return highlightInfo;
+        return info;
       }
     }
     return null;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 449df8e..e2babf5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -47,7 +47,6 @@
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.*;
 import com.intellij.refactoring.util.RefactoringChangeUtil;
@@ -893,7 +892,7 @@
     PsiClass outerClass = aClass.getContainingClass();
     if (outerClass == null) return null;
 
-    if (outerClass instanceof JspClass || hasEnclosingInstanceInScope(outerClass, placeToSearchEnclosingFrom, true, false)) return null;
+    if (outerClass instanceof PsiSyntheticClass || hasEnclosingInstanceInScope(outerClass, placeToSearchEnclosingFrom, true, false)) return null;
     return reportIllegalEnclosingUsage(placeToSearchEnclosingFrom, aClass, outerClass, element);
   }
 
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 0aa08d0b..636b033 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
@@ -1198,7 +1198,8 @@
     return null;
   }
 
-  public static TextRange getFixRange(PsiElement element) {
+  @NotNull
+  public static TextRange getFixRange(@NotNull PsiElement element) {
     TextRange range = element.getTextRange();
     int start = range.getStartOffset();
     int end = range.getEndOffset();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java
index a8c041e..b9ea90c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java
@@ -19,21 +19,19 @@
  */
 package com.intellij.codeInsight.daemon.impl.analysis;
 
-import com.intellij.application.options.colors.ColorAndFontOptions;
-import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
-import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
+import com.intellij.application.options.colors.ScopeAttributesUtil;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
 import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
 import com.intellij.openapi.editor.colors.TextAttributesScheme;
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.packageDependencies.DependencyValidationManager;
+import com.intellij.packageDependencies.DependencyValidationManagerImpl;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import com.intellij.psi.impl.source.tree.ElementType;
 import com.intellij.psi.impl.source.tree.TreeUtil;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
@@ -233,14 +231,14 @@
     PsiFile file = element.getContainingFile();
     if (file == null) return null;
     TextAttributes result = null;
-    final DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(file.getProject());
-    List<Pair<NamedScope,NamedScopesHolder>> scopes = daemonCodeAnalyzer.getScopeBasedHighlightingCachedScopes();
+    DependencyValidationManagerImpl validationManager = (DependencyValidationManagerImpl)DependencyValidationManager.getInstance(file.getProject());
+    List<Pair<NamedScope,NamedScopesHolder>> scopes = validationManager.getScopeBasedHighlightingCachedScopes();
     for (Pair<NamedScope, NamedScopesHolder> scope : scopes) {
       NamedScope namedScope = scope.getFirst();
       NamedScopesHolder scopesHolder = scope.getSecond();
       PackageSet packageSet = namedScope.getValue();
       if (packageSet != null && packageSet.contains(file, scopesHolder)) {
-        TextAttributesKey scopeKey = ColorAndFontOptions.getScopeTextAttributeKey(namedScope.getName());
+        TextAttributesKey scopeKey = ScopeAttributesUtil.getScopeTextAttributeKey(namedScope.getName());
         TextAttributes attributes = colorsScheme.getAttributes(scopeKey);
         if (attributes == null || attributes.isEmpty()) {
           continue;
@@ -252,7 +250,7 @@
   }
 
   public static TextRange getMethodDeclarationTextRange(@NotNull PsiMethod method) {
-    if (method instanceof JspHolderMethod) return TextRange.EMPTY_RANGE;
+    if (method instanceof SyntheticElement) return TextRange.EMPTY_RANGE;
     int start = stripAnnotationsFromModifierList(method.getModifierList());
     final TextRange throwsRange = method.getThrowsList().getTextRange();
     LOG.assertTrue(throwsRange != null, method);
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 5c59702..5657a40 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
@@ -2603,11 +2603,13 @@
     return info;
   }
 
-  public static void registerChangeVariableTypeFixes(PsiVariable parameter, PsiType itemType, HighlightInfo highlightInfo) {
+  public static void registerChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType, HighlightInfo highlightInfo) {
     if (itemType instanceof PsiMethodReferenceType) return;
-    for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
-      for (IntentionAction action : fixProvider.getFixes(parameter, itemType)) {
-        QuickFixAction.registerQuickFixAction(highlightInfo, action);
+    if (itemType != null) {
+      for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
+        for (IntentionAction action : fixProvider.getFixes(parameter, itemType)) {
+          QuickFixAction.registerQuickFixAction(highlightInfo, action);
+        }
       }
     }
     ChangeParameterClassFix.registerQuickFixAction(parameter.getType(), itemType, highlightInfo);
@@ -2656,10 +2658,12 @@
     LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"),
     TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations");
 
+    @NotNull
     private final LanguageLevel level;
+    @NotNull
     private final String key;
 
-    Feature(final LanguageLevel level, @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) {
+    Feature(@NotNull LanguageLevel level, @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) {
       this.level = level;
       this.key = key;
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
index a4db183..a3f235e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
@@ -21,11 +21,10 @@
 import com.intellij.openapi.diagnostic.Logger;
 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.projectRoots.JavaSdk;
 import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.JdkVersionUtil;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.roots.*;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -43,7 +42,7 @@
 
   private final LanguageLevel myLevel;
 
-  public IncreaseLanguageLevelFix(LanguageLevel targetLevel) {
+  public IncreaseLanguageLevelFix(@NotNull LanguageLevel targetLevel) {
     myLevel = targetLevel;
   }
 
@@ -59,10 +58,10 @@
     return CodeInsightBundle.message("set.language.level");
   }
 
-  private static boolean isJdkSupportsLevel(@Nullable final Sdk jdk, final LanguageLevel level) {
+  private static boolean isJdkSupportsLevel(@Nullable final Sdk jdk, @NotNull LanguageLevel level) {
     if (jdk == null) return true;
-    final JavaSdk sdk = JavaSdk.getInstance();
-    final JavaSdkVersion version = sdk.getVersion(jdk);
+    String versionString = jdk.getVersionString();
+    JavaSdkVersion version = versionString == null ? null : JdkVersionUtil.getVersion(versionString);
     return version != null && version.getMaxLanguageLevel().isAtLeast(level);
   }
 
@@ -74,7 +73,7 @@
     return isLanguageLevelAcceptable(project, module, myLevel);
   }
 
-  public static boolean isLanguageLevelAcceptable(final Project project, Module module, final LanguageLevel level) {
+  private static boolean isLanguageLevelAcceptable(@NotNull Project project, Module module, @NotNull LanguageLevel level) {
     return isJdkSupportsLevel(getRelevantJdk(project, module), level);
   }
 
@@ -100,7 +99,7 @@
   }
 
   @Nullable
-  private static Sdk getRelevantJdk(final Project project, @Nullable Module module) {
+  private static Sdk getRelevantJdk(@NotNull Project project, @Nullable Module module) {
     Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk();
     Sdk moduleJdk = module == null ? null : ModuleRootManager.getInstance(module).getSdk();
     return moduleJdk == null ? projectJdk : moduleJdk;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
index ac607483..2fc03f8 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
@@ -38,7 +38,6 @@
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.codeStyle.SuggestedNameInfo;
 import com.intellij.psi.codeStyle.VariableKind;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -91,7 +90,7 @@
            && field.getManager().isInProject(field)
            && !field.hasModifierProperty(PsiModifier.STATIC)
            && containingClass != null
-           && !(containingClass instanceof JspClass)
+           && !(containingClass instanceof PsiSyntheticClass)
            && containingClass.getName() != null;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
index b30a19f..06704aa 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
@@ -28,12 +28,12 @@
 import com.intellij.psi.util.PsiUtil;
 import org.jetbrains.annotations.NotNull;
 
-import java.util.HashMap;
+import java.util.EnumMap;
 import java.util.Map;
 
 public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
   @Override
-  public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new ImportClassFix(ref));
     registrar.register(SetupJDKFix.getInstance());
 
@@ -80,7 +80,7 @@
                                               @NotNull PsiReferenceExpression refExpr) {
     final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
 
-    final Map<VariableKind, IntentionAction> map = new HashMap<VariableKind, IntentionAction>();
+    final Map<VariableKind, IntentionAction> map = new EnumMap<VariableKind, IntentionAction>(VariableKind.class);
     map.put(VariableKind.FIELD, new CreateFieldFromUsageFix(refExpr));
     map.put(VariableKind.STATIC_FINAL_FIELD, new CreateConstantFieldFromUsageFix(refExpr));
     if (!refExpr.isQualified()) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeQuickFixProvider.java
index 5b500b8..46b172a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeQuickFixProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeQuickFixProvider.java
@@ -24,10 +24,12 @@
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.psi.PsiVariable;
 import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
 
 public class VariableTypeQuickFixProvider implements ChangeVariableTypeQuickFixProvider{
+  @NotNull
   @Override
-  public IntentionAction[] getFixes(PsiVariable variable, PsiType toReturn) {
+  public IntentionAction[] getFixes(@NotNull PsiVariable variable, @NotNull PsiType toReturn) {
     return new IntentionAction[]{new VariableTypeFix(variable, toReturn)};
   }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MethodCallFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MethodCallFixer.java
index 041149c..0f9bc4f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MethodCallFixer.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MethodCallFixer.java
@@ -61,7 +61,9 @@
       }
 
       final PsiExpression[] params = args.getExpressions();
-      if (params.length > 0 && startLine(editor, args) != startLine(editor, params[0])) {
+      if (params.length > 0 && 
+          startLine(editor, args) != startLine(editor, params[0]) && 
+          editor.getCaretModel().getOffset() < params[0].getTextRange().getStartOffset()) {
         endOffset = args.getTextRange().getStartOffset() + 1;
       }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
index 1b08887..c6cdb98 100644
--- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
@@ -22,7 +22,6 @@
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import org.jetbrains.annotations.Nullable;
 
 public class JavaFoldingBuilder extends JavaFoldingBuilderBase {
@@ -47,8 +46,9 @@
   @Nullable
   @Override
   public TextRange getRangeToFold(PsiElement element) {
-    if (element instanceof JspHolderMethod)
+    if (element instanceof SyntheticElement) {
       return null;
+    }
     return super.getRangeToFold(element);    //To change body of overridden methods use File | Settings | File Templates.
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
index 01d7187..f33c6e4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
@@ -20,6 +20,7 @@
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.MethodImplementor;
 import com.intellij.codeInsight.intention.AddAnnotationFix;
+import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
 import com.intellij.featureStatistics.FeatureUsageTracker;
 import com.intellij.featureStatistics.ProductivityFeatureNames;
 import com.intellij.ide.fileTemplates.FileTemplate;
@@ -53,7 +54,6 @@
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.infos.CandidateInfo;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -246,7 +246,7 @@
 
   public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden, boolean insertOverride) {
     if (insertOverride && canInsertOverride(overridden, targetClass)) {
-      annotate(method, Override.class.getName());
+      AddAnnotationPsiFix.addPhysicalAnnotation(Override.class.getName(), PsiNameValuePair.EMPTY_ARRAY, method.getModifierList());
     }
     final Module module = ModuleUtilCore.findModuleForPsiElement(targetClass);
     final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;
@@ -256,7 +256,8 @@
       for (String annotation : each.getAnnotations(project)) {
         if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue;
         if (AnnotationUtil.isAnnotated(overridden, annotation, false, false)) {
-          annotate(method, annotation, each.annotationsToRemove(project, annotation));
+          AddAnnotationPsiFix.removePhysicalAnnotations(method, each.annotationsToRemove(project, annotation));
+          AddAnnotationPsiFix.addPhysicalAnnotation(annotation, PsiNameValuePair.EMPTY_ARRAY, method.getModifierList());
         }
       }
     }
@@ -577,7 +578,7 @@
       if (name != null) {
         MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, nextBaseMethod.getParameterList(), nextBaseMethod.getTypeParameterList(), substitutor, nextBaseMethod.isConstructor());
         PsiMethod nextMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
-        if (nextMethod != null){
+        if (nextMethod != null && nextMethod.isPhysical()){
           return nextMethod;
         }
       }
@@ -624,7 +625,7 @@
     while (element instanceof PsiTypeParameter);
 
     final PsiClass aClass = (PsiClass)element;
-    if (aClass instanceof JspClass) return null;
+    if (aClass instanceof PsiSyntheticClass) return null;
     return aClass == null || !allowInterface && aClass.isInterface() ? null : aClass;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java
index 556c762..4756a5b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java
@@ -26,7 +26,6 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.util.RefactoringChangeUtil;
@@ -52,7 +51,7 @@
     if (!field.hasInitializer()) return false;
     PsiClass psiClass = field.getContainingClass();
 
-    return psiClass != null && !psiClass.isInterface() && !(psiClass instanceof PsiAnonymousClass) && !(psiClass instanceof JspClass);
+    return psiClass != null && !psiClass.isInterface() && !(psiClass instanceof PsiAnonymousClass) && !(psiClass instanceof PsiSyntheticClass);
   }
 
   private boolean hasUnsuitableModifiers(@NotNull PsiField field) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
index c740b78..f06bf08 100644
--- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
@@ -22,8 +22,6 @@
 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import com.intellij.psi.javadoc.*;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PropertyUtil;
@@ -421,7 +419,7 @@
   @Nullable
   public ProblemDescriptor[] checkClass(@NotNull PsiClass psiClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
     if (psiClass instanceof PsiAnonymousClass) return null;
-    if (psiClass instanceof JspClass) return null;
+    if (psiClass instanceof PsiSyntheticClass) return null;
     if (psiClass instanceof PsiTypeParameter) return null;
     if (IGNORE_DEPRECATED && psiClass.isDeprecated()) {
       return null;
@@ -553,7 +551,7 @@
   @Override
   @Nullable
   public ProblemDescriptor[] checkMethod(@NotNull PsiMethod psiMethod, @NotNull InspectionManager manager, boolean isOnTheFly) {
-    if (psiMethod instanceof JspHolderMethod) return null;
+    if (psiMethod instanceof SyntheticElement) return null;
     if (IGNORE_DEPRECATED && (psiMethod.isDeprecated() || psiMethod.getContainingClass().isDeprecated())) {
       return null;
     }
diff --git a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
index b740fcf..609a4fc 100644
--- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
@@ -473,14 +473,16 @@
     }
   }
 
-  public static LocalQuickFix[] getChangeVariableTypeFixes(PsiVariable parameter, PsiType itemType) {
+  public static LocalQuickFix[] getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType) {
     if (itemType instanceof PsiMethodReferenceType) return LocalQuickFix.EMPTY_ARRAY;
     final List<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
     LOG.assertTrue(parameter.isValid());
-    for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
-      for (IntentionAction action : fixProvider.getFixes(parameter, itemType)) {
-        if (action instanceof LocalQuickFix) {
-          result.add((LocalQuickFix)action);
+    if (itemType != null) {
+      for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
+        for (IntentionAction action : fixProvider.getFixes(parameter, itemType)) {
+          if (action instanceof LocalQuickFix) {
+            result.add((LocalQuickFix)action);
+          }
         }
       }
     }
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 c465975..e01c21c 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
@@ -33,7 +33,6 @@
 import com.intellij.openapi.util.TextRange;
 import com.intellij.pom.Navigatable;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import com.intellij.psi.presentation.java.ClassPresentationUtil;
 import com.intellij.psi.util.PsiFormatUtil;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -125,7 +124,7 @@
       mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN);
     }
     if (enclosingElement instanceof PsiMethod) {
-      if (enclosingElement instanceof JspHolderMethod) {
+      if (enclosingElement instanceof SyntheticElement) {
         PsiFile file = enclosingElement.getContainingFile();
         myHighlightedText.getEnding().addText(file != null ? file.getName() : IdeBundle.message("node.call.hierarchy.unknown.jsp"), mainTextAttributes);
       }
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/method/OverrideImplementMethodAction.java b/java/java-impl/src/com/intellij/ide/hierarchy/method/OverrideImplementMethodAction.java
index 1bc9f6f..2b09e70 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/method/OverrideImplementMethodAction.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/method/OverrideImplementMethodAction.java
@@ -28,11 +28,7 @@
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.wm.ToolWindowManager;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiSubstitutor;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
+import com.intellij.psi.*;
 import com.intellij.psi.util.MethodSignature;
 import com.intellij.util.IncorrectOperationException;
 
@@ -151,7 +147,7 @@
 
   private static boolean canImplementOverride(final MethodHierarchyNodeDescriptor descriptor, final MethodHierarchyBrowser methodHierarchyBrowser, final boolean toImplement) {
     final PsiClass psiClass = descriptor.getPsiClass();
-    if (psiClass == null || psiClass instanceof JspClass) return false;
+    if (psiClass == null || psiClass instanceof PsiSyntheticClass) return false;
     final PsiMethod baseMethod = methodHierarchyBrowser.getBaseMethod();
     if (baseMethod == null) return false;
     final MethodSignature signature = baseMethod.getSignature(PsiSubstitutor.EMPTY);
diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java
index 570e42e..bcca6cd 100644
--- a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java
+++ b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java
@@ -29,7 +29,6 @@
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.jsp.JspFile;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
@@ -47,7 +46,7 @@
     ArrayList<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
     for (final AbstractTreeNode child : children) {
       Object o = child.getValue();
-      if (o instanceof PsiClassOwner && !(o instanceof JspFile)) {
+      if (o instanceof PsiClassOwner && !(o instanceof ServerPageFile)) {
         final ViewSettings settings1 = ((ProjectViewNode)parent).getSettings();
         final PsiClassOwner classOwner = (PsiClassOwner)o;
         final VirtualFile file = classOwner.getVirtualFile();
@@ -181,6 +180,6 @@
       }
       return result;
     }
-    
+
   }
 }
diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java b/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
index 06a5920..2f186db 100644
--- a/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
+++ b/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
@@ -24,7 +24,6 @@
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import com.intellij.psi.search.searches.SuperMethodsSearch;
 import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
 import com.intellij.psi.util.PsiFormatUtil;
@@ -45,11 +44,12 @@
     super(isInherited, method);
   }
 
+  @Override
   @NotNull
   public Collection<StructureViewTreeElement> getChildrenBase() {
     final ArrayList<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>();
     final PsiMethod element = getElement();
-    if (element == null || element instanceof JspHolderMethod) return result;
+    if (element == null || element instanceof SyntheticElement) return result;
 
     final TextRange range = element.getTextRange();
     if (range == null) return result;
@@ -72,6 +72,7 @@
     return result;
   }
 
+  @Override
   public String getPresentableText() {
     String method = PsiFormatUtil.formatMethod(getElement(),
                                                PsiSubstitutor.EMPTY,
@@ -126,6 +127,7 @@
     return getElement();
   }
 
+  @Override
   public String getAlphaSortKey() {
     final PsiMethod method = getElement();
     if (method != null) {
diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
index d123dff..0738da4 100644
--- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
+++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.ide.util.gotoByName;
 
+import com.intellij.navigation.EfficientChooseByNameContributor;
 import com.intellij.navigation.GotoClassContributor;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.project.Project;
@@ -22,14 +23,27 @@
 import com.intellij.psi.presentation.java.SymbolPresentationUtil;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.Processor;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.IdFilter;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 
-public class DefaultClassNavigationContributor implements GotoClassContributor {
+public class DefaultClassNavigationContributor implements EfficientChooseByNameContributor, GotoClassContributor {
   @Override
   @NotNull
   public String[] getNames(Project project, boolean includeNonProjectItems) {
+    if (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping) {
+      GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
+      CommonProcessors.CollectProcessor<String> processor = new CommonProcessors.CollectProcessor<String>();
+      processNames(processor, scope, DefaultFileNavigationContributor.getFilter(project, includeNonProjectItems));
+
+      return ArrayUtil.toStringArray(processor.getResults());
+    }
+
     return PsiShortNamesCache.getInstance(project).getAllClassNames();
   }
 
@@ -54,18 +68,26 @@
   @Override
   public String getQualifiedName(final NavigationItem item) {
     if (item instanceof PsiClass) {
-      final PsiClass psiClass = (PsiClass)item;
-      final String qName = psiClass.getQualifiedName();
-      if (qName != null) return qName;
-
-      final String containerText = SymbolPresentationUtil.getSymbolContainerText(psiClass);
-      return containerText + "." + psiClass.getName();
+      return getQualifiedNameForClass((PsiClass)item);
     }
     return null;
   }
 
+  public static String getQualifiedNameForClass(PsiClass psiClass) {
+    final String qName = psiClass.getQualifiedName();
+    if (qName != null) return qName;
+
+    final String containerText = SymbolPresentationUtil.getSymbolContainerText(psiClass);
+    return containerText + "." + psiClass.getName();
+  }
+
   @Override
   public String getQualifiedNameSeparator() {
     return ".";
   }
+
+  @Override
+  public void processNames(Processor<String> processor, GlobalSearchScope scope, IdFilter filter) {
+    PsiShortNamesCache.getInstance(scope.getProject()).processAllClassNames(processor, scope, filter);
+  }
 }
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
index 9cf66d3..fbf7ae9 100644
--- a/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
+++ b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
@@ -10,7 +10,7 @@
  */
 public class FindJarQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
   @Override
-  public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new JavaFindJarFix(ref));
   }
 
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
index 6b1a322..52c68a0 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
@@ -43,7 +43,6 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.jsp.JspFile;
 import com.intellij.util.PathsList;
 import com.intellij.util.containers.HashSet;
 import org.jdom.Element;
@@ -348,7 +347,7 @@
       if (file instanceof PsiJavaFile) {
         final PsiJavaFile javaFile = (PsiJavaFile)file;
         final String packageName = javaFile.getPackageName();
-        if (containsPackagePrefix(module, packageName) || (packageName.length() == 0 && !(javaFile instanceof JspFile)) || !myUsePackageNotation) {
+        if (containsPackagePrefix(module, packageName) || (packageName.length() == 0 && !(javaFile instanceof ServerPageFile)) || !myUsePackageNotation) {
           mySourceFiles.add(FileUtil.toSystemIndependentName(fileOrDir.getPath()));
         }
         else {
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java
index 5b0013c..67b4397 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java
@@ -35,6 +35,7 @@
 import com.intellij.refactoring.introduceVariable.IntroduceVariableHandler;
 import com.intellij.refactoring.memberPullUp.JavaPullUpHandler;
 import com.intellij.refactoring.memberPushDown.JavaPushDownHandler;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -42,7 +43,7 @@
  */
 public class JavaRefactoringSupportProvider extends RefactoringSupportProvider {
   @Override
-  public boolean isSafeDeleteAvailable(PsiElement element) {
+  public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
     return element instanceof PsiClass || element instanceof PsiMethod || element instanceof PsiField ||
            (element instanceof PsiParameter && ((PsiParameter)element).getDeclarationScope() instanceof PsiMethod) ||
            element instanceof PsiPackage || element instanceof PsiLocalVariable;
@@ -59,12 +60,12 @@
   }
 
   @Override
-  public boolean isInplaceRenameAvailable(final PsiElement element, final PsiElement context) {
+  public boolean isInplaceRenameAvailable(@NotNull final PsiElement element, final PsiElement context) {
     return mayRenameInplace(element, context);
   }
 
   @Override
-  public boolean isMemberInplaceRenameAvailable(PsiElement elementToRename, PsiElement context) {
+  public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) {
     return elementToRename instanceof PsiMember;
   }
 
@@ -115,7 +116,7 @@
   }
 
   @Override
-  public boolean isInplaceIntroduceAvailable(PsiElement element, PsiElement context) {
+  public boolean isInplaceIntroduceAvailable(@NotNull PsiElement element, PsiElement context) {
     if (!(element instanceof PsiExpression)) return false;
     if (context == null || context.getContainingFile() != element.getContainingFile()) return false;
     return true;
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
index 3b03958..bcec4ef 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
@@ -20,11 +20,11 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.JavaTokenType;
+import com.intellij.psi.PsiSyntheticClass;
 import com.intellij.psi.TokenType;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.formatter.FormatterUtil;
 import com.intellij.psi.formatter.common.AbstractBlock;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.impl.source.tree.JavaDocElementType;
 import com.intellij.psi.impl.source.tree.JavaElementType;
 import com.intellij.psi.impl.source.tree.StdTokenSets;
@@ -59,7 +59,7 @@
   /**
    * There is a possible case that 'implements' section is incomplete (e.g. ends with comma). We may want to align lbrace
    * to the comma then.
-   * 
+   *
    * @param alignment     block alignment
    * @param baseNode      base AST node
    * @return              alignment strategy to use for the given node
@@ -86,7 +86,7 @@
     }
     return AlignmentStrategy.wrap(alignment);
   }
-  
+
   private boolean isSwitchCodeBlock() {
     return myNode.getTreeParent().getElementType() == JavaElementType.SWITCH_STATEMENT;
   }
@@ -108,7 +108,7 @@
 
     int state = BEFORE_FIRST;
 
-    if (myNode.getPsi() instanceof JspClass) {
+    if (myNode.getPsi() instanceof PsiSyntheticClass) {
       state = INSIDE_BODY;
     }
 
@@ -157,7 +157,7 @@
     }
     return StringUtil.countNewLines(whiteSpaceCandidate.getChars()) > 0 ? myAlignment : defaultAlignment;
   }
-  
+
   @Nullable
   private ASTNode processCaseAndStatementAfter(final ArrayList<Block> result,
                                                ASTNode child,
diff --git a/java/java-impl/src/com/intellij/psi/impl/search/JavaIndexPatternBuilder.java b/java/java-impl/src/com/intellij/psi/impl/search/JavaIndexPatternBuilder.java
index d93136c..3794863 100644
--- a/java/java-impl/src/com/intellij/psi/impl/search/JavaIndexPatternBuilder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/search/JavaIndexPatternBuilder.java
@@ -17,10 +17,7 @@
 
 import com.intellij.lang.java.JavaParserDefinition;
 import com.intellij.lexer.Lexer;
-import com.intellij.psi.JavaDocTokenType;
-import com.intellij.psi.JavaTokenType;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.*;
 import com.intellij.psi.impl.source.tree.StdTokenSets;
 import com.intellij.psi.jsp.JspFile;
 import com.intellij.psi.tree.IElementType;
@@ -48,7 +45,7 @@
   @Override
   @Nullable
   public TokenSet getCommentTokenSet(final PsiFile file) {
-    if (file instanceof PsiJavaFile && !(file instanceof JspFile)) {
+    if (file instanceof PsiJavaFile && !(file instanceof ServerPageFile)) {
       return TokenSet.orSet(StdTokenSets.COMMENT_BIT_SET, XML_COMMENT_BIT_SET, JavaDocTokenType.ALL_JAVADOC_TOKENS, XML_DATA_CHARS);
     }
     return null;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
index 5e4f279..58457da 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
@@ -41,7 +41,6 @@
 import com.intellij.psi.impl.source.resolve.reference.impl.GenericReference;
 import com.intellij.psi.infos.CandidateInfo;
 import com.intellij.psi.infos.ClassCandidateInfo;
-import com.intellij.psi.jsp.JspFile;
 import com.intellij.psi.scope.JavaScopeProcessorEvent;
 import com.intellij.psi.scope.PsiScopeProcessor;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -413,7 +412,7 @@
       PsiFile containingFile = psiElement.getContainingFile();
 
       if (containingFile instanceof PsiJavaFile) {
-        if (containingFile instanceof JspFile) {
+        if (containingFile instanceof ServerPageFile) {
           containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE);
           if (containingFile == null) return JavaResolveResult.EMPTY;
         }
diff --git a/java/java-impl/src/com/intellij/psi/util/proximity/ReferenceListWeigher.java b/java/java-impl/src/com/intellij/psi/util/proximity/ReferenceListWeigher.java
index 217585f..b7d29f1 100644
--- a/java/java-impl/src/com/intellij/psi/util/proximity/ReferenceListWeigher.java
+++ b/java/java-impl/src/com/intellij/psi/util/proximity/ReferenceListWeigher.java
@@ -18,6 +18,7 @@
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.PsiElementPattern;
 import com.intellij.psi.*;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.ProximityLocation;
@@ -29,6 +30,9 @@
  */
 public class ReferenceListWeigher extends ProximityWeigher {
 
+  private static final PsiElementPattern.Capture<PsiElement> INSIDE_REFERENCE_LIST =
+    PlatformPatterns.psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiReferenceList.class);
+
   protected enum Preference {
     Interfaces, Classes, Exceptions
   }
@@ -36,7 +40,7 @@
   @Nullable
   protected Preference getPreferredCondition(@NotNull ProximityLocation location) {
     PsiElement position = location.getPosition();
-    if (PlatformPatterns.psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiReferenceList.class).accepts(position)) {
+    if (INSIDE_REFERENCE_LIST.accepts(position)) {
       assert position != null;
       PsiReferenceList list = (PsiReferenceList)position.getParent().getParent();
       PsiReferenceList.Role role = list.getRole();
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
index 7279f90..eee40ea 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
@@ -1239,8 +1239,16 @@
 
   public boolean isDeclaredInside(PsiVariable variable) {
     if (variable instanceof ImplicitVariable) return false;
-    int startOffset = myElements[0].getTextRange().getStartOffset();
-    int endOffset = myElements[myElements.length - 1].getTextRange().getEndOffset();
+    int startOffset;
+    int endOffset;
+    if (myExpression != null) {
+      final TextRange range = myExpression.getTextRange();
+      startOffset = range.getStartOffset();
+      endOffset = range.getEndOffset();
+    } else {
+      startOffset = myElements[0].getTextRange().getStartOffset();
+      endOffset = myElements[myElements.length - 1].getTextRange().getEndOffset();
+    }
     PsiIdentifier nameIdentifier = variable.getNameIdentifier();
     if (nameIdentifier == null) return false;
     final TextRange range = nameIdentifier.getTextRange();
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
index 9d64136..271e832 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
@@ -211,7 +211,7 @@
     }*/
     PsiExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class);
     while (expression != null) {
-      if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) && 
+      if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) &&
           (acceptVoid || expression.getType() != PsiType.VOID)) {
         if (expression instanceof PsiMethodReferenceExpression) {
           expressions.add(expression);
@@ -570,7 +570,7 @@
 
     final PsiFile file = anchorStatement.getContainingFile();
     LOG.assertTrue(file != null, "expr.getContainingFile() == null");
-    final PsiElement nameSuggestionContext = editor != null ? file.findElementAt(editor.getCaretModel().getOffset()) : null;
+    final PsiElement nameSuggestionContext = editor == null ? null : file.findElementAt(editor.getCaretModel().getOffset());
     final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(expr.getLanguage());
     final boolean isInplaceAvailableOnDataContext =
       supportProvider != null &&
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownConflicts.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownConflicts.java
index 032d5ff..c7589f9 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownConflicts.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownConflicts.java
@@ -72,7 +72,7 @@
     }
   }
 
-  public boolean checkTargetClassConflicts(final PsiClass targetClass, final boolean checkStatic, final PsiElement context) {
+  public void checkTargetClassConflicts(final PsiClass targetClass, final boolean checkStatic, final PsiElement context) {
     if (targetClass != null) {
       for (final PsiMember movedMember : myMovedMembers) {
         checkMemberPlacementInTargetClassConflict(targetClass, movedMember);
@@ -98,43 +98,39 @@
         });
       }
     }
-    Runnable searchConflictsRunnable = new Runnable() {
-      public void run() {
-        Members:
-        for (PsiMember member : myMovedMembers) {
-          for (PsiReference ref : ReferencesSearch.search(member, member.getResolveScope(), false)) {
-            final PsiElement element = ref.getElement();
-            if (element instanceof PsiReferenceExpression) {
-              final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
-              final PsiExpression qualifier = referenceExpression.getQualifierExpression();
-              if (qualifier != null) {
-                final PsiType qualifierType = qualifier.getType();
-                PsiClass aClass = null;
-                if (qualifierType instanceof PsiClassType) {
-                  aClass = ((PsiClassType)qualifierType).resolve();
-                }
-                else {
-                  if (!checkStatic) continue;
-                  if (qualifier instanceof PsiReferenceExpression) {
-                    final PsiElement resolved = ((PsiReferenceExpression)qualifier).resolve();
-                    if (resolved instanceof PsiClass) {
-                      aClass = (PsiClass)resolved;
-                    }
-                  }
-                }
-
-                if (!InheritanceUtil.isInheritorOrSelf(aClass, targetClass, true)) {
-                  myConflicts.putValue(referenceExpression, RefactoringBundle.message("pushed.members.will.not.be.visible.from.certain.call.sites"));
-                  break Members;
+    Members:
+    for (PsiMember member : myMovedMembers) {
+      for (PsiReference ref : ReferencesSearch.search(member, member.getResolveScope(), false)) {
+        final PsiElement element = ref.getElement();
+        if (element instanceof PsiReferenceExpression) {
+          final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
+          final PsiExpression qualifier = referenceExpression.getQualifierExpression();
+          if (qualifier != null) {
+            final PsiType qualifierType = qualifier.getType();
+            PsiClass aClass = null;
+            if (qualifierType instanceof PsiClassType) {
+              aClass = ((PsiClassType)qualifierType).resolve();
+            }
+            else {
+              if (!checkStatic) continue;
+              if (qualifier instanceof PsiReferenceExpression) {
+                final PsiElement resolved = ((PsiReferenceExpression)qualifier).resolve();
+                if (resolved instanceof PsiClass) {
+                  aClass = (PsiClass)resolved;
                 }
               }
             }
+
+            if (!InheritanceUtil.isInheritorOrSelf(aClass, targetClass, true)) {
+              myConflicts.putValue(referenceExpression, RefactoringBundle.message("pushed.members.will.not.be.visible.from.certain.call.sites"));
+              break Members;
+            }
           }
         }
-        RefactoringConflictsUtil.analyzeAccessibilityConflicts(myMovedMembers, targetClass, myConflicts, null, context, myAbstractMembers);
       }
-    };
-    return !ProgressManager.getInstance().runProcessWithProgressSynchronously(searchConflictsRunnable, RefactoringBundle.message("detecting.possible.conflicts"), false, context.getProject());
+    }
+    RefactoringConflictsUtil.analyzeAccessibilityConflicts(myMovedMembers, targetClass, myConflicts, null, context, myAbstractMembers);
+    
   }
 
   public void checkMemberPlacementInTargetClassConflict(final PsiClass targetClass, final PsiMember movedMember) {
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
index 71b2661..a6cecc7 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
@@ -20,6 +20,7 @@
 import com.intellij.codeInsight.intention.impl.CreateClassDialog;
 import com.intellij.codeInsight.intention.impl.CreateSubclassAction;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
@@ -87,7 +88,7 @@
   }
 
   protected boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) {
-    UsageInfo[] usagesIn = refUsages.get();
+    final UsageInfo[] usagesIn = refUsages.get();
     final PushDownConflicts pushDownConflicts = new PushDownConflicts(myClass, myMemberInfos);
     pushDownConflicts.checkSourceClassConflicts();
 
@@ -115,14 +116,20 @@
         } else if (answer != 1) return false;
       }
     }
-    for (UsageInfo usage : usagesIn) {
-      final PsiElement element = usage.getElement();
-      if (element instanceof PsiClass) {
-        boolean canceled = pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element);
-        if (canceled) return false;
+    Runnable runnable = new Runnable() {
+      public void run() {
+        for (UsageInfo usage : usagesIn) {
+          final PsiElement element = usage.getElement();
+          if (element instanceof PsiClass) {
+            pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element);
+          }
+        }
       }
-    }
+    };
 
+    if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) {
+      return false;
+    }
     return showConflicts(pushDownConflicts.getConflicts(), usagesIn);
   }
 
diff --git a/java/java-impl/src/com/intellij/refactoring/migration/MigrationUtil.java b/java/java-impl/src/com/intellij/refactoring/migration/MigrationUtil.java
index 7a1924f..a559a39 100644
--- a/java/java-impl/src/com/intellij/refactoring/migration/MigrationUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/migration/MigrationUtil.java
@@ -48,13 +48,18 @@
 
       // rename all references
       for (UsageInfo usage : usages) {
-        PsiElement element = usage.getElement();
-        if (element == null || !element.isValid()) continue;
-        if (element instanceof PsiJavaCodeReferenceElement) {
-          ((PsiJavaCodeReferenceElement)element).bindToElement(aPackage);
-        }
-        else {
-          bindNonJavaReference(aPackage, element, usage);
+        if (usage instanceof MigrationProcessor.MigrationUsageInfo) {
+          final MigrationProcessor.MigrationUsageInfo usageInfo = (MigrationProcessor.MigrationUsageInfo)usage;
+          if (Comparing.equal(newQName, usageInfo.mapEntry.getNewName())) {
+            PsiElement element = usage.getElement();
+            if (element == null || !element.isValid()) continue;
+            if (element instanceof PsiJavaCodeReferenceElement) {
+              ((PsiJavaCodeReferenceElement)element).bindToElement(aPackage);
+            }
+            else {
+              bindNonJavaReference(aPackage, element, usage);
+            }
+          }
         }
       }
     }
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
index 38fa2e6..8322228 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
@@ -31,7 +31,6 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.file.JavaDirectoryServiceImpl;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.refactoring.JavaRefactoringSettings;
 import com.intellij.refactoring.RefactoringBundle;
@@ -81,12 +80,12 @@
       final PsiClass[] classes = ((PsiClassOwner)element).getClasses();
       if (classes.length == 0) return true;
       for (PsiClass aClass : classes) {
-        if (aClass instanceof JspClass) return true;
+        if (aClass instanceof PsiSyntheticClass) return true;
       }
       parentFile = (PsiFile)element;
     }
     else {
-      if (element instanceof JspClass) return true;
+      if (element instanceof PsiSyntheticClass) return true;
       if (!(element instanceof PsiClass)) return true;
       if (element instanceof PsiAnonymousClass) return true;
       if (((PsiClass)element).getContainingClass() != null) return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandlerDelegate.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandlerDelegate.java
index acf48b7..314666c 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandlerDelegate.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandlerDelegate.java
@@ -15,27 +15,28 @@
  */
 package com.intellij.refactoring.move.moveInstanceMethod;
 
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
-import com.intellij.refactoring.move.MoveHandlerDelegate;
-import com.intellij.refactoring.move.MoveCallback;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.refactoring.move.MoveCallback;
+import com.intellij.refactoring.move.MoveHandlerDelegate;
 import com.intellij.refactoring.move.moveClassesOrPackages.JavaMoveClassesOrPackagesHandler;
 import org.jetbrains.annotations.Nullable;
 
 public class MoveInstanceMethodHandlerDelegate extends MoveHandlerDelegate {
+  @Override
   public boolean canMove(final PsiElement[] elements, @Nullable final PsiElement targetContainer) {
     if (elements.length != 1) return false;
     PsiElement element = elements [0];
     if (!(element instanceof PsiMethod)) return false;
-    if (element instanceof JspHolderMethod) return false;
+    if (element instanceof SyntheticElement) return false;
     PsiMethod method = (PsiMethod) element;
     if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
     return super.canMove(elements, targetContainer);
   }
 
+  @Override
   public boolean isValidTarget(final PsiElement psiElement, PsiElement[] sources) {
     for (PsiElement source : sources) {
       if (JavaMoveClassesOrPackagesHandler.invalid4Move(source)) return false;
@@ -43,6 +44,7 @@
     return psiElement instanceof PsiClass && !(psiElement instanceof PsiAnonymousClass);
   }
 
+  @Override
   public boolean tryToMove(final PsiElement element, final Project project, final DataContext dataContext, final PsiReference reference,
                            final Editor editor) {
     if (element instanceof PsiMethod) {
@@ -55,6 +57,7 @@
     return false;
   }
 
+  @Override
   public void doMove(final Project project, final PsiElement[] elements, final PsiElement targetContainer, final MoveCallback callback) {
     new MoveInstanceMethodHandler().invoke(project, elements, null);
   }
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersHandler.java
index 16c3c33..077963f 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersHandler.java
@@ -19,7 +19,6 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
 import com.intellij.refactoring.move.MoveCallback;
 import com.intellij.refactoring.move.MoveHandlerDelegate;
 import org.jetbrains.annotations.Nullable;
@@ -52,7 +51,7 @@
   private static boolean isFieldOrStaticMethod(final PsiElement element) {
     if (element instanceof PsiField) return true;
     if (element instanceof PsiMethod) {
-      if (element instanceof JspHolderMethod) return false;
+      if (element instanceof SyntheticElement) return false;
       return ((PsiMethod) element).hasModifierProperty(PsiModifier.STATIC);
     }
     return false;
diff --git a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
index d60d08d..1f9d9f8 100644
--- a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
+++ b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
@@ -22,23 +22,30 @@
 import com.intellij.codeInsight.generation.PsiGenerationInfo;
 import com.intellij.codeInsight.generation.actions.BaseGenerateAction;
 import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
+import com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable;
+import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.util.CommonRefactoringUtil;
 import com.intellij.ui.components.JBList;
+import com.intellij.util.Consumer;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction {
@@ -48,13 +55,46 @@
     super(new MyHandler(methodKind));
   }
 
+  @Nullable
+  @Override
+  public AnAction createEditTemplateAction(DataContext dataContext) {
+    final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
+    final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
+    final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
+    final PsiClass targetClass = editor == null || file == null ? null : getTargetClass(editor, file);
+    if (targetClass != null) {
+      final List<TestFramework> frameworks = TestIntegrationUtils.findSuitableFrameworks(targetClass);
+      final TestIntegrationUtils.MethodKind methodKind = ((MyHandler)getHandler()).myMethodKind;
+      if (!frameworks.isEmpty()) {
+        return new AnAction("Edit Template") {
+          @Override
+          public void actionPerformed(AnActionEvent e) {
+            chooseAndPerform(editor, frameworks, new Consumer<TestFramework>() {
+              @Override
+              public void consume(TestFramework framework) {
+                final FileTemplateDescriptor descriptor = methodKind.getFileTemplateDescriptor(framework);
+                if (descriptor != null) {
+                  final String fileName = descriptor.getFileName();
+                  AllFileTemplatesConfigurable.editCodeTemplate(FileUtil.getNameWithoutExtension(fileName), project);
+                } else {
+                  HintManager.getInstance().showErrorHint(editor, "No template found for " + framework.getName() + ":" + BaseGenerateTestSupportMethodAction.this.getTemplatePresentation().getText());
+                }
+              }
+            });
+          }
+        };
+      }
+    }
+    return null;
+  }
+
   @Override
   protected PsiClass getTargetClass(Editor editor, PsiFile file) {
     return findTargetClass(editor, file);
   }
 
   @Nullable
-  private static PsiClass findTargetClass(Editor editor, PsiFile file) {
+  private static PsiClass findTargetClass(@NotNull Editor editor, @NotNull PsiFile file) {
     int offset = editor.getCaretModel().getOffset();
     PsiElement element = file.findElementAt(offset);
     return element == null ? null : TestIntegrationUtils.findOuterClass(element);
@@ -86,6 +126,47 @@
     return true;
   }
 
+  private static void chooseAndPerform(Editor editor, List<TestFramework> frameworks, final Consumer<TestFramework> consumer) {
+    if (frameworks.size() == 1) {
+      consumer.consume(frameworks.get(0));
+      return;
+    }
+
+    final JList list = new JBList(frameworks.toArray(new TestFramework[frameworks.size()]));
+    list.setCellRenderer(new DefaultListCellRenderer() {
+      @Override
+      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        Component result = super.getListCellRendererComponent(list, "", index, isSelected, cellHasFocus);
+        if (value == null) return result;
+        TestFramework framework = (TestFramework)value;
+
+        setIcon(framework.getIcon());
+        setText(framework.getName());
+
+        return result;
+      }
+    });
+
+
+    PopupChooserBuilder builder = new PopupChooserBuilder(list);
+    builder.setFilteringEnabled(new Function<Object, String>() {
+      @Override
+      public String fun(Object o) {
+        return ((TestFramework)o).getName();
+      }
+    });
+
+    builder
+      .setTitle("Choose Framework")
+      .setItemChoosenCallback(new Runnable() {
+        @Override
+        public void run() {
+          consumer.consume((TestFramework)list.getSelectedValue());
+        }
+      })
+      .setMovable(true)
+      .createPopup().showInBestPositionFor(editor);
+  }
 
   private static class MyHandler implements CodeInsightActionHandler {
     private TestIntegrationUtils.MethodKind myMethodKind;
@@ -97,51 +178,24 @@
     public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull final PsiFile file) {
       final PsiClass targetClass = findTargetClass(editor, file);
       final List<TestFramework> frameworks = TestIntegrationUtils.findSuitableFrameworks(targetClass);
-      if (frameworks.isEmpty()) return;
-
-      if (frameworks.size() == 1) {
-        doGenerate(editor, file, targetClass, frameworks.get(0));
-        return;
-      }
-
-      final JList list = new JBList(frameworks.toArray(new TestFramework[frameworks.size()]));
-      list.setCellRenderer(new DefaultListCellRenderer() {
-        @Override
-        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-          Component result = super.getListCellRendererComponent(list, "", index, isSelected, cellHasFocus);
-          if (value == null) return result;
-          TestFramework framework = (TestFramework)value;
-
-          setIcon(framework.getIcon());
-          setText(framework.getName());
-
-          return result;
+      for (Iterator<TestFramework> iterator = frameworks.iterator(); iterator.hasNext(); ) {
+        if (myMethodKind.getFileTemplateDescriptor(iterator.next()) == null) {
+          iterator.remove();
         }
-      });
-
-      final Runnable runnable = new Runnable() {
-        public void run() {
-          TestFramework selected = (TestFramework)list.getSelectedValue();
-          if (selected == null) return;
-          doGenerate(editor, file, targetClass, selected);
+      }
+      if (frameworks.isEmpty()) return;
+      final Consumer<TestFramework> consumer = new Consumer<TestFramework>() {
+        @Override
+        public void consume(TestFramework framework) {
+          if (framework == null) return;
+          doGenerate(editor, file, targetClass, framework);
         }
       };
 
-      PopupChooserBuilder builder = new PopupChooserBuilder(list);
-      builder.setFilteringEnabled(new Function<Object, String>() {
-        @Override
-        public String fun(Object o) {
-          return ((TestFramework)o).getName();
-        }
-      });
-
-      builder
-        .setTitle("Choose Framework")
-        .setItemChoosenCallback(runnable)
-        .setMovable(true)
-        .createPopup().showInBestPositionFor(editor);
+      chooseAndPerform(editor, frameworks, consumer);
     }
 
+
     private void doGenerate(final Editor editor, final PsiFile file, final PsiClass targetClass, final TestFramework framework) {
       if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) return;
 
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 b4f6127..add3fe2 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
@@ -25,7 +25,6 @@
 import com.intellij.openapi.vcs.FileStatus;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
-import com.intellij.psi.jsp.JspFile;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usages.Usage;
@@ -53,7 +52,7 @@
 
     PsiFile topLevelFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
 
-    if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof JspFile) {
+    if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof ServerPageFile) {
       return null;
     }
     PsiElement containingClass = topLevelFile == containingFile ? psiElement : InjectedLanguageManager
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/NonJavaFileGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/NonJavaFileGroupingRule.java
index 90be2e8..f18012d 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/NonJavaFileGroupingRule.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/NonJavaFileGroupingRule.java
@@ -18,7 +18,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.jsp.JspFile;
+import com.intellij.psi.ServerPageFile;
 import com.intellij.usages.Usage;
 import com.intellij.usages.UsageGroup;
 import org.jetbrains.annotations.NotNull;
@@ -28,11 +28,12 @@
     super(project);
   }
 
+  @Override
   public UsageGroup groupUsage(@NotNull Usage usage) {
     final FileUsageGroup usageGroup = (FileUsageGroup)super.groupUsage(usage);
     if (usageGroup != null) {
       final PsiFile psiFile = usageGroup.getPsiFile();
-      if (psiFile instanceof PsiJavaFile && !(psiFile instanceof JspFile)) {
+      if (psiFile instanceof PsiJavaFile && !(psiFile instanceof ServerPageFile)) {
         return null;
       }
     }
diff --git a/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java b/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java
index 128bd56..0fd831c 100644
--- a/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java
+++ b/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java
@@ -22,6 +22,7 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.xml.XmlElement;
 import com.intellij.util.ProcessingContext;
 import com.intellij.util.ReflectionCache;
 import com.intellij.util.SmartList;
@@ -142,7 +143,10 @@
     final Object valueObject = element.getValue();
     if (!(valueObject instanceof PsiClass)) return Collections.emptyList();
 
-    final PsiReference[] references = ourProvider.getReferencesByElement(DomUtil.getValueElement(element), new ProcessingContext());
+    final XmlElement valueElement = DomUtil.getValueElement(element);
+    if (valueElement == null) return Collections.emptyList();
+
+    final PsiReference[] references = ourProvider.getReferencesByElement(valueElement, new ProcessingContext());
     for (PsiReference reference : references) {
       if (reference instanceof JavaClassReference) {
         final PsiReferenceProvider psiReferenceProvider = ((JavaClassReference)reference).getProvider();
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
index 38465bd..6854c57 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
@@ -20,9 +20,11 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.CommonProcessors;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
+import com.intellij.util.indexing.IdFilter;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
@@ -89,6 +91,10 @@
     return ContainerUtil.process(getAllClassNames(), processor);
   }
 
+  public boolean processAllClassNames(Processor<String> processor, GlobalSearchScope scope, IdFilter filter) {
+    return ContainerUtil.process(getAllClassNames(), processor);
+  }
+
   /**
    * Adds the names of all classes in the project and (optionally) libraries
    * to the specified set.
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
index 52d5801..e6ba22d 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
@@ -27,6 +27,7 @@
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
+import com.intellij.util.indexing.IdFilter;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -106,6 +107,16 @@
   }
 
   @Override
+  public boolean processAllClassNames(Processor<String> processor, GlobalSearchScope scope, IdFilter filter) {
+    for (PsiShortNamesCache cache : myCaches) {
+      if (!cache.processAllClassNames(processor, scope, filter)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
   public void getAllClassNames(@NotNull HashSet<String> dest) {
     for (PsiShortNamesCache cache : myCaches) {
       cache.getAllClassNames(dest);
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
index b17c4b1..e702d01 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
@@ -32,6 +32,8 @@
 import com.intellij.util.Processor;
 import com.intellij.util.SmartList;
 import com.intellij.util.containers.HashSet;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.IdFilter;
 import gnu.trove.THashSet;
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NonNls;
@@ -115,6 +117,11 @@
   }
 
   @Override
+  public boolean processAllClassNames(Processor<String> processor, GlobalSearchScope scope, IdFilter filter) {
+    return StubIndex.getInstance().processAllKeys(JavaStubIndexKeys.CLASS_SHORT_NAMES, processor, scope, filter);
+  }
+
+  @Override
   @NotNull
   public PsiMethod[] getMethodsByName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
     Collection<PsiMethod> methods = StubIndex.getInstance().get(JavaStubIndexKeys.METHODS, name, myManager.getProject(), new JavaSourceFilterScope(scope));
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
index 7faeaf9..95e27ea 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
@@ -26,6 +26,7 @@
 import com.intellij.psi.stubs.StringStubIndexExtension;
 import com.intellij.psi.stubs.StubIndex;
 import com.intellij.psi.stubs.StubIndexKey;
+import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -33,10 +34,16 @@
 public class JavaShortClassNameIndex extends StringStubIndexExtension<PsiClass> {
 
   private static final JavaShortClassNameIndex ourInstance = new JavaShortClassNameIndex();
+
   public static JavaShortClassNameIndex getInstance() {
     return ourInstance;
   }
 
+  @Override
+  public int getVersion() {
+    return super.getVersion() + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 1 : 0);
+  }
+
   @NotNull
   @Override
   public StubIndexKey<String, PsiClass> getKey() {
@@ -47,4 +54,9 @@
   public Collection<PsiClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
     return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiClass.class);
   }
+
+  @Override
+  public boolean traceKeyHashToVirtualFileMapping() {
+    return FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
+  }
 }
\ No newline at end of file
diff --git a/java/openapi/src/com/intellij/codeInsight/ClassUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/ClassUtil.java
similarity index 100%
rename from java/openapi/src/com/intellij/codeInsight/ClassUtil.java
rename to java/java-psi-api/src/com/intellij/codeInsight/ClassUtil.java
diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
index a00e880..b30f262 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi;
 
+import com.intellij.openapi.util.Computable;
 import com.intellij.psi.util.MethodSignature;
 import com.intellij.psi.util.PsiUtil;
 import org.jetbrains.annotations.NotNull;
@@ -58,8 +59,13 @@
       }
     } else if (functionalInterfaceReturnType != null) {
       final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(lambdaExpression);
-      for (PsiExpression expression : returnExpressions) {
-        final PsiType expressionType = expression.getType();
+      for (final PsiExpression expression : returnExpressions) {
+        final PsiType expressionType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, new Computable<PsiType>() {
+          @Override
+          public PsiType compute() {
+            return expression.getType();
+          }
+        });
         if (expressionType != null && !functionalInterfaceReturnType.isAssignableFrom(expressionType)) {
           return "Incompatible return type " + expressionType.getPresentableText() + " in lambda expression";
         }
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 41c4aa5..2bfe470 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -711,9 +711,9 @@
       }
     }
 
-    final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType));
+    final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType, false));
     final PsiClass rClass = r.getElement();
-    final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType1));
+    final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType1, false));
     final PsiClass rClass1 = r1.getElement();
     if (rClass != null && rClass1 != null) {
       if (rClass == rClass1) {
@@ -722,13 +722,13 @@
           final PsiType t = r.getSubstitutor().substituteWithBoundsPromotion(parameter);
           final PsiType t1 = r1.getSubstitutor().substituteWithBoundsPromotion(parameter);
           if (t == null || t1 == null) continue;
-          if (t1.isAssignableFrom(t) && !GenericsUtil.eliminateWildcards(t1).equals(t)) {
+          if (t1.isAssignableFrom(t)) {
             if (moreSpecific == 1) {
               return 0;
             }
             moreSpecific = -1;
           }
-          else if (t.isAssignableFrom(t1) && !GenericsUtil.eliminateWildcards(t).equals(t1)) {
+          else if (t.isAssignableFrom(t1)) {
             if (moreSpecific == -1) {
               return 0;
             }
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
index 4b2b4da..756543d 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
@@ -82,8 +82,12 @@
     final PsiParameter[] parameters = method.getParameterList().getParameters();
     PsiType[] parameterTypes = new PsiType[parameters.length];
     for (int i = 0; i < parameterTypes.length; i++) {
-      PsiType type = parameters[i].getType();
+      PsiParameter parameter = parameters[i];
+      PsiType type = parameter.getType();
       parameterTypes[i] = isRaw ? TypeConversionUtil.erasure(substitutor.substitute(type)) : type;
+      if (!parameterTypes[i].isValid()) {
+        PsiUtil.ensureValidType(parameterTypes[i], "Method " + method + " of " + method.getClass() + "; param " + parameter + " of " + parameter.getClass());
+      }
     }
 
     return new MethodSignatureBackedByPsiMethod(method, substitutor, isRaw, parameterTypes, methodTypeParameters);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java
index 3d6f4c7..abe33b5 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java
@@ -355,7 +355,7 @@
     return buffer.toString();
   }
 
-  public static String formatType(PsiType type, int options, @NotNull PsiSubstitutor substitutor){
+  public static String formatType(@Nullable PsiType type, int options, @NotNull PsiSubstitutor substitutor){
     type = substitutor.substitute(type);
     if ((options & SHOW_RAW_TYPE) != 0) {
       type = TypeConversionUtil.erasure(type);
@@ -368,6 +368,7 @@
         }
       }
     }
+    if (type == null) return "null";
     return (options & SHOW_FQ_CLASS_NAMES) == 0 ? type.getPresentableText() : type.getInternalCanonicalText();
   }
 
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
index d0b3dc9..d241e3f 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
@@ -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.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.intellij.psi.util;
 
 import com.intellij.openapi.util.Condition;
@@ -26,7 +25,6 @@
  * @author mike
  */
 public class PsiMethodUtil {
-
   private static final JavaMainMethodProvider[] myProviders = Extensions.getExtensions(JavaMainMethodProvider.EP_NAME);
 
   public static final Condition<PsiClass> MAIN_CLASS = new Condition<PsiClass>() {
@@ -38,8 +36,7 @@
     }
   };
 
-  private PsiMethodUtil() {
-  }
+  private PsiMethodUtil() { }
 
   @Nullable
   public static PsiMethod findMainMethod(final PsiClass aClass) {
@@ -70,7 +67,7 @@
     final PsiType type = parameters[0].getType();
     if (!(type instanceof PsiArrayType)) return false;
     final PsiType componentType = ((PsiArrayType)type).getComponentType();
-    return componentType.equalsToText("java.lang.String");
+    return componentType.equalsToText(CommonClassNames.JAVA_LANG_STRING);
   }
 
   public static boolean hasMainMethod(final PsiClass psiClass) {
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
index 642d855..7cedb1d 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
@@ -1028,16 +1028,24 @@
   }
 
   public static void ensureValidType(@NotNull PsiType type) {
+    ensureValidType(type, null);
+  }
+  public static void ensureValidType(@NotNull PsiType type, @Nullable String customMessage) {
     if (!type.isValid()) {
       TimeoutUtil.sleep(1); // to see if processing in another thread suddenly makes the type valid again (which is a bug)
       if (type.isValid()) {
-        LOG.error("PsiType resurrected: " + type + " of " + type.getClass());
+        LOG.error("PsiType resurrected: " + type + " of " + type.getClass() + " " + customMessage);
         return;
       }
       if (type instanceof PsiClassType) {
-        ((PsiClassType)type).resolve(); // should throw exception
+        try {
+          ((PsiClassType)type).resolve(); // should throw exception
+        }
+        catch (PsiInvalidElementAccessException e) {
+          throw customMessage == null? e : new RuntimeException(customMessage, e);
+        }
       }
-      throw new AssertionError("Invalid type: " + type + " of class " + type.getClass());
+      throw new AssertionError("Invalid type: " + type + " of class " + type.getClass() + " " + customMessage);
     }
   }
 
diff --git a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
index 91af96d..f3a325a 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
@@ -523,7 +523,8 @@
             }
           }
         }
-        if (parent instanceof PsiInstanceOfExpression || TypeConversionUtil.isAssignable(castTo, opType, false)) {
+        if (parent instanceof PsiInstanceOfExpression || (TypeConversionUtil.isAssignable(castTo, opType, false) && 
+                                                          (expectedTypeByParent == null || TypeConversionUtil.isAssignable(expectedTypeByParent, opType, false)))) {
           addToResults(typeCast);
         }
       }
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 2a7ba4f..7887f0d 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -893,9 +893,6 @@
     PsiSubstitutor leftSubstitutor = leftResult.getSubstitutor();
 
     if (!leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) {
-      if (!allowUncheckedConversion && PsiUtil.isRawSubstitutor(leftClass, leftSubstitutor) && !rightClass.hasTypeParameters() && !(rightClass instanceof PsiTypeParameter)) {
-        return false;
-      }
       rightSubstitutor = getSuperClassSubstitutor(leftClass, rightClass, rightSubstitutor);
       rightClass = leftClass;
     }
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java
index 1ada9aa..080ef4a 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java
@@ -126,6 +126,8 @@
       final PsiClass boundClass1 = PsiUtil.resolveClassInType(extendsBound1);
       final PsiClass boundClass2 = PsiUtil.resolveClassInType(extendsBound2);
       if (boundClass1 != null && boundClass2 != null) {
+        if (extendsBound1 instanceof PsiClassType && extendsBound2 instanceof PsiClassType && 
+            (((PsiClassType)extendsBound1).isRaw() ^ ((PsiClassType)extendsBound2).isRaw())) return true;
         return proveExtendsBoundsDistinct(type1, type2, boundClass1, boundClass2);
       }
       return provablyDistinct(extendsBound1, extendsBound2, 1);
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 8d75564..464c01b 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
@@ -21,6 +21,7 @@
 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;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -56,6 +57,14 @@
   private final ConcurrentMap<String, List<PsiFile>> myExternalAnnotations = new ConcurrentSoftValueHashMap<String, List<PsiFile>>(10, 0.75f, 2);
   protected final PsiManager myPsiManager;
 
+  @SuppressWarnings("UnusedDeclaration")
+  private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
+    @Override
+    public void run() {
+      dropCache();
+    }
+  });
+
   public BaseExternalAnnotationsManager(final PsiManager psiManager) {
     myPsiManager = psiManager;
   }
@@ -215,7 +224,8 @@
   }
 
   protected void duplicateError(@NotNull PsiFile file, @NotNull String externalName, @NotNull String text) {
-    LOG.error(text + "; for signature: '" + externalName + "' in the file " + file.getVirtualFile().getPresentableUrl());
+    VirtualFile virtualFile = file.getVirtualFile();
+    LOG.error(text + "; for signature: '" + externalName + "' in the file " + (virtualFile != null ? virtualFile.getPresentableUrl() : null));
   }
 
   @NotNull
@@ -406,7 +416,7 @@
     @NotNull private final String annotationClassFqName;
     @NotNull private final String annotationParameters;
     private final VirtualFile virtualFile;
-    private PsiAnnotation annotation;
+    private volatile PsiAnnotation annotation;
 
     private AnnotationData(@NotNull String annotationClassFqName, @NotNull String annotationParameters, VirtualFile virtualFile) {
       this.annotationClassFqName = annotationClassFqName;
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/FileParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/FileParser.java
index eeee9777..6b9f154 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/FileParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/FileParser.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,19 +55,14 @@
                         @NotNull final String errorMessageKey) {
     parsePackageStatement(builder);
 
-    final Pair<PsiBuilder.Marker, Boolean> impListInfo = parseImportList(builder, importListStoppers);
+    Pair<PsiBuilder.Marker, Boolean> impListInfo = parseImportList(builder, importListStoppers);
 
     Boolean firstDeclarationOk = null;
     PsiBuilder.Marker firstDeclaration = null;
     PsiBuilder.Marker invalidElements = null;
     while (!builder.eof()) {
       if (builder.getTokenType() == JavaTokenType.SEMICOLON) {
-        if (invalidElements != null) {
-          invalidElements.error(error(bundle, errorMessageKey));
-          invalidElements = null;
-        }
         builder.advanceLexer();
-        if (firstDeclarationOk == null) firstDeclarationOk = false;
         continue;
       }
 
@@ -124,7 +119,7 @@
 
     final PsiBuilder.Marker ref = myParser.getReferenceParser().parseJavaCodeReference(builder, true, false, false, false);
     if (ref == null) {
-      statement.rollbackTo();
+      statement.error(JavaErrorMessages.message("expected.class.or.interface"));
       return null;
     }
 
@@ -136,13 +131,21 @@
 
   @NotNull
   public Pair<PsiBuilder.Marker, Boolean> parseImportList(final PsiBuilder builder, final TokenSet stoppers) {
-    final PsiBuilder.Marker list = builder.mark();
+    PsiBuilder.Marker list = builder.mark();
 
-    final boolean isEmpty = builder.getTokenType() != JavaTokenType.IMPORT_KEYWORD;
+    IElementType tokenType = builder.getTokenType();
+    boolean isEmpty = tokenType != JavaTokenType.IMPORT_KEYWORD && tokenType != JavaTokenType.SEMICOLON;
     if (!isEmpty) {
       PsiBuilder.Marker invalidElements = null;
       while (!builder.eof()) {
-        if (stoppers.contains(builder.getTokenType())) break;
+        tokenType = builder.getTokenType();
+        if (stoppers.contains(tokenType)) {
+          break;
+        }
+        else if (tokenType == JavaTokenType.SEMICOLON) {
+          builder.advanceLexer();
+          continue;
+        }
 
         final PsiBuilder.Marker statement = parseImportStatement(builder);
         if (statement != null) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
index a5aed98..3850cea 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
@@ -19,6 +19,7 @@
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -217,14 +218,14 @@
       pineBuffer.append('<');
       for (int i = 0; i < typeParameters.length; i++) {
         PsiTypeParameter typeParameter = typeParameters[i];
-        assert typeParameter.isValid();
+        PsiUtilCore.ensureValid(typeParameter);
         if (i > 0) pineBuffer.append(',');
         final PsiType substitutionResult = substitutor.substitute(typeParameter);
         if (substitutionResult == null) {
           pineBuffer = null;
           break;
         }
-        assert substitutionResult.isValid();
+        PsiUtil.ensureValidType(substitutionResult);
         if (canonical) {
           if (internal) {
             pineBuffer.append(substitutionResult.getInternalCanonicalText());
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
index 48a0e09..bc62cc8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
@@ -44,6 +44,7 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -91,7 +92,7 @@
   }
 
   public int getKind() {
-    LOG.assertTrue(isValid());
+    PsiUtilCore.ensureValid(this);
     CompositeElement treeParent = getTreeParent();
     IElementType i = treeParent.getElementType();
     if (isDummy(i)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
index bbe39b3..6410991 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
@@ -1199,6 +1199,7 @@
 
         PsiType[] superTypes = typeParameter.getSuperTypes();
         if (superTypes.length == 0) return null;
+        final PsiType[] types = new PsiType[superTypes.length];
         for (int i = 0; i < superTypes.length; i++) {
           PsiType superType = substitutor.substitute(superTypes[i]);
           if (superType instanceof PsiClassType && ((PsiClassType)superType).isRaw()) {
@@ -1206,9 +1207,9 @@
           }
           if (superType == null) superType = PsiType.getJavaLangObject(myManager, scope);
           if (superType == null) return null;
-          superTypes[i] = superType;
+          types[i] = superType;
         }
-        return policy.getInferredTypeWithNoConstraint(myManager, PsiIntersectionType.createIntersection(superTypes));
+        return policy.getInferredTypeWithNoConstraint(myManager, PsiIntersectionType.createIntersection(types));
       }
       return null;
     }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
index f397423..27012ff 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
@@ -97,6 +97,7 @@
       if (type2 == null) return null;
     }
 
+    if (type1 instanceof PsiLambdaParameterType || type2 instanceof PsiLambdaParameterType) return null;
     final PsiType leastUpperBound = GenericsUtil.getLeastUpperBound(type1, type2, getManager());
     return leastUpperBound != null ? PsiUtil.captureToplevelWildcards(leastUpperBound, this) : null;
   }
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 2cd3f29..4c799c6 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
@@ -393,7 +393,7 @@
     }
 
     private PsiSubstitutor getSubstitutor(PsiType type) {
-      final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
+      final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type));
       PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor();
       if (type instanceof PsiClassType) {
         final PsiClass psiClass = resolveResult.getElement();
diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml
index cc0afca..ef3e588 100644
--- a/java/java-tests/java-tests.iml
+++ b/java/java-tests/java-tests.iml
@@ -30,6 +30,7 @@
     <orderEntry type="module" module-name="java-indexing-api" scope="TEST" />
     <orderEntry type="module" module-name="external-system-impl" scope="RUNTIME" />
     <orderEntry type="module" module-name="junit_rt" scope="TEST" />
+    <orderEntry type="module" module-name="manifest" scope="TEST" />
   </component>
 </module>
 
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MultilineCall.java b/java/java-tests/testData/codeInsight/completeStatement/MultilineCall.java
new file mode 100644
index 0000000..dfcca36
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MultilineCall.java
@@ -0,0 +1,6 @@
+class Test {
+  Object method() {
+      method(
+          factory()<caret>
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MultilineCall_after.java b/java/java-tests/testData/codeInsight/completeStatement/MultilineCall_after.java
new file mode 100644
index 0000000..1d2e3fc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MultilineCall_after.java
@@ -0,0 +1,6 @@
+class Test {
+  Object method() {
+      method(
+              factory());<caret>
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DelegatingConstructorCall.java b/java/java-tests/testData/codeInsight/completion/normalSorting/DelegatingConstructorCall.java
new file mode 100644
index 0000000..a9849ac
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normalSorting/DelegatingConstructorCall.java
@@ -0,0 +1,12 @@
+class SearchParameters {
+
+  public SearchParameters(PsiElement element) {
+    this(e<caret>);
+  }
+
+  public SearchParameters(final PsiElement element, final boolean checkDeep) {
+  }
+
+}
+
+class PsiElement {}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97276.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97276.java
index c059e83..625d706 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97276.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97276.java
@@ -2,3 +2,16 @@
 class SomeClass {
     static <I extends Interf<? super I>> Class<I> someMethod(I i) { return null; }
 }
+
+interface OtherInterf<I1 extends Interf, I2 extends Interf> {}
+interface ImmutableSet<S> {}
+
+class SomeOtherClass {
+  static ImmutableSet<Class<? extends OtherInterf<?, ?>>> someOtherMethod() {
+    return <error descr="Inconvertible types; cannot cast 'ImmutableSet<java.lang.Class<? extends OtherInterf>>' to 'ImmutableSet<java.lang.Class<? extends OtherInterf<?,?>>>'">(ImmutableSet<Class<? extends OtherInterf<?, ?>>>)aux(OtherInterf.class)</error>;
+  }
+
+  static <T> ImmutableSet<Class<? extends T>> aux(Class<T> t) {
+    return null;
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RawAssignments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RawAssignments.java
new file mode 100644
index 0000000..bfbe439
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RawAssignments.java
@@ -0,0 +1,18 @@
+import java.io.*;
+import java.util.*;
+
+interface Foo {
+    String getText(Map attributes) throws IOException;
+    String getText(Properties attributes) throws IOException;
+}
+
+class Bar {
+    void foo(Foo foo, Properties prop) throws IOException {
+        foo.getText(prop);
+    }
+}
+public abstract class Hashtable<K,V> implements Map<K,V>, Cloneable {
+}
+
+public abstract class Properties extends Hashtable<Object,Object> {
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA112323.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA112323.java
new file mode 100644
index 0000000..95e8fcf
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA112323.java
@@ -0,0 +1,17 @@
+import java.util.*;
+interface Stream<T> {
+    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
+}
+
+interface Function<T, R> {
+    R apply(T t);
+}
+
+class Test1
+{
+    public static void main(Stream<Map.Entry<String, Long>> stream)
+    {
+        Stream<String> map = stream.map(Map.Entry::getKey);
+    }
+
+}
diff --git a/java/java-tests/testData/psi/parser-partial/files/ExtraSemicolons.txt b/java/java-tests/testData/psi/parser-partial/files/ExtraSemicolons.txt
new file mode 100644
index 0000000..d761853
--- /dev/null
+++ b/java/java-tests/testData/psi/parser-partial/files/ExtraSemicolons.txt
@@ -0,0 +1,37 @@
+PsiJavaFile:ExtraSemicolons.java
+  PsiPackageStatement:p
+    PsiKeyword:package('package')
+    PsiWhiteSpace(' ')
+    PsiJavaCodeReferenceElement:p
+      PsiIdentifier:p('p')
+      PsiReferenceParameterList
+        <empty list>
+    PsiJavaToken:SEMICOLON(';')
+  PsiImportList
+    PsiJavaToken:SEMICOLON(';')
+    PsiWhiteSpace('\n')
+    PsiImportStatement
+      PsiKeyword:import('import')
+      PsiWhiteSpace(' ')
+      PsiJavaCodeReferenceElement:a
+        PsiIdentifier:a('a')
+        PsiReferenceParameterList
+          <empty list>
+      PsiJavaToken:SEMICOLON(';')
+    PsiJavaToken:SEMICOLON(';')
+  PsiWhiteSpace('\n')
+  PsiClass:C
+    PsiModifierList:
+      <empty list>
+    PsiKeyword:class('class')
+    PsiWhiteSpace(' ')
+    PsiIdentifier:C('C')
+    PsiTypeParameterList
+      <empty list>
+    PsiReferenceList
+      <empty list>
+    PsiReferenceList
+      <empty list>
+    PsiJavaToken:LBRACE('{')
+    PsiJavaToken:RBRACE('}')
+  PsiJavaToken:SEMICOLON(';')
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage0.txt b/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage0.txt
index cc9866b..bd210ad 100644
--- a/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage0.txt
+++ b/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage0.txt
@@ -1,5 +1,5 @@
 PsiJavaFile:UnclosedPackage0.java
-  PsiImportList
-    <empty list>
   PsiErrorElement:'class' or 'interface' expected
-    PsiKeyword:package('package')
\ No newline at end of file
+    PsiKeyword:package('package')
+  PsiImportList
+    <empty list>
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/extractMethod/Expression.java b/java/java-tests/testData/refactoring/extractMethod/Expression.java
new file mode 100644
index 0000000..452a7b9
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethod/Expression.java
@@ -0,0 +1,35 @@
+public class AnnotationArgConverter {
+  public GrAnnotationMemberValue convert(PsiAnnotationMemberValue value) {
+    final StringBuilder buffer = new StringBuilder();
+
+    buffer.append("@A(");
+     
+    <selection>value.accept(new JavaElementVisitor() {
+      @Override
+      public void visitExpression(PsiExpression expression) {
+        buffer.append(expression.getText());
+      }
+
+      @Override
+      public void visitNewExpression(PsiNewExpression expression) {
+        PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
+        if (arrayInitializer == null) {
+          super.visitNewExpression(expression);
+        }
+        else {
+          buffer.append(")");
+        }
+      }
+
+    })</selection>;
+
+    buffer.append(")");
+
+    try {
+      return GroovyPsiElementFactory.getInstance(value.getProject()).createAnnotationFromText(buffer.toString());
+    }
+    catch (IncorrectOperationException e) {
+      return null;
+    }
+  }
+}
diff --git a/java/java-tests/testData/refactoring/extractMethod/Expression_after.java b/java/java-tests/testData/refactoring/extractMethod/Expression_after.java
new file mode 100644
index 0000000..03f1402
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethod/Expression_after.java
@@ -0,0 +1,39 @@
+public class AnnotationArgConverter {
+  public GrAnnotationMemberValue convert(PsiAnnotationMemberValue value) {
+    final StringBuilder buffer = new StringBuilder();
+
+    buffer.append("@A(");
+     
+    newMethod(value, buffer);
+
+    buffer.append(")");
+
+    try {
+      return GroovyPsiElementFactory.getInstance(value.getProject()).createAnnotationFromText(buffer.toString());
+    }
+    catch (IncorrectOperationException e) {
+      return null;
+    }
+  }
+
+    private void newMethod(PsiAnnotationMemberValue value, final StringBuilder buffer) {
+        value.accept(new JavaElementVisitor() {
+          @Override
+          public void visitExpression(PsiExpression expression) {
+            buffer.append(expression.getText());
+          }
+    
+          @Override
+          public void visitNewExpression(PsiNewExpression expression) {
+            PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
+            if (arrayInitializer == null) {
+              super.visitNewExpression(expression);
+            }
+            else {
+              buffer.append(")");
+            }
+          }
+    
+        });
+    }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
index f1afadd..536c2cc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
@@ -205,6 +205,7 @@
   public void testIDEADEV40479() throws Exception { doTest(); }
 
   public void testMultilineReturn() throws Exception { doTest(); }
+  public void testMultilineCall() throws Exception { doTest(); }
 
   public void testIDEADEV13019() throws Exception {
     doTestBracesNextLineStyle();
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 0a31d5e..6690708 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
@@ -1464,5 +1464,34 @@
     assert !lookup
   }
 
+  public void "test template prefix is better than middle matches"() {
+    myFixture.configureByText "a.java", """
+class Cls {
+  void foo() {
+    <caret>
+  }
+  void mySout() {}
+}
+""" 
+    type('sout')
+    myFixture.assertPreferredCompletionItems 0, 'sout', 'mySout'
+  }
+
+  public void "test single overriding getter"() {
+    myFixture.configureByText "a.java", """
+public class Foo {
+    public int getField() {}
+}
+
+class X extends Foo {
+    int field;
+
+    <caret>
+}
+"""
+    type 'getf'
+    assert myFixture.lookupElementStrings == ['public int getField']
+  }
+
 
 }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
index fedb91c..5f92714 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
@@ -267,6 +267,27 @@
     myFixture.assertPreferredCompletionItems 0, 'see', 'see bar.Bar', 'see foo.Foo'
   }
 
+  public void testShortenMethodParameterTypes() {
+    CodeStyleSettingsManager.getSettings(getProject()).USE_FQ_CLASS_NAMES_IN_JAVADOC = false
+    try {
+      myFixture.addClass("package foo; public class Foo {}")
+      myFixture.configureByText "a.java", '''
+import foo.*;
+
+/**
+ * {@link #go<caret>
+ */
+class Goo { void goo(Foo foo {} }
+'''
+      myFixture.completeBasic()
+      assert myFixture.editor.document.text.contains('@link #goo(Foo)')
+    }
+    finally {
+      CodeStyleSettingsManager.getSettings(getProject()).USE_FQ_CLASS_NAMES_IN_JAVADOC = true
+    }
+    
+  }
+
   public void testCustomReferenceProvider() throws Exception {
     PsiReferenceRegistrarImpl registrar =
       (PsiReferenceRegistrarImpl) ReferenceProvidersRegistry.getInstance().getRegistrar(StdLanguages.JAVA);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
index 64f2f02c..05e8feb 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
@@ -36,6 +36,10 @@
     checkPreferredItems(0, "return", "register");
   }
 
+  public void testDelegatingConstructorCall() {
+    checkPreferredItems 0, 'element', 'equals'
+  }
+
   public void testPreferAnnotationMethods() throws Throwable {
     checkPreferredItems(0, "name", "value", "Foo", "Anno");
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
index 0363b0f..968d078 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
@@ -16,7 +16,7 @@
 package com.intellij.codeInsight.daemon;
 
 import com.intellij.analysis.PackagesScopesProvider;
-import com.intellij.application.options.colors.ColorAndFontOptions;
+import com.intellij.application.options.colors.ScopeAttributesUtil;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
 import com.intellij.openapi.application.ex.PathManagerEx;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -188,11 +188,11 @@
     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
     manager.addColorsScheme(scheme);
     EditorColorsManager.getInstance().setGlobalScheme(scheme);
-    TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xScope.getName());
+    TextAttributesKey xKey = ScopeAttributesUtil.getScopeTextAttributeKey(xScope.getName());
     TextAttributes xAttributes = new TextAttributes(Color.cyan, Color.darkGray, Color.blue, EffectType.BOXED, Font.ITALIC);
     scheme.setAttributes(xKey, xAttributes);
 
-    TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilScope.getName());
+    TextAttributesKey utilKey = ScopeAttributesUtil.getScopeTextAttributeKey(utilScope.getName());
     TextAttributes utilAttributes = new TextAttributes(Color.gray, Color.magenta, Color.orange, EffectType.STRIKEOUT, Font.BOLD);
     scheme.setAttributes(utilKey, utilAttributes);
 
@@ -215,16 +215,16 @@
     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
     manager.addColorsScheme(scheme);
     EditorColorsManager.getInstance().setGlobalScheme(scheme);
-    TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xScope.getName());
+    TextAttributesKey xKey = ScopeAttributesUtil.getScopeTextAttributeKey(xScope.getName());
     TextAttributes xAttributes = new TextAttributes(Color.cyan, Color.darkGray, Color.blue, null, Font.ITALIC);
     scheme.setAttributes(xKey, xAttributes);
 
-    TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilScope.getName());
+    TextAttributesKey utilKey = ScopeAttributesUtil.getScopeTextAttributeKey(utilScope.getName());
     TextAttributes utilAttributes = new TextAttributes(Color.gray, Color.magenta, Color.orange, EffectType.STRIKEOUT, Font.BOLD);
     scheme.setAttributes(utilKey, utilAttributes);
 
     NamedScope projectScope = PackagesScopesProvider.getInstance(myProject).getProjectProductionScope();
-    TextAttributesKey projectKey = ColorAndFontOptions.getScopeTextAttributeKey(projectScope.getName());
+    TextAttributesKey projectKey = ScopeAttributesUtil.getScopeTextAttributeKey(projectScope.getName());
     TextAttributes projectAttributes = new TextAttributes(null, null, Color.blue, EffectType.BOXED, Font.ITALIC);
     scheme.setAttributes(projectKey, projectAttributes);
 
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
index a0c0ffa..0333f9e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
@@ -314,6 +314,7 @@
   public void testBoxingSpecific() { doTest5(false); }
   public void testIDEA67843() { doTest5(false); }
   public void testAmbiguousTypeParamVsConcrete() { doTest5(false); }
+  public void testRawAssignments() throws Exception { doTest5(false); }
 
   public void testJavaUtilCollections_NoVerify() throws Exception {
     PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
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 9eecd70..064b2c3 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
@@ -83,6 +83,10 @@
     doTest();
   }
 
+  public void testIDEA112323() throws Exception {
+    doTest();
+  }
+
   private void doTest() {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
index 12ed060..223e911 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
@@ -640,4 +640,18 @@
 """
   }
 
+  public void "test stop at SELECTION when invoked surround template by tab"() {
+    myFixture.configureByText "a.txt", "<caret>"
+    
+    final TemplateManager manager = TemplateManager.getInstance(getProject());
+    final Template template = manager.createTemplate("xxx", "user", 'foo $ARG$ bar $END$ goo $SELECTION$ after');
+    template.addVariable("ARG", "", "", true);
+    
+    manager.startTemplate(editor, template);
+    myFixture.type('arg')
+    state.nextTab()
+    assert !state
+    checkResultByText 'foo arg bar  goo <caret> after';
+  }
+
 }
diff --git a/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java
index 95e80d2..72e9c2a 100644
--- a/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java
+++ b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java
@@ -42,6 +42,6 @@
 
   public void testMatcher1()          throws Exception {checkTree("ico");}
   public void testMatcher2()          throws Exception {checkTree("ico");}
-  @Bombed(user = "peter", month = Calendar.AUGUST, day = 20)
+  @Bombed(user = "peter", month = Calendar.SEPTEMBER, day = 20)
   public void testAnonymousMatcher2() throws Exception {checkTree("ico");}
 }
diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java
index 52766f5..8b39692 100644
--- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java
+++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.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,7 +19,6 @@
 import com.intellij.lang.java.parser.JavaParser;
 import com.intellij.lang.java.parser.JavaParsingTestCase;
 
-
 public class FileParserTest extends JavaParsingTestCase {
   public FileParserTest() {
     super("parser-partial/files");
@@ -41,6 +40,10 @@
   public void testUnclosedImport2() { doParserTest("import java.awt."); }
   public void testUnclosedImport3() { doParserTest("import static a"); }
 
+  public void testExtraSemicolons() { doParserTest("package p;;\n" +
+                                                   "import a;;\n" +
+                                                   "class C{};"); }
+
   public void testFileWithClass() { doParserTest("package a;\n" +
                                                  "import b;\n" +
                                                  "public class C { }\n" +
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
index 88537b7..b566465 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java
@@ -591,6 +591,10 @@
     doTest();
   }
 
+  public void testExpression() throws Exception {
+    doTest();
+  }
+
   private void doTestDisabledParam() throws PrepareFailedException {
     final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
     settings.ELSE_ON_NEW_LINE = true;
diff --git a/java/jdkAnnotations/java/lang/annotations.xml b/java/jdkAnnotations/java/lang/annotations.xml
index d5cc0c4..8863fc9 100644
--- a/java/jdkAnnotations/java/lang/annotations.xml
+++ b/java/jdkAnnotations/java/lang/annotations.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <root>
+  <item name='java.lang.Boolean boolean getBoolean(java.lang.String) 0'>
+    <annotation name='org.jetbrains.annotations.NonNls'/>
+  </item>
   <item name="java.lang.CharSequence java.lang.String toString()">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
diff --git a/java/jdkAnnotations/java/util/annotations.xml b/java/jdkAnnotations/java/util/annotations.xml
index 47962ab..58ea647 100644
--- a/java/jdkAnnotations/java/util/annotations.xml
+++ b/java/jdkAnnotations/java/util/annotations.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <root>
+  <item name='java.util.AbstractCollection T[] toArray(T[]) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
   <item name="java.util.ArrayList ArrayList(java.util.Collection&lt;? extends E&gt;) 0">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
@@ -845,6 +848,30 @@
   <item name="java.util.NavigableSet java.util.NavigableSet&lt;E&gt; tailSet(E, boolean)">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
+  <item name='java.util.Set T[] toArray(T[])'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set T[] toArray(T[]) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set boolean addAll(java.util.Collection&lt;? extends E&gt;) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set boolean containsAll(java.util.Collection&lt;?&gt;) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set boolean removeAll(java.util.Collection&lt;?&gt;) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set boolean retainAll(java.util.Collection&lt;?&gt;) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set java.lang.Object[] toArray()'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
+  <item name='java.util.Set java.util.Iterator&lt;E&gt; iterator()'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
   <item name="java.util.SortedMap java.util.Comparator&lt;? super K&gt; comparator()">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
diff --git a/java/jdkAnnotations/java/util/concurrent/annotations.xml b/java/jdkAnnotations/java/util/concurrent/annotations.xml
index 661e32a..0083087 100644
--- a/java/jdkAnnotations/java/util/concurrent/annotations.xml
+++ b/java/jdkAnnotations/java/util/concurrent/annotations.xml
@@ -3,6 +3,9 @@
   <item name="java.util.concurrent.BlockingQueue E poll(long, java.util.concurrent.TimeUnit) 1">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
+  <item name='java.util.concurrent.BlockingQueue boolean offer(E) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
   <item name="java.util.concurrent.BlockingQueue boolean offer(E, long, java.util.concurrent.TimeUnit) 2">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
@@ -201,6 +204,9 @@
   <item name="java.util.concurrent.FutureTask V get(long, java.util.concurrent.TimeUnit) 1">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
+  <item name='java.util.concurrent.LinkedBlockingQueue boolean offer(E) 0'>
+    <annotation name='org.jetbrains.annotations.NotNull'/>
+  </item>
   <item name="java.util.concurrent.ScheduledExecutorService java.util.concurrent.ScheduledFuture&lt;?&gt; schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit)">
     <annotation name="org.jetbrains.annotations.NotNull" />
   </item>
diff --git a/java/manifest/manifest.iml b/java/manifest/manifest.iml
new file mode 100644
index 0000000..1c394dd
--- /dev/null
+++ b/java/manifest/manifest.iml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="util" />
+    <orderEntry type="module" module-name="core-api" />
+    <orderEntry type="module" module-name="analysis-api" />
+    <orderEntry type="module" module-name="platform-api" />
+    <orderEntry type="module" module-name="lang-api" />
+    <orderEntry type="module" module-name="core-impl" />
+    <orderEntry type="module" module-name="java-psi-api" />
+    <orderEntry type="module" module-name="java-impl" />
+    <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+  </component>
+</module>
+
diff --git a/java/manifest/src/inspectionDescriptions/MissingFinalNewline.html b/java/manifest/src/inspectionDescriptions/MissingFinalNewline.html
new file mode 100644
index 0000000..c02bc3b
--- /dev/null
+++ b/java/manifest/src/inspectionDescriptions/MissingFinalNewline.html
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (c) 2007-2009, Osmorc Development Team
+  ~ All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~     * Redistributions of source code must retain the above copyright notice, this list
+  ~       of conditions and the following disclaimer.
+  ~     * Redistributions in binary form must reproduce the above copyright notice, this
+  ~       list of conditions and the following disclaimer in the documentation and/or other
+  ~       materials provided with the distribution.
+  ~     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+  ~       used to endorse or promote products derived from this software without specific
+  ~       prior written permission.
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+  ~ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  ~ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+  ~ THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  ~ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+  ~ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  ~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+  ~ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+  ~ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<html>
+<body>
+  <p>Checks whether a manifest file ends with a final newline (as required by the JAR file specification).</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/java/manifest/src/inspectionDescriptions/MisspelledHeader.html b/java/manifest/src/inspectionDescriptions/MisspelledHeader.html
new file mode 100644
index 0000000..325bcb0
--- /dev/null
+++ b/java/manifest/src/inspectionDescriptions/MisspelledHeader.html
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (c) 2007-2009, Osmorc Development Team
+  ~ All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~     * Redistributions of source code must retain the above copyright notice, this list
+  ~       of conditions and the following disclaimer.
+  ~     * Redistributions in binary form must reproduce the above copyright notice, this
+  ~       list of conditions and the following disclaimer in the documentation and/or other
+  ~       materials provided with the distribution.
+  ~     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+  ~       used to endorse or promote products derived from this software without specific
+  ~       prior written permission.
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+  ~ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  ~ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+  ~ THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  ~ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+  ~ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  ~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+  ~ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+  ~ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<html>
+<body>
+  <p>Reports any unknown and probably misspelled header names and provides possible variants.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java
new file mode 100644
index 0000000..4d5fe2c
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java
@@ -0,0 +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 org.jetbrains.lang.manifest;
+
+import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.PropertyKey;
+
+public class ManifestBundle extends AbstractBundle {
+  public static final String PATH_TO_BUNDLE = "org.jetbrains.lang.manifest.ManifestBundle";
+
+  private static final ManifestBundle BUNDLE = new ManifestBundle();
+
+  private ManifestBundle() {
+    super(PATH_TO_BUNDLE);
+  }
+
+  public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
+    return BUNDLE.getMessage(key, params);
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties
new file mode 100644
index 0000000..b216895
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties
@@ -0,0 +1,14 @@
+manifest.unexpected.token=Unexpected token
+manifest.colon.expected=':' expected
+manifest.whitespace.expected=Whitespace expected
+manifest.header.expected=Header expected
+
+header.reference.invalid=Invalid reference
+header.reference.unknown=Cannot resolve
+header.main.class.invalid=Invalid main class
+
+inspection.group=Manifest
+inspection.newline.message=Manifest file doesn't end with a final newline
+inspection.newline.fix=Add newline
+inspection.header.message=Header name is unknown or spelled incorrectly
+inspection.header.fix=Change to ''{0}''
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileType.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileType.java
new file mode 100644
index 0000000..553d673
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileType.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestFileType extends LanguageFileType {
+  public ManifestFileType() {
+    super(ManifestLanguage.INSTANCE);
+  }
+
+  @NotNull
+  @NonNls
+  @Override
+  public String getName() {
+    return "Manifest";
+  }
+
+  @NotNull
+  @Override
+  public String getDescription() {
+    return "Manifest";
+  }
+
+  @NotNull
+  @NonNls
+  @Override
+  public String getDefaultExtension() {
+    return "MF";
+  }
+
+  @Nullable
+  @Override
+  public Icon getIcon() {
+    return AllIcons.FileTypes.Manifest;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileTypeFactory.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileTypeFactory.java
new file mode 100644
index 0000000..e6e31cc
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestFileTypeFactory.java
@@ -0,0 +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 org.jetbrains.lang.manifest;
+
+import com.intellij.openapi.fileTypes.FileTypeConsumer;
+import com.intellij.openapi.fileTypes.FileTypeFactory;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class ManifestFileTypeFactory extends FileTypeFactory {
+  public final static LanguageFileType MANIFEST = new ManifestFileType();
+
+  @Override
+  public void createFileTypes(@NotNull FileTypeConsumer consumer) {
+    consumer.consume(MANIFEST, "MF");
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestLanguage.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestLanguage.java
new file mode 100644
index 0000000..88204be
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestLanguage.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest;
+
+import com.intellij.lang.Language;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestLanguage extends Language {
+  public static final ManifestLanguage INSTANCE = new ManifestLanguage();
+
+  public ManifestLanguage() {
+    super("Manifest");
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/completion/ManifestCompletionContributor.java b/java/manifest/src/org/jetbrains/lang/manifest/completion/ManifestCompletionContributor.java
new file mode 100644
index 0000000..554c25b
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/completion/ManifestCompletionContributor.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.completion;
+
+import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestLanguage;
+import org.jetbrains.lang.manifest.header.HeaderParserRepository;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+
+/**
+ * Completion contributor which adds the name of all known headers to the autocomplete list.
+ *
+ * @author <a href="mailto:janthomae@janthomae.de">Jan Thom&auml;</a>
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestCompletionContributor extends CompletionContributor {
+  public ManifestCompletionContributor(@NotNull final HeaderParserRepository repository) {
+    extend(CompletionType.BASIC,
+           PlatformPatterns.psiElement(ManifestTokenType.HEADER_NAME).withLanguage(ManifestLanguage.INSTANCE),
+           new CompletionProvider<CompletionParameters>() {
+             @Override
+             public void addCompletions(@NotNull CompletionParameters parameters,
+                                        ProcessingContext context,
+                                        @NotNull CompletionResultSet resultSet) {
+               for (String header : repository.getAllHeaderNames()) {
+                 resultSet.addElement(LookupElementBuilder.create(header).withInsertHandler(HEADER_INSERT_HANDLER));
+               }
+             }
+           }
+    );
+  }
+
+  private static final InsertHandler<LookupElement> HEADER_INSERT_HANDLER = new InsertHandler<LookupElement>() {
+    @Override
+    public void handleInsert(InsertionContext context, LookupElement item) {
+      context.setAddCompletionChar(false);
+      EditorModificationUtil.insertStringAtCaret(context.getEditor(), ": ");
+      context.commitDocument();
+    }
+  };
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java
new file mode 100644
index 0000000..8ab3669
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A match describes how good a header known to a particular header provider matches a given header.
+ * The name of the given header may contain typos and so there may be no perfect match. A perfect match will
+ * have a Levenshtein distance of 0. Worse matches will have greater Levenshtein distances.
+ *
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderNameMatch implements Comparable<HeaderNameMatch> {
+  private final int myDistance;
+  private final String myHeaderName;
+
+  public HeaderNameMatch(int distance, @NotNull String headerName) {
+    myDistance = distance;
+    myHeaderName = headerName;
+  }
+
+  public int getDistance() {
+    return myDistance;
+  }
+
+  public String getHeaderName() {
+    return myHeaderName;
+  }
+
+  /**
+   * Matches are compared based on their distance.
+   */
+  @Override
+  public int compareTo(@NotNull HeaderNameMatch o) {
+    return getDistance() - o.getDistance();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    HeaderNameMatch that = (HeaderNameMatch)o;
+
+    return myDistance == that.myDistance && myHeaderName.equals(that.myHeaderName);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myDistance;
+    result = 31 * result + myHeaderName.hashCode();
+    return result;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParser.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParser.java
new file mode 100644
index 0000000..31c3faf
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParser.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header;
+
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.psi.PsiReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.HeaderValuePart;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface HeaderParser {
+  /**
+   * Parses a header starting from a first token after semicolon and space.
+   */
+  void parse(@NotNull PsiBuilder builder);
+
+  /**
+   * Annotates the header with errors or any other useful information.
+   * Should return true if the element was annotated with errors.
+   */
+  boolean annotate(@NotNull Header header, @NotNull AnnotationHolder holder);
+
+  /**
+   * Returns the raw data of the header converted into some domain specific value (e.g. Version or VersionRange).
+   */
+  @Nullable
+  Object getConvertedValue(@NotNull Header header);
+
+  /**
+   * Returns references from a given header value, or empty array if none/not applicable.
+   */
+  @NotNull
+  PsiReference[] getReferences(@NotNull HeaderValuePart headerValuePart);
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserProvider.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserProvider.java
new file mode 100644
index 0000000..d101349
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface HeaderParserProvider {
+  ExtensionPointName<HeaderParserProvider> EP_NAME = ExtensionPointName.create("com.intellij.manifest.parser.provider");
+
+  @NotNull
+  Map<String, HeaderParser> getHeaderParsers();
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java
new file mode 100644
index 0000000..27b80df
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.text.LevenshteinDistance;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.HeaderValuePart;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderParserRepository {
+  public static HeaderParserRepository getInstance() {
+    return ServiceManager.getService(HeaderParserRepository.class);
+  }
+
+  private final NotNullLazyValue<Map<String, HeaderParser>> myParsers = new NotNullLazyValue<Map<String, HeaderParser>>() {
+    @NotNull
+    @Override
+    protected Map<String, HeaderParser> compute() {
+      Map<String, HeaderParser> map = ContainerUtil.newHashMap();
+      for (HeaderParserProvider provider : Extensions.getExtensions(HeaderParserProvider.EP_NAME)) {
+        map.putAll(provider.getHeaderParsers());
+      }
+      return map;
+    }
+  };
+
+  @Nullable
+  public HeaderParser getHeaderParser(@Nullable String headerName) {
+    return myParsers.getValue().get(headerName);
+  }
+
+  @NotNull
+  public Collection<HeaderNameMatch> getMatches(@NotNull String headerName) {
+    HeaderParser parser = myParsers.getValue().get(headerName);
+    if (parser != null) {
+      return ContainerUtil.emptyList();
+    }
+
+    LevenshteinDistance distance = new LevenshteinDistance();
+    Set<HeaderNameMatch> result = new TreeSet<HeaderNameMatch>();
+    for (Map.Entry<String, HeaderParser> entry : myParsers.getValue().entrySet()) {
+      String otherName = entry.getKey();
+      int dist = distance.calculateMetrics(headerName, otherName);
+      result.add(new HeaderNameMatch(dist, otherName));
+    }
+    return result;
+  }
+
+  @NotNull
+  public Set<String> getAllHeaderNames() {
+    return myParsers.getValue().keySet();
+  }
+
+  @Nullable
+  public Object getConvertedValue(@NotNull Header header) {
+    HeaderParser parser = getHeaderParser(header.getName());
+    return parser != null ? parser.getConvertedValue(header) : null;
+  }
+
+  @NotNull
+  public PsiReference[] getReferences(@NotNull HeaderValuePart headerValuePart) {
+    Header header = PsiTreeUtil.getParentOfType(headerValuePart, Header.class);
+    if (header != null) {
+      HeaderParser parser = getHeaderParser(header.getName());
+      if (parser != null) {
+        return parser.getReferences(headerValuePart);
+      }
+    }
+
+    return PsiReference.EMPTY_ARRAY;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/impl/ClassReferenceParser.java b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/ClassReferenceParser.java
new file mode 100644
index 0000000..3a87727
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/ClassReferenceParser.java
@@ -0,0 +1,97 @@
+/*
+ * 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.lang.manifest.header.impl;
+
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiMethodUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestBundle;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.HeaderValue;
+import org.jetbrains.lang.manifest.psi.HeaderValuePart;
+
+public class ClassReferenceParser extends StandardHeaderParser {
+  public static final HeaderParser INSTANCE = new ClassReferenceParser();
+
+  @NotNull
+  @Override
+  public PsiReference[] getReferences(@NotNull HeaderValuePart headerValuePart) {
+    final Module module = ModuleUtilCore.findModuleForPsiElement(headerValuePart);
+    JavaClassReferenceProvider provider;
+    if (module != null) {
+      provider = new JavaClassReferenceProvider() {
+        @Override
+        public GlobalSearchScope getScope(Project project) {
+          return GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module);
+        }
+      };
+    }
+    else {
+      provider = new JavaClassReferenceProvider();
+    }
+    return provider.getReferencesByElement(headerValuePart);
+  }
+
+  @Override
+  public boolean annotate(@NotNull Header header, @NotNull AnnotationHolder holder) {
+    HeaderValue value = header.getHeaderValue();
+    if (!(value instanceof HeaderValuePart)) return false;
+
+    PsiReference[] references = value.getReferences();
+    if (references.length == 0) {
+      holder.createErrorAnnotation(((HeaderValuePart)value).getHighlightingRange(), ManifestBundle.message("header.reference.invalid"));
+      return true;
+    }
+
+    for (int i = 0; i < references.length; i++) {
+      PsiReference reference = references[i];
+      PsiElement element = reference.resolve();
+      if (element == null) {
+        TextRange range = reference.getRangeInElement().shiftRight(value.getTextOffset());
+        holder.createErrorAnnotation(range, ManifestBundle.message("header.reference.unknown"));
+        return true;
+      }
+
+      if (i == references.length - 1) {
+        if (checkClass(reference, element, holder)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  protected boolean checkClass(@NotNull PsiReference reference, @NotNull PsiElement element, @NotNull AnnotationHolder holder) {
+    if (element instanceof PsiClass && PsiMethodUtil.hasMainMethod((PsiClass)element)) {
+      return false;
+    }
+
+    TextRange range = reference.getRangeInElement().shiftRight(reference.getElement().getTextOffset());
+    holder.createErrorAnnotation(range, ManifestBundle.message("header.main.class.invalid"));
+    return true;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardHeaderParser.java b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardHeaderParser.java
new file mode 100644
index 0000000..7aeb792
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardHeaderParser.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header.impl;
+
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.parser.ManifestParser;
+import org.jetbrains.lang.manifest.psi.*;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class StandardHeaderParser implements HeaderParser {
+  public static final HeaderParser INSTANCE = new StandardHeaderParser();
+
+  @Override
+  public void parse(@NotNull PsiBuilder builder) {
+    PsiBuilder.Marker marker = builder.mark();
+    while (!builder.eof() && !ManifestParser.HEADER_END_TOKENS.contains(builder.getTokenType())) {
+      IElementType lastToken = builder.getTokenType();
+      builder.advanceLexer();
+      if (lastToken == ManifestTokenType.NEWLINE && builder.getTokenType() != ManifestTokenType.SIGNIFICANT_SPACE) {
+        break;
+      }
+    }
+    marker.done(ManifestElementType.HEADER_VALUE_PART);
+  }
+
+  @Override
+  public boolean annotate(@NotNull Header header, @NotNull AnnotationHolder holder) {
+    return false;
+  }
+
+  @Nullable
+  @Override
+  public Object getConvertedValue(@NotNull Header header) {
+    HeaderValue value = header.getHeaderValue();
+    return value != null ? value.getUnwrappedText() : null;
+  }
+
+  @NotNull
+  @Override
+  public PsiReference[] getReferences(@NotNull HeaderValuePart headerValuePart) {
+    return PsiReference.EMPTY_ARRAY;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardManifestHeaderParsers.java b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardManifestHeaderParsers.java
new file mode 100644
index 0000000..c6adcbb
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/header/impl/StandardManifestHeaderParsers.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.header.impl;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.header.HeaderParserProvider;
+
+import java.util.Map;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class StandardManifestHeaderParsers implements HeaderParserProvider {
+  private final Map<String, HeaderParser> myParsers;
+
+  public StandardManifestHeaderParsers() {
+    myParsers = ContainerUtil.newHashMap();
+    myParsers.put("Manifest-Version", StandardHeaderParser.INSTANCE);
+    myParsers.put("Created-By", StandardHeaderParser.INSTANCE);
+    myParsers.put("Signature-Version", StandardHeaderParser.INSTANCE);
+    myParsers.put("Class-Path", StandardHeaderParser.INSTANCE);
+    myParsers.put("Main-Class", ClassReferenceParser.INSTANCE);
+    myParsers.put("Implementation-Title", StandardHeaderParser.INSTANCE);
+    myParsers.put("Implementation-Version", StandardHeaderParser.INSTANCE);
+    myParsers.put("Implementation-Vendor", StandardHeaderParser.INSTANCE);
+    myParsers.put("Implementation-Vendor-Id", StandardHeaderParser.INSTANCE);
+    myParsers.put("Implementation-URL", StandardHeaderParser.INSTANCE);
+    myParsers.put("Specification-Title", StandardHeaderParser.INSTANCE);
+    myParsers.put("Specification-Version", StandardHeaderParser.INSTANCE);
+    myParsers.put("Specification-Vendor", StandardHeaderParser.INSTANCE);
+    myParsers.put("Sealed", StandardHeaderParser.INSTANCE);
+    myParsers.put("Name", StandardHeaderParser.INSTANCE);
+    myParsers.put("Content-Type", StandardHeaderParser.INSTANCE);
+    myParsers.put("Java-Bean", StandardHeaderParser.INSTANCE);
+    myParsers.put("MD5-Digest", StandardHeaderParser.INSTANCE);
+    myParsers.put("SHA-Digest", StandardHeaderParser.INSTANCE);
+    myParsers.put("Magic", StandardHeaderParser.INSTANCE);
+  }
+
+  @NotNull
+  @Override
+  public Map<String, HeaderParser> getHeaderParsers() {
+    return myParsers;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/HeaderAnnotator.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/HeaderAnnotator.java
new file mode 100644
index 0000000..bf2c43e
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/HeaderAnnotator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.highlighting;
+
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.Annotator;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.header.HeaderParserRepository;
+import org.jetbrains.lang.manifest.psi.Header;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderAnnotator implements Annotator {
+  private final HeaderParserRepository myRepository;
+
+  public HeaderAnnotator(@NotNull HeaderParserRepository repository) {
+    myRepository = repository;
+  }
+
+  @Override
+  public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
+    if (psiElement instanceof Header) {
+      Header header = (Header)psiElement;
+      HeaderParser headerParser = myRepository.getHeaderParser(header.getName());
+      if (headerParser != null) {
+        headerParser.annotate(header, holder);
+      }
+    }
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestColorsAndFonts.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestColorsAndFonts.java
new file mode 100644
index 0000000..453235d
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestColorsAndFonts.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.highlighting;
+
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestColorsAndFonts {
+  public static final TextAttributesKey HEADER_NAME_KEY =
+    TextAttributesKey.createTextAttributesKey("manifest.header.name", DefaultLanguageHighlighterColors.KEYWORD);
+  public static final TextAttributesKey HEADER_ASSIGNMENT_KEY =
+    TextAttributesKey.createTextAttributesKey("manifest.header.assignment", DefaultLanguageHighlighterColors.OPERATION_SIGN);
+  public static final TextAttributesKey HEADER_VALUE_KEY =
+    TextAttributesKey.createTextAttributesKey("manifest.header.value", DefaultLanguageHighlighterColors.IDENTIFIER);
+
+  private ManifestColorsAndFonts() { }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestSyntaxHighlighterFactory.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestSyntaxHighlighterFactory.java
new file mode 100644
index 0000000..765eac5
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/ManifestSyntaxHighlighterFactory.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 org.jetbrains.lang.manifest.highlighting;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.parser.ManifestLexer;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ManifestSyntaxHighlighterFactory extends SyntaxHighlighterFactory {
+  public static final SyntaxHighlighter HIGHLIGHTER = new SyntaxHighlighterBase() {
+    private final Map<IElementType, TextAttributesKey> myAttributes;
+    {
+      myAttributes = new HashMap<IElementType, TextAttributesKey>();
+      myAttributes.put(ManifestTokenType.HEADER_NAME, ManifestColorsAndFonts.HEADER_NAME_KEY);
+      myAttributes.put(ManifestTokenType.COLON, ManifestColorsAndFonts.HEADER_ASSIGNMENT_KEY);
+      myAttributes.put(ManifestTokenType.HEADER_VALUE_PART, ManifestColorsAndFonts.HEADER_VALUE_KEY);
+    }
+
+    @NotNull
+    @Override
+    public Lexer getHighlightingLexer() {
+      return new ManifestLexer();
+    }
+
+    @NotNull
+    @Override
+    public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+      return pack(myAttributes.get(tokenType));
+    }
+  };
+
+  @NotNull
+  @Override
+  public SyntaxHighlighter getSyntaxHighlighter(@Nullable Project project, @Nullable VirtualFile virtualFile) {
+    return HIGHLIGHTER;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java
new file mode 100644
index 0000000..7404b27
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.highlighting;
+
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestBundle;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.ManifestFile;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+import org.jetbrains.lang.manifest.psi.Section;
+
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class MissingFinalNewlineInspection extends LocalInspectionTool {
+  @Override
+  public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
+    if (file instanceof ManifestFile) {
+      String text = file.getText();
+      if (text != null && text.length() > 0 && !StringUtil.endsWith(text, "\n")) {
+        List<Section> sections = ((ManifestFile)file).getSections();
+        assert sections.size() > 0 : text;
+        Section section = sections.get(sections.size() - 1);
+        ProblemDescriptor descriptor = manager.createProblemDescriptor(
+          section.getLastChild(), ManifestBundle.message("inspection.newline.message"),
+          new AddNewlineQuickFix(section), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly
+        );
+        return new ProblemDescriptor[]{descriptor};
+      }
+    }
+
+    return null;
+  }
+
+  private static class AddNewlineQuickFix implements LocalQuickFix {
+    private final Section mySection;
+
+    private AddNewlineQuickFix(Section section) {
+      mySection = section;
+    }
+
+    @NotNull
+    @Override
+    public String getName() {
+      return ManifestBundle.message("inspection.newline.fix");
+    }
+
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return ManifestBundle.message("inspection.group");
+    }
+
+    @Override
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      PsiElement lastChild = mySection.getLastChild();
+      if (lastChild instanceof Header) {
+        lastChild.getNode().addLeaf(ManifestTokenType.NEWLINE, "\n", null);
+      }
+    }
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java
new file mode 100644
index 0000000..75f4176
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.highlighting;
+
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestBundle;
+import org.jetbrains.lang.manifest.header.HeaderNameMatch;
+import org.jetbrains.lang.manifest.header.HeaderParserRepository;
+import org.jetbrains.lang.manifest.psi.Header;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class MisspelledHeaderInspection extends LocalInspectionTool {
+  private static final int MAX_SUGGESTIONS = 10;
+
+  private HeaderParserRepository myRepository;
+
+  public MisspelledHeaderInspection() {
+    myRepository = HeaderParserRepository.getInstance();
+  }
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+    return new PsiElementVisitor() {
+      @Override
+      public void visitElement(PsiElement element) {
+        if (element instanceof Header) {
+          Header header = (Header)element;
+          Collection<HeaderNameMatch> matches = myRepository.getMatches(header.getName());
+          if (!matches.isEmpty()) {
+            List<HeaderNameSpellingQuickFix> fixes = ContainerUtil.newArrayListWithCapacity(MAX_SUGGESTIONS);
+            for (HeaderNameMatch match : matches) {
+              fixes.add(new HeaderNameSpellingQuickFix(header, match));
+              if (fixes.size() == MAX_SUGGESTIONS) {
+                break;
+              }
+            }
+            holder.registerProblem(
+              header.getNameElement(), ManifestBundle.message("inspection.header.message"),
+              ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes.toArray(new HeaderNameSpellingQuickFix[fixes.size()])
+            );
+          }
+        }
+      }
+    };
+  }
+
+  private static class HeaderNameSpellingQuickFix implements LocalQuickFix {
+    private final Header myHeader;
+    private final String myNewName;
+
+    private HeaderNameSpellingQuickFix(Header header, HeaderNameMatch match) {
+      myHeader = header;
+      myNewName = match.getHeaderName();
+    }
+
+    @NotNull
+    @Override
+    public String getName() {
+      return ManifestBundle.message("inspection.header.fix", myNewName);
+    }
+
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return ManifestBundle.message("inspection.group");
+    }
+
+    @Override
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      myHeader.setName(myNewName);
+    }
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestLexer.java b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestLexer.java
new file mode 100644
index 0000000..26741c2
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestLexer.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.parser;
+
+import com.intellij.lexer.LexerBase;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestLexer extends LexerBase {
+  private enum State {
+    INITIAL_STATE, WAITING_FOR_HEADER_ASSIGNMENT_STATE, WAITING_FOR_SPACE_AFTER_HEADER_NAME_STATE, BROKEN_LINE
+  }
+
+  private static final Map<Character, IElementType> SPECIAL_CHARACTERS_TOKEN_MAPPING;
+  static {
+    SPECIAL_CHARACTERS_TOKEN_MAPPING = new HashMap<Character, IElementType>();
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put(':', ManifestTokenType.COLON);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put(';', ManifestTokenType.SEMICOLON);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put(',', ManifestTokenType.COMMA);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put('=', ManifestTokenType.EQUALS);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put('(', ManifestTokenType.OPENING_PARENTHESIS_TOKEN);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put(')', ManifestTokenType.CLOSING_PARENTHESIS_TOKEN);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put('[', ManifestTokenType.OPENING_BRACKET_TOKEN);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put(']', ManifestTokenType.CLOSING_BRACKET_TOKEN);
+    SPECIAL_CHARACTERS_TOKEN_MAPPING.put('\"', ManifestTokenType.QUOTE);
+  }
+
+  private CharSequence myBuffer;
+  private int myEndOffset;
+  private int myTokenStart;
+  private int myTokenEnd;
+  private State myCurrentState;
+  private IElementType myTokenType;
+
+  @Override
+  public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
+    this.myBuffer = buffer;
+    this.myEndOffset = endOffset;
+    myCurrentState = State.values()[initialState];
+
+    myTokenStart = startOffset;
+    parseNextToken();
+  }
+
+  @Override
+  public void advance() {
+    myTokenStart = myTokenEnd;
+    parseNextToken();
+  }
+
+  @Override
+  public int getState() {
+    return myCurrentState.ordinal();
+  }
+
+  @Nullable
+  @Override
+  public IElementType getTokenType() {
+    return myTokenType;
+  }
+
+  @Override
+  public int getTokenStart() {
+    return myTokenStart;
+  }
+
+  @Override
+  public int getTokenEnd() {
+    return myTokenEnd;
+  }
+
+  @Override
+  public int getBufferEnd() {
+    return myEndOffset;
+  }
+
+  @Override
+  public CharSequence getBufferSequence() {
+    return myBuffer;
+  }
+
+  private void parseNextToken() {
+    if (myTokenStart < myEndOffset) {
+      if (isNewline(myTokenStart)) {
+        myTokenType = isLineStart(myTokenStart) ? ManifestTokenType.SECTION_END : ManifestTokenType.NEWLINE;
+        myTokenEnd = myTokenStart + 1;
+        myCurrentState = State.INITIAL_STATE;
+      }
+      else if (myCurrentState == State.WAITING_FOR_HEADER_ASSIGNMENT_STATE) {
+        if (isColon(myTokenStart)) {
+          myTokenType = ManifestTokenType.COLON;
+          myCurrentState = State.WAITING_FOR_SPACE_AFTER_HEADER_NAME_STATE;
+        }
+        else {
+          myTokenType = TokenType.BAD_CHARACTER;
+        }
+        myTokenEnd = myTokenStart + 1;
+      }
+      else if (myCurrentState == State.WAITING_FOR_SPACE_AFTER_HEADER_NAME_STATE) {
+        if (isSpace(myTokenStart)) {
+          myTokenEnd = myTokenStart + 1;
+          myTokenType = ManifestTokenType.SIGNIFICANT_SPACE;
+        }
+        else {
+          myTokenEnd = myTokenStart;
+          while (myTokenEnd < myEndOffset && !isSpecialCharacter(myTokenEnd) && !isNewline(myTokenEnd)) {
+            myTokenEnd++;
+          }
+          myTokenType = ManifestTokenType.HEADER_VALUE_PART;
+        }
+        myCurrentState = State.INITIAL_STATE;
+      }
+      else if (isHeaderStart(myTokenStart)) {
+        if (isAlphaNum(myTokenStart)) {
+          myTokenEnd = myTokenStart + 1;
+          while (myTokenEnd < myEndOffset && isHeaderChar(myTokenEnd)) {
+            myTokenEnd++;
+          }
+          myTokenType = ManifestTokenType.HEADER_NAME;
+          myCurrentState = State.WAITING_FOR_HEADER_ASSIGNMENT_STATE;
+        }
+        else {
+          myTokenEnd = myTokenStart + 1;
+          myTokenType = TokenType.BAD_CHARACTER;
+          myCurrentState = State.BROKEN_LINE;
+        }
+      }
+      else if (isContinuationStart(myTokenStart)) {
+        myTokenType = ManifestTokenType.SIGNIFICANT_SPACE;
+        myTokenEnd = myTokenStart + 1;
+        myCurrentState = State.INITIAL_STATE;
+      }
+      else if (myCurrentState == State.BROKEN_LINE) {
+        myTokenEnd = myTokenStart + 1;
+        myTokenType = TokenType.BAD_CHARACTER;
+      }
+      else if (isSpecialCharacter(myTokenStart)) {
+        myTokenType = getTokenTypeForSpecialCharacter(myTokenStart);
+        myTokenEnd = myTokenStart + 1;
+        myCurrentState = State.INITIAL_STATE;
+      }
+      else {
+        myTokenEnd = myTokenStart;
+        while (myTokenEnd < myEndOffset && !isSpecialCharacter(myTokenEnd) && !isNewline(myTokenEnd)) {
+          myTokenEnd++;
+        }
+        myTokenType = ManifestTokenType.HEADER_VALUE_PART;
+      }
+    }
+    else {
+      myTokenType = null;
+      myTokenEnd = myTokenStart;
+    }
+  }
+
+  private boolean isNewline(int position) {
+    return myBuffer.charAt(position) == '\n';
+  }
+
+  private boolean isHeaderStart(int position) {
+    return isLineStart(position) && !Character.isWhitespace(myBuffer.charAt(position));
+  }
+
+  private boolean isAlphaNum(int position) {
+    return Character.isLetterOrDigit(myBuffer.charAt(position));
+  }
+
+  private boolean isHeaderChar(int position) {
+    return isAlphaNum(position) || myBuffer.charAt(position) == '-' || myBuffer.charAt(position) == '_';
+  }
+
+  private boolean isContinuationStart(int position) {
+    return isLineStart(position) && !isHeaderStart(position);
+  }
+
+  private boolean isLineStart(int position) {
+    return position == 0 || isNewline(position - 1);
+  }
+
+  private boolean isSpace(int position) {
+    return myBuffer.charAt(position) == ' ';
+  }
+
+  private boolean isColon(int position) {
+    return myBuffer.charAt(position) == ':';
+  }
+
+  private boolean isSpecialCharacter(int position) {
+    return SPECIAL_CHARACTERS_TOKEN_MAPPING.get(myBuffer.charAt(position)) != null;
+  }
+
+  private IElementType getTokenTypeForSpecialCharacter(int position) {
+    return SPECIAL_CHARACTERS_TOKEN_MAPPING.get(myBuffer.charAt(position));
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParser.java b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParser.java
new file mode 100644
index 0000000..de22144
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParser.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.parser;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestBundle;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.header.HeaderParserRepository;
+import org.jetbrains.lang.manifest.header.impl.StandardHeaderParser;
+import org.jetbrains.lang.manifest.psi.ManifestElementType;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+
+import static com.intellij.lang.PsiBuilderUtil.expect;
+import static com.intellij.util.ObjectUtils.notNull;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestParser implements PsiParser {
+  public static final TokenSet HEADER_END_TOKENS = TokenSet.create(ManifestTokenType.SECTION_END, ManifestTokenType.HEADER_NAME);
+
+  private final HeaderParserRepository myRepository;
+
+  public ManifestParser() {
+    myRepository = ServiceManager.getService(HeaderParserRepository.class);
+  }
+
+  @NotNull
+  @Override
+  public ASTNode parse(IElementType root, PsiBuilder builder) {
+    builder.setDebugMode(ApplicationManager.getApplication().isUnitTestMode());
+
+    PsiBuilder.Marker rootMarker = builder.mark();
+    while (!builder.eof()) {
+      parseSection(builder);
+    }
+    rootMarker.done(root);
+
+    return builder.getTreeBuilt();
+  }
+
+  private void parseSection(PsiBuilder builder) {
+    PsiBuilder.Marker section = builder.mark();
+
+    while (!builder.eof()) {
+      IElementType tokenType = builder.getTokenType();
+      if (tokenType == ManifestTokenType.HEADER_NAME) {
+        parseHeader(builder);
+      }
+      else if (tokenType == ManifestTokenType.SECTION_END) {
+        builder.advanceLexer();
+        break;
+      }
+      else {
+        PsiBuilder.Marker marker = builder.mark();
+        consumeHeaderValue(builder);
+        marker.error(ManifestBundle.message("manifest.header.expected"));
+      }
+    }
+
+    section.done(ManifestElementType.SECTION);
+  }
+
+  private void parseHeader(PsiBuilder builder) {
+    PsiBuilder.Marker header = builder.mark();
+    String headerName = builder.getTokenText();
+    assert headerName != null : "[" + builder.getOriginalText() + "]@" + builder.getCurrentOffset();
+    builder.advanceLexer();
+
+    PsiBuilder.Marker errors = null;
+    if (builder.getTokenType() == TokenType.BAD_CHARACTER) {
+      errors = builder.mark();
+      while (builder.getTokenType() == TokenType.BAD_CHARACTER) {
+        builder.advanceLexer();
+      }
+      errors.error(ManifestBundle.message("manifest.unexpected.token"));
+    }
+
+    if (builder.getTokenType() == ManifestTokenType.COLON) {
+      builder.advanceLexer();
+
+      if (!expect(builder, ManifestTokenType.SIGNIFICANT_SPACE)) {
+        builder.error(ManifestBundle.message("manifest.whitespace.expected"));
+      }
+
+      HeaderParser headerParser = notNull(myRepository.getHeaderParser(headerName), StandardHeaderParser.INSTANCE);
+      headerParser.parse(builder);
+    }
+    else {
+      PsiBuilder.Marker marker;
+      if (errors == null) {
+        marker = builder.mark();
+      }
+      else {
+        marker = errors.precede();
+        errors.drop();
+      }
+      consumeHeaderValue(builder);
+      marker.error(ManifestBundle.message("manifest.colon.expected"));
+    }
+
+    header.done(ManifestElementType.HEADER);
+  }
+
+  private static void consumeHeaderValue(PsiBuilder builder) {
+    while (!builder.eof() && !HEADER_END_TOKENS.contains(builder.getTokenType())) {
+      builder.advanceLexer();
+    }
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParserDefinition.java b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParserDefinition.java
new file mode 100644
index 0000000..dfe1d97
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/parser/ManifestParserDefinition.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.parser;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiUtilCore;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.ManifestElementType;
+import org.jetbrains.lang.manifest.psi.impl.ManifestFileImpl;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestParserDefinition implements ParserDefinition {
+  @NotNull
+  @Override
+  public Lexer createLexer(Project project) {
+    return new ManifestLexer();
+  }
+
+  @Override
+  public PsiParser createParser(Project project) {
+    return new ManifestParser();
+  }
+
+  @Override
+  public IFileElementType getFileNodeType() {
+    return ManifestElementType.FILE;
+  }
+
+  @NotNull
+  @Override
+  public TokenSet getWhitespaceTokens() {
+    return TokenSet.EMPTY;
+  }
+
+  @NotNull
+  @Override
+  public TokenSet getCommentTokens() {
+    return TokenSet.EMPTY;
+  }
+
+  @NotNull
+  @Override
+  public TokenSet getStringLiteralElements() {
+    return TokenSet.EMPTY;
+  }
+
+  @NotNull
+  @Override
+  public PsiElement createElement(ASTNode node) {
+    IElementType type = node.getElementType();
+    if (type instanceof ManifestElementType) {
+      return ((ManifestElementType)type).createPsi(node);
+    }
+
+    return PsiUtilCore.NULL_PSI_ELEMENT;
+  }
+
+  @Override
+  public PsiFile createFile(FileViewProvider viewProvider) {
+    return new ManifestFileImpl(viewProvider);
+  }
+
+  @SuppressWarnings("SpellCheckingInspection")
+  @Override
+  public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+    return left.getPsi() instanceof Header || right.getPsi() instanceof Header ?
+           SpaceRequirements.MUST_LINE_BREAK : SpaceRequirements.MUST_NOT;
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/Header.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/Header.java
new file mode 100644
index 0000000..9528a77
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/Header.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.psi.PsiNamedElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface Header extends PsiNamedElement {
+  @NotNull
+  @Override
+  String getName();
+
+  @NotNull
+  ManifestToken getNameElement();
+
+  /**
+   * Returns a first header value element if exists.
+   */
+  @Nullable
+  HeaderValue getHeaderValue();
+
+  /**
+   * Returns a list of all header value elements.
+   */
+  @NotNull
+  List<HeaderValue> getHeaderValues();
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValue.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValue.java
new file mode 100644
index 0000000..98ccb22
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValue.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A manifest header value is a "common ground" for any element
+ * produced by {@link org.jetbrains.lang.manifest.header.HeaderParser} implementations.
+ *
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface HeaderValue extends PsiElement {
+  /**
+   * Returns the unwrapped text without the newlines and extra continuation spaces.
+   */
+  @NotNull
+  String getUnwrappedText();
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValuePart.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValuePart.java
new file mode 100644
index 0000000..624a661
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/HeaderValuePart.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A header value part is either the whole value of a header or the building block for complex structures.
+ *
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface HeaderValuePart extends HeaderValue {
+  /**
+   * Returns the range to highlight in the element.
+   */
+  @NotNull
+  TextRange getHighlightingRange();
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestElementType.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestElementType.java
new file mode 100644
index 0000000..a6a9d61
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestElementType.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.IFileElementType;
+import org.jetbrains.lang.manifest.ManifestLanguage;
+import org.jetbrains.lang.manifest.psi.impl.HeaderImpl;
+import org.jetbrains.lang.manifest.psi.impl.HeaderValuePartImpl;
+import org.jetbrains.lang.manifest.psi.impl.SectionImpl;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public abstract class ManifestElementType extends IElementType {
+  public static final IFileElementType FILE = new IFileElementType("ManifestFile", ManifestLanguage.INSTANCE);
+
+  public static final IElementType SECTION = new ManifestElementType("SECTION") {
+    @Override
+    public PsiElement createPsi(ASTNode node) {
+      return new SectionImpl(node);
+    }
+  };
+
+  public static final IElementType HEADER = new ManifestElementType("HEADER") {
+    @Override
+    public PsiElement createPsi(ASTNode node) {
+      return new HeaderImpl(node);
+    }
+  };
+
+  public static final IElementType HEADER_VALUE_PART = new ManifestElementType("HEADER_VALUE_PART") {
+    @Override
+    public PsiElement createPsi(ASTNode node) {
+      return new HeaderValuePartImpl(node);
+    }
+  };
+
+  public ManifestElementType(String name) {
+    super(name, ManifestLanguage.INSTANCE);
+  }
+
+  public abstract PsiElement createPsi(ASTNode node);
+
+  @Override
+  public String toString() {
+    return "MF:" + super.toString();
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestFile.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestFile.java
new file mode 100644
index 0000000..a262859
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestFile.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface ManifestFile extends PsiFile {
+  /**
+   * Returns all sections of the file.
+   */
+  @NotNull
+  List<Section> getSections();
+
+  /**
+   * Returns main (first) section if not empty.
+   */
+  @Nullable
+  Section getMainSection();
+
+  /**
+   * Returns all headers from the main section in this file.
+   */
+  @NotNull
+  List<Header> getHeaders();
+
+  /**
+   * Returns the header from the main section with the given name, or null if no such header exists.
+   */
+  @Nullable
+  Header getHeader(@NotNull String name);
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestToken.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestToken.java
new file mode 100644
index 0000000..4d5260b
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestToken.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface ManifestToken extends PsiElement {
+  ManifestTokenType getTokenType();
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestTokenType.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestTokenType.java
new file mode 100644
index 0000000..8a0a70d
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/ManifestTokenType.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.ILeafElementType;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.ManifestLanguage;
+import org.jetbrains.lang.manifest.psi.impl.ManifestTokenImpl;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public final class ManifestTokenType extends IElementType implements ILeafElementType {
+  public static final ManifestTokenType HEADER_NAME = new ManifestTokenType("HEADER_NAME_TOKEN");
+  public static final ManifestTokenType NEWLINE = new ManifestTokenType("NEWLINE_TOKEN");
+  public static final ManifestTokenType SECTION_END = new ManifestTokenType("SECTION_END_TOKEN");
+  public static final ManifestTokenType COLON = new ManifestTokenType("COLON_TOKEN");
+  public static final ManifestTokenType SEMICOLON = new ManifestTokenType("SEMICOLON_TOKEN");
+  public static final ManifestTokenType EQUALS = new ManifestTokenType("EQUALS_TOKEN");
+  public static final ManifestTokenType COMMA = new ManifestTokenType("COMMA_TOKEN");
+  public static final ManifestTokenType QUOTE = new ManifestTokenType("QUOTE_TOKEN");
+  public static final ManifestTokenType HEADER_VALUE_PART = new ManifestTokenType("HEADER_VALUE_PART_TOKEN");
+  public static final ManifestTokenType SIGNIFICANT_SPACE = new ManifestTokenType("SIGNIFICANT_SPACE_TOKEN");
+  public static final ManifestTokenType OPENING_PARENTHESIS_TOKEN = new ManifestTokenType("OPENING_PARENTHESIS_TOKEN");
+  public static final ManifestTokenType CLOSING_PARENTHESIS_TOKEN = new ManifestTokenType("CLOSING_PARENTHESIS_TOKEN");
+  public static final ManifestTokenType OPENING_BRACKET_TOKEN = new ManifestTokenType("OPENING_BRACKET_TOKEN");
+  public static final ManifestTokenType CLOSING_BRACKET_TOKEN = new ManifestTokenType("CLOSING_BRACKET_TOKEN");
+
+  private ManifestTokenType(@NotNull @NonNls String debugName) {
+    super(debugName, ManifestLanguage.INSTANCE);
+  }
+
+  @NotNull
+  @Override
+  public ASTNode createLeafNode(CharSequence text) {
+    return new ManifestTokenImpl(this, text);
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/Section.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/Section.java
new file mode 100644
index 0000000..d36a6e2
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/Section.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi;
+
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public interface Section extends PsiElement {
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderImpl.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderImpl.java
new file mode 100644
index 0000000..e14bb98
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.tree.LeafElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.psi.*;
+
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderImpl extends ASTWrapperPsiElement implements Header {
+  public HeaderImpl(@NotNull ASTNode node) {
+    super(node);
+  }
+
+  @NotNull
+  @Override
+  public String getName() {
+    return getNameElement().getText();
+  }
+
+  @Override
+  public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
+    ((LeafElement)getNameElement().getNode()).replaceWithText(name);
+    return this;
+  }
+
+  @NotNull
+  @Override
+  public ManifestToken getNameElement() {
+    ManifestToken token = (ManifestToken)getNode().findChildByType(ManifestTokenType.HEADER_NAME);
+    assert token != null : getText();
+    return token;
+  }
+
+  @Nullable
+  @Override
+  public HeaderValue getHeaderValue() {
+    return PsiTreeUtil.getChildOfType(this, HeaderValue.class);
+  }
+
+  @NotNull
+  @Override
+  public List<HeaderValue> getHeaderValues() {
+    return PsiTreeUtil.getChildrenOfTypeAsList(this, HeaderValue.class);
+  }
+
+  @Override
+  public String toString() {
+    return "Header:" + getName();
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartImpl.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartImpl.java
new file mode 100644
index 0000000..a9c7fe2
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+import org.jetbrains.lang.manifest.header.HeaderParserRepository;
+import org.jetbrains.lang.manifest.psi.HeaderValuePart;
+import org.jetbrains.lang.manifest.psi.ManifestToken;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderValuePartImpl extends ASTWrapperPsiElement implements HeaderValuePart {
+  private final HeaderParserRepository myRepository;
+
+  public HeaderValuePartImpl(ASTNode node) {
+    super(node);
+    myRepository = ServiceManager.getService(HeaderParserRepository.class);
+  }
+
+  @NotNull
+  @Override
+  public PsiReference[] getReferences() {
+    return getUnwrappedText().isEmpty() ? PsiReference.EMPTY_ARRAY : myRepository.getReferences(this);
+  }
+
+  @NotNull
+  @Override
+  public String getUnwrappedText() {
+    StringBuilder builder = new StringBuilder();
+
+    for (PsiElement element = getFirstChild(); element != null; element = element.getNextSibling()) {
+      if (element instanceof ManifestToken) {
+        ManifestTokenType tokenType = ((ManifestToken)element).getTokenType();
+        if (tokenType == ManifestTokenType.NEWLINE || tokenType == ManifestTokenType.SIGNIFICANT_SPACE) {
+          continue;
+        }
+      }
+      builder.append(element.getText());
+    }
+
+    return builder.toString().trim();
+  }
+
+  @NotNull
+  @Override
+  public TextRange getHighlightingRange() {
+    PsiElement last = getLastChild();
+    if (last instanceof ManifestToken && ((ManifestToken)last).getTokenType() == ManifestTokenType.NEWLINE) {
+      int start = getTextOffset();
+      PsiElement prev = last.getPrevSibling();
+      return new TextRange(start, prev != null ? prev.getTextRange().getEndOffset() : start);
+    }
+    return getTextRange();
+  }
+
+  @Override
+  public String toString() {
+    return "HeaderValuePart";
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartManipulator.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartManipulator.java
new file mode 100644
index 0000000..156b7b6
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/HeaderValuePartManipulator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.lang.manifest.ManifestFileTypeFactory;
+import org.jetbrains.lang.manifest.psi.HeaderValue;
+import org.jetbrains.lang.manifest.psi.HeaderValuePart;
+import org.jetbrains.lang.manifest.psi.ManifestFile;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class HeaderValuePartManipulator extends AbstractElementManipulator<HeaderValuePart> {
+  @Override
+  public HeaderValuePart handleContentChange(HeaderValuePart element, TextRange range, String newContent) throws IncorrectOperationException {
+    String text = "HeaderValuePartManipulator: " + range.replace(element.getText(), newContent);
+    PsiFile file = PsiFileFactory.getInstance(element.getProject()).createFileFromText("DUMMY.MF", ManifestFileTypeFactory.MANIFEST, text);
+    HeaderValue value = ((ManifestFile)file).getHeaders().get(0).getHeaderValue();
+    assert value != null : text;
+    return (HeaderValuePart)element.replace(value);
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestFileImpl.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestFileImpl.java
new file mode 100644
index 0000000..97f5e35
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestFileImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.extapi.psi.PsiFileBase;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.ManifestFileTypeFactory;
+import org.jetbrains.lang.manifest.ManifestLanguage;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.ManifestFile;
+import org.jetbrains.lang.manifest.psi.Section;
+
+import java.util.List;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestFileImpl extends PsiFileBase implements ManifestFile {
+  public ManifestFileImpl(FileViewProvider viewProvider) {
+    super(viewProvider, ManifestLanguage.INSTANCE);
+  }
+
+  @NotNull
+  @Override
+  public FileType getFileType() {
+    return ManifestFileTypeFactory.MANIFEST;
+  }
+
+  @NotNull
+  @Override
+  public List<Section> getSections() {
+    return PsiTreeUtil.getChildrenOfTypeAsList(this, Section.class);
+  }
+
+  @Nullable
+  @Override
+  public Section getMainSection() {
+    return findChildByClass(Section.class);
+  }
+
+  @NotNull
+  @Override
+  public List<Header> getHeaders() {
+    return PsiTreeUtil.getChildrenOfTypeAsList(getFirstChild(), Header.class);
+  }
+
+  @Nullable
+  @Override
+  public Header getHeader(@NotNull String name) {
+    Header child = PsiTreeUtil.findChildOfType(getFirstChild(), Header.class);
+    while (child != null) {
+      if (name.equals(child.getName())) {
+        return child;
+      }
+      child = PsiTreeUtil.getNextSiblingOfType(child, Header.class);
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    return "ManifestFile:" + getName();
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestTokenImpl.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestTokenImpl.java
new file mode 100644
index 0000000..4bd603a
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/ManifestTokenImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import org.jetbrains.lang.manifest.psi.ManifestToken;
+import org.jetbrains.lang.manifest.psi.ManifestTokenType;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestTokenImpl extends LeafPsiElement implements ManifestToken {
+  public ManifestTokenImpl(ManifestTokenType type, CharSequence text) {
+    super(type, text);
+  }
+
+  @Override
+  public ManifestTokenType getTokenType() {
+    return (ManifestTokenType)getElementType();
+  }
+
+  @Override
+  public String toString() {
+    return "ManifestToken:" + getTokenType();
+  }
+}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/SectionImpl.java b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/SectionImpl.java
new file mode 100644
index 0000000..2df8ce1
--- /dev/null
+++ b/java/manifest/src/org/jetbrains/lang/manifest/psi/impl/SectionImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest.psi.impl;
+
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import org.jetbrains.lang.manifest.psi.Section;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class SectionImpl extends ASTWrapperPsiElement implements Section {
+  public SectionImpl(ASTNode node) {
+    super(node);
+  }
+
+  @Override
+  public String toString() {
+    return "Section";
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java
new file mode 100644
index 0000000..a0f1bb9
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.lang.manifest;
+
+import com.intellij.codeInsight.completion.LightCompletionTestCase;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+public class ManifestCompletionTest extends LightCompletionTestCase {
+  public void testHeaderNameCompletionVariants() throws Exception {
+    LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
+    complete();
+    assertContainsItems("Specification-Vendor", "Specification-Version");
+    assertNotContainItems("Specification-Title");
+  }
+
+  public void testHeaderNameEnterCompletion() throws Exception {
+    LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
+    complete();
+    assertContainsItems("Specification-Vendor");
+    selectItem(myItems[0], '\n');
+    checkResultByText("Specification-Vendor: <caret>\n");
+  }
+
+  public void testHeaderNameColonCompletion() throws Exception {
+    LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
+    complete();
+    assertContainsItems("Specification-Vendor");
+    selectItem(myItems[0], ':');
+    checkResultByText("Specification-Vendor: <caret>\n");
+  }
+
+  public void testHeaderNameSpaceCompletion() throws Exception {
+    LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
+    complete();
+    assertContainsItems("Specification-Vendor");
+    selectItem(myItems[0], ' ');
+    checkResultByText("Specification-Vendor: <caret>\n");
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestHighlightingTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestHighlightingTest.java
new file mode 100644
index 0000000..178a75a
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestHighlightingTest.java
@@ -0,0 +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 org.jetbrains.lang.manifest;
+
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+
+public class ManifestHighlightingTest extends LightCodeInsightFixtureTestCase {
+  public void testMainClass() {
+    doTest(
+      "Main-Class: <error descr=\"Invalid reference\"></error>\n" +
+      "Main-Class: org.<error descr=\"Cannot resolve\">acme</error>.Main\n" +
+      "Main-Class: java.lang.<error descr=\"Invalid main class\">String</error>\n"
+    );
+  }
+
+  private void doTest(String text) {
+    myFixture.configureByText("MANIFEST.MF", text);
+    myFixture.checkHighlighting(true, false, false);
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestLexerTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestLexerTest.java
new file mode 100644
index 0000000..8966131
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestLexerTest.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.lang.manifest;
+
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.lang.manifest.parser.ManifestLexer;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestLexerTest {
+  @Test
+  public void testSpaces() {
+    doTest("   ",
+
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('  ')");
+  }
+
+  @Test
+  public void testRandomText() {
+    doTest("some text\nsome more text",
+
+           "HEADER_NAME_TOKEN ('some')\n" +
+           "BAD_CHARACTER (' ')\n" +
+           "BAD_CHARACTER ('t')\n" +
+           "BAD_CHARACTER ('e')\n" +
+           "BAD_CHARACTER ('x')\n" +
+           "BAD_CHARACTER ('t')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "HEADER_NAME_TOKEN ('some')\n" +
+           "BAD_CHARACTER (' ')\n" +
+           "BAD_CHARACTER ('m')\n" +
+           "BAD_CHARACTER ('o')\n" +
+           "BAD_CHARACTER ('r')\n" +
+           "BAD_CHARACTER ('e')\n" +
+           "BAD_CHARACTER (' ')\n" +
+           "BAD_CHARACTER ('t')\n" +
+           "BAD_CHARACTER ('e')\n" +
+           "BAD_CHARACTER ('x')\n" +
+           "BAD_CHARACTER ('t')");
+  }
+
+  @Test
+  public void testValid() {
+    doTest("Name: Value",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')");
+  }
+
+  @Test
+  public void testInvalidSpaceBeforeColon() {
+    doTest("Name : Value",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "BAD_CHARACTER (' ')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')");
+  }
+
+  @Test
+  public void testMissingSpaceAfterColon() {
+    doTest("Name:Value",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')");
+  }
+
+  @Test
+  public void testTwoHeaders() {
+    doTest("Name: Value\nName2: Value2",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "HEADER_NAME_TOKEN ('Name2')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value2')");
+  }
+
+  @Test
+  public void testContinuation() {
+    doTest("Name: Value\n Value2",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value2')");
+  }
+
+  @Test
+  public void testSection() {
+    doTest("Name: Value\n\nName2: Value2",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "SECTION_END_TOKEN ('\n')\n" +
+           "HEADER_NAME_TOKEN ('Name2')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value2')");
+  }
+
+  @Test
+  public void testNoIgnoredSpaces() {
+    doTest("Name: Value \n   Value2",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('Value ')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('  Value2')");
+  }
+
+  @Test
+  public void testSpecialCharacters() {
+    doTest("Name: ;:=,\"",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "SEMICOLON_TOKEN (';')\n" +
+           "COLON_TOKEN (':')\n" +
+           "EQUALS_TOKEN ('=')\n" +
+           "COMMA_TOKEN (',')\n" +
+           "QUOTE_TOKEN ('\"')");
+  }
+
+  @Test
+  public void testErrorEndsAtNewline() {
+    doTest("Name \n value",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "BAD_CHARACTER (' ')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('value')");
+  }
+
+  @Test
+  public void testNewlineBetweenSpecialChars() {
+    doTest("Name: ab;dir:\n =value\n",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('ab')\n" +
+           "SEMICOLON_TOKEN (';')\n" +
+           "HEADER_VALUE_PART_TOKEN ('dir')\n" +
+           "COLON_TOKEN (':')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "EQUALS_TOKEN ('=')\n" +
+           "HEADER_VALUE_PART_TOKEN ('value')\n" +
+           "NEWLINE_TOKEN ('\n')");
+  }
+
+  @Test
+  public void testBadHeaderStart() {
+    doTest("Name: ab;dir:\n" +
+           "=value;a:=b\n",
+
+           "HEADER_NAME_TOKEN ('Name')\n" +
+           "COLON_TOKEN (':')\n" +
+           "SIGNIFICANT_SPACE_TOKEN (' ')\n" +
+           "HEADER_VALUE_PART_TOKEN ('ab')\n" +
+           "SEMICOLON_TOKEN (';')\n" +
+           "HEADER_VALUE_PART_TOKEN ('dir')\n" +
+           "COLON_TOKEN (':')\n" +
+           "NEWLINE_TOKEN ('\n')\n" +
+           "BAD_CHARACTER ('=')\n" +
+           "BAD_CHARACTER ('v')\n" +
+           "BAD_CHARACTER ('a')\n" +
+           "BAD_CHARACTER ('l')\n" +
+           "BAD_CHARACTER ('u')\n" +
+           "BAD_CHARACTER ('e')\n" +
+           "BAD_CHARACTER (';')\n" +
+           "BAD_CHARACTER ('a')\n" +
+           "BAD_CHARACTER (':')\n" +
+           "BAD_CHARACTER ('=')\n" +
+           "BAD_CHARACTER ('b')\n" +
+           "NEWLINE_TOKEN ('\n')");
+  }
+
+  private static void doTest(String text, String expected) {
+    ManifestLexer lexer = new ManifestLexer();
+    lexer.start(text);
+
+    StringBuilder actual = new StringBuilder();
+    IElementType token;
+    while ((token = lexer.getTokenType()) != null) {
+      actual.append(token).append(" ('").append(lexer.getTokenText()).append("')\n");
+      lexer.advance();
+    }
+
+    assertEquals(expected.trim(), actual.toString().trim());
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestParserTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestParserTest.java
new file mode 100644
index 0000000..411fbc8
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestParserTest.java
@@ -0,0 +1,354 @@
+/*
+ * 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.lang.manifest;
+
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.DebugUtil;
+import com.intellij.testFramework.LightIdeaTestCase;
+import com.intellij.testFramework.LightPlatformTestCase;
+import junit.framework.Assert;
+
+/**
+ * @author Robert F. Beeger (robert@beeger.net)
+ */
+public class ManifestParserTest extends LightIdeaTestCase {
+  public void testEmpty() {
+    doTest("",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  <empty list>\n");
+  }
+
+  public void testSpaces() {
+    doTest("  ",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    PsiErrorElement:Header expected\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      ManifestToken:HEADER_VALUE_PART_TOKEN(' ')\n");
+  }
+
+  public void testRandomText() {
+    doTest("some text\nmore text",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:some\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('some')\n" +
+           "      PsiErrorElement:':' expected\n" +
+           "        PsiElement(BAD_CHARACTER)(' ')\n" +
+           "        PsiElement(BAD_CHARACTER)('t')\n" +
+           "        PsiElement(BAD_CHARACTER)('e')\n" +
+           "        PsiElement(BAD_CHARACTER)('x')\n" +
+           "        PsiElement(BAD_CHARACTER)('t')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    Header:more\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('more')\n" +
+           "      PsiErrorElement:':' expected\n" +
+           "        PsiElement(BAD_CHARACTER)(' ')\n" +
+           "        PsiElement(BAD_CHARACTER)('t')\n" +
+           "        PsiElement(BAD_CHARACTER)('e')\n" +
+           "        PsiElement(BAD_CHARACTER)('x')\n" +
+           "        PsiElement(BAD_CHARACTER)('t')\n");
+  }
+
+  public void testNoHeader() {
+    doTest(" some text",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    PsiErrorElement:Header expected\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      ManifestToken:HEADER_VALUE_PART_TOKEN('some text')\n");
+  }
+
+  public void testBadHeaderStart() {
+    doTest("Name: ab;dir:\n" +
+           "=value;a:=b\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Name\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Name')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('ab')\n" +
+           "        ManifestToken:SEMICOLON_TOKEN(';')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('dir')\n" +
+           "        ManifestToken:COLON_TOKEN(':')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    PsiErrorElement:Header expected\n" +
+           "      PsiElement(BAD_CHARACTER)('=')\n" +
+           "      PsiElement(BAD_CHARACTER)('v')\n" +
+           "      PsiElement(BAD_CHARACTER)('a')\n" +
+           "      PsiElement(BAD_CHARACTER)('l')\n" +
+           "      PsiElement(BAD_CHARACTER)('u')\n" +
+           "      PsiElement(BAD_CHARACTER)('e')\n" +
+           "      PsiElement(BAD_CHARACTER)(';')\n" +
+           "      PsiElement(BAD_CHARACTER)('a')\n" +
+           "      PsiElement(BAD_CHARACTER)(':')\n" +
+           "      PsiElement(BAD_CHARACTER)('=')\n" +
+           "      PsiElement(BAD_CHARACTER)('b')\n" +
+           "      ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testNewLines() {
+    doTest("\n\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n" +
+           "  Section\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n");
+  }
+
+  public void testSimple() {
+    doTest("Manifest-Version: 1.0\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('1.0')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testExtraSpaceInHeaderAssignment() {
+    doTest("Manifest-Version : 1.0\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      PsiErrorElement:Unexpected token\n" +
+           "        PsiElement(BAD_CHARACTER)(' ')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('1.0')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testMissingSpaceInHeaderAssignment() {
+    doTest("Specification-Vendor:name\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Specification-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Specification-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      PsiErrorElement:Whitespace expected\n" +
+           "        <empty list>\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('name')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleWithNewLines() {
+    doTest("Manifest-Version: 1.0\n\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('1.0')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleIncomplete() {
+    doTest("Manifest-Version:",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      PsiErrorElement:Whitespace expected\n" +
+           "        <empty list>\n" +
+           "      HeaderValuePart\n" +
+           "        <empty list>\n");
+  }
+
+  public void testSimpleIncompleteWithNewLine() {
+    doTest("Manifest-Version:\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      PsiErrorElement:Whitespace expected\n" +
+           "        <empty list>\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleIncompleteWithNewLines() {
+    doTest("Manifest-Version:\n\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      PsiErrorElement:Whitespace expected\n" +
+           "        <empty list>\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleWithContinuation() {
+    doTest("Specification-Vendor: Acme\n" +
+           " Company\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Specification-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Specification-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('Acme')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "        ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('Company')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleWithQuotedValue() {
+    doTest("Implementation-Vendor: \"Apache Software Foundation\"\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Implementation-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Implementation-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:QUOTE_TOKEN('\"')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('Apache Software Foundation')\n" +
+           "        ManifestToken:QUOTE_TOKEN('\"')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleHeaderValueStartsWithColon() {
+    doTest("Implementation-Vendor: :value\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Implementation-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Implementation-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:COLON_TOKEN(':')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('value')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleHeaderValueStartsWithEquals() {
+    doTest("Implementation-Vendor: =value\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Implementation-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Implementation-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:EQUALS_TOKEN('=')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('value')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testSimpleHeaderValueStartsWithSemicolon() {
+    doTest("Implementation-Vendor: ;value\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Implementation-Vendor\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Implementation-Vendor')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:SEMICOLON_TOKEN(';')\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('value')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testTwoHeaders() {
+    doTest("Manifest-Version: 1.0\n" +
+           "Ant-Version: Apache Ant 1.6.5\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('1.0')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    Header:Ant-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Ant-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('Apache Ant 1.6.5')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n");
+  }
+
+  public void testTwoSections() {
+    doTest("Manifest-Version: 1.0\n" +
+           "\n" +
+           "Ant-Version: Apache Ant 1.6.5\n\n",
+
+           "ManifestFile:MANIFEST.MF\n" +
+           "  Section\n" +
+           "    Header:Manifest-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Manifest-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('1.0')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n" +
+           "  Section\n" +
+           "    Header:Ant-Version\n" +
+           "      ManifestToken:HEADER_NAME_TOKEN('Ant-Version')\n" +
+           "      ManifestToken:COLON_TOKEN(':')\n" +
+           "      ManifestToken:SIGNIFICANT_SPACE_TOKEN(' ')\n" +
+           "      HeaderValuePart\n" +
+           "        ManifestToken:HEADER_VALUE_PART_TOKEN('Apache Ant 1.6.5')\n" +
+           "        ManifestToken:NEWLINE_TOKEN('\\n')\n" +
+           "    ManifestToken:SECTION_END_TOKEN('\\n')\n");
+  }
+
+  private static void doTest(String source, String expected) {
+    PsiFile file = LightPlatformTestCase.createLightFile("MANIFEST.MF", source);
+    Assert.assertEquals(expected, DebugUtil.psiToString(file, true));
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java
new file mode 100644
index 0000000..64d8fc2
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.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 org.jetbrains.lang.manifest;
+
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.LightIdeaTestCase;
+import com.intellij.testFramework.LightPlatformTestCase;
+import junit.framework.Assert;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.lang.manifest.psi.Header;
+import org.jetbrains.lang.manifest.psi.HeaderValue;
+import org.jetbrains.lang.manifest.psi.ManifestFile;
+
+public class ManifestPsiTest extends LightIdeaTestCase {
+  public void testFile() {
+    ManifestFile file = createFile("");
+    Assert.assertEquals(0, file.getSections().size());
+    Assert.assertNull(file.getMainSection());
+    Assert.assertEquals(0, file.getHeaders().size());
+
+    file = createFile("Header: value\n\nAnother-Header: another value\n");
+    Assert.assertEquals(2, file.getSections().size());
+    Assert.assertNotNull(file.getMainSection());
+    Assert.assertEquals(1, file.getHeaders().size());
+    Assert.assertNotNull(file.getHeader("Header"));
+    Assert.assertNull(file.getHeader("Another-Header"));
+  }
+
+  public void testHeader() {
+    ManifestFile file = createFile("Header: value\nEmpty-Header:\nBad-Header\n");
+    assertHeaderValue(file, "Header", "value");
+    assertHeaderValue(file, "Empty-Header", "");
+    assertHeaderValue(file, "Bad-Header", null);
+  }
+
+  private static ManifestFile createFile(String text) {
+    PsiFile file = LightPlatformTestCase.createLightFile("MANIFEST.MF", text);
+    assert file instanceof ManifestFile : file;
+    return (ManifestFile)file;
+  }
+
+  private static void assertHeaderValue(ManifestFile file, String name, @Nullable String expected) {
+    Header header = file.getHeader(name);
+    Assert.assertNotNull(header);
+
+    HeaderValue value = header.getHeaderValue();
+    if (expected == null) {
+      Assert.assertNull(value);
+    }
+    else {
+      Assert.assertNotNull(value);
+      Assert.assertEquals(expected, value.getUnwrappedText());
+    }
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/MissingFinalNewlineInspectionTest.java b/java/manifest/test/org/jetbrains/lang/manifest/MissingFinalNewlineInspectionTest.java
new file mode 100644
index 0000000..a55b938
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/MissingFinalNewlineInspectionTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.lang.manifest;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import junit.framework.Assert;
+import org.jetbrains.lang.manifest.highlighting.MissingFinalNewlineInspection;
+
+public class MissingFinalNewlineInspectionTest extends LightCodeInsightFixtureTestCase {
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    myFixture.enableInspections(new MissingFinalNewlineInspection());
+  }
+
+  public void testEmptyFile() {
+    myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "");
+    Assert.assertEquals(0, myFixture.getAvailableIntentions().size());
+  }
+
+  public void testNoProblem() {
+    myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Manifest-Version: 1.0\n");
+    Assert.assertEquals(0, myFixture.getAvailableIntentions().size());
+  }
+
+  public void testFix() {
+    myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Manifest-Version: 1.0");
+    IntentionAction intention = myFixture.findSingleIntention(ManifestBundle.message("inspection.newline.fix"));
+    myFixture.launchAction(intention);
+    myFixture.checkResult("Manifest-Version: 1.0\n");
+  }
+}
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java b/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java
new file mode 100644
index 0000000..844ed05
--- /dev/null
+++ b/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.lang.manifest;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import junit.framework.Assert;
+import org.jetbrains.lang.manifest.highlighting.MisspelledHeaderInspection;
+
+import java.util.List;
+
+public class MisspelledHeaderInspectionTest extends LightCodeInsightFixtureTestCase {
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    myFixture.enableInspections(new MisspelledHeaderInspection());
+  }
+
+  public void testNoProblem() {
+    myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Manifest-Version: 1.0\n");
+    Assert.assertEquals(0, myFixture.getAvailableIntentions().size());
+  }
+
+  public void testFix() {
+    myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "ManifestVersion: 1.0\n");
+    List<IntentionAction> intentions = myFixture.filterAvailableIntentions("Change to");
+    Assert.assertTrue(intentions.size() > 0);
+    myFixture.launchAction(intentions.get(0));
+    myFixture.checkResult("Manifest-Version: 1.0\n");
+  }
+}
diff --git a/java/openapi/src/com/intellij/codeInsight/generation/actions/BaseGenerateAction.java b/java/openapi/src/com/intellij/codeInsight/generation/actions/BaseGenerateAction.java
index e8afbc6..7426653 100644
--- a/java/openapi/src/com/intellij/codeInsight/generation/actions/BaseGenerateAction.java
+++ b/java/openapi/src/com/intellij/codeInsight/generation/actions/BaseGenerateAction.java
@@ -18,6 +18,8 @@
 
 import com.intellij.codeInsight.CodeInsightActionHandler;
 import com.intellij.codeInsight.actions.CodeInsightAction;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
@@ -25,13 +27,18 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class BaseGenerateAction extends CodeInsightAction {
+public class BaseGenerateAction extends CodeInsightAction implements GenerateActionPopupTemplateInjector {
   private final CodeInsightActionHandler myHandler;
 
   public BaseGenerateAction(CodeInsightActionHandler handler) {
     myHandler = handler;
   }
 
+  @Nullable
+  public AnAction createEditTemplateAction(DataContext dataContext) {
+    return null;
+  }
+
   @NotNull
   @Override
   protected final CodeInsightActionHandler getHandler() {
diff --git a/java/openapi/src/com/intellij/codeInsight/quickfix/ChangeVariableTypeQuickFixProvider.java b/java/openapi/src/com/intellij/codeInsight/quickfix/ChangeVariableTypeQuickFixProvider.java
index 5f0113e..f420e78 100644
--- a/java/openapi/src/com/intellij/codeInsight/quickfix/ChangeVariableTypeQuickFixProvider.java
+++ b/java/openapi/src/com/intellij/codeInsight/quickfix/ChangeVariableTypeQuickFixProvider.java
@@ -24,9 +24,11 @@
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.psi.PsiType;
 import com.intellij.psi.PsiVariable;
+import org.jetbrains.annotations.NotNull;
 
 public interface ChangeVariableTypeQuickFixProvider {
   ExtensionPointName<ChangeVariableTypeQuickFixProvider> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.changeVariableTypeQuickFixProvider");
 
-  IntentionAction[] getFixes(PsiVariable variable, PsiType toReturn);
+  @NotNull
+  IntentionAction[] getFixes(@NotNull PsiVariable variable, @NotNull PsiType toReturn);
 }
\ No newline at end of file
diff --git a/java/remote-servers/remote-servers-java.iml b/java/remote-servers/remote-servers-java.iml
new file mode 100644
index 0000000..994a29f
--- /dev/null
+++ b/java/remote-servers/remote-servers-java.iml
@@ -0,0 +1,20 @@
+<?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="remote-servers-api" />
+    <orderEntry type="module" module-name="debugger-impl" />
+    <orderEntry type="module" module-name="core-api" />
+    <orderEntry type="module" module-name="lang-api" />
+    <orderEntry type="module" module-name="xdebugger-api" />
+    <orderEntry type="module" module-name="lang-impl" />
+    <orderEntry type="module" module-name="execution-openapi" />
+    <orderEntry type="module" module-name="remote-servers-impl" scope="RUNTIME" />
+  </component>
+</module>
+
diff --git a/java/remote-servers/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java b/java/remote-servers/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java
new file mode 100644
index 0000000..3ec24ef
--- /dev/null
+++ b/java/remote-servers/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java
@@ -0,0 +1,143 @@
+package com.intellij.remoteServer.impl.runtime.deployment.debug;
+
+import com.intellij.debugger.DebugEnvironment;
+import com.intellij.debugger.DebugUIEnvironment;
+import com.intellij.debugger.engine.RemoteDebugProcessHandler;
+import com.intellij.debugger.ui.DebuggerPanelsManager;
+import com.intellij.diagnostic.logging.LogFilesManager;
+import com.intellij.execution.*;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.impl.ConsoleViewImpl;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.execution.ui.actions.CloseAction;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.runtime.deployment.debug.JavaDebugConnectionData;
+import com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author nik
+ */
+public class JavaDebuggerLauncherImpl extends JavaDebuggerLauncher {
+  private static final Logger LOG = Logger.getInstance(JavaDebuggerLauncherImpl.class);
+
+  @Override
+  public void startDebugSession(@NotNull JavaDebugConnectionData info, @NotNull ExecutionEnvironment executionEnvironment, RemoteServer<?> server)
+    throws ExecutionException {
+    final Project project = executionEnvironment.getProject();
+    Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
+    final DebuggerPanelsManager manager = DebuggerPanelsManager.getInstance(project);
+    final RemoteConnection remoteConnection = new RemoteConnection(true, info.getHost(), String.valueOf(info.getPort()), false);
+    DebugEnvironment debugEnvironment = new RemoteServerDebugEnvironment(project, remoteConnection, executionEnvironment.getRunProfile());
+    DebugUIEnvironment debugUIEnvironment = new RemoteServerDebugUIEnvironment(debugEnvironment, executionEnvironment);
+    RunContentDescriptor debugContentDescriptor = manager.attachVirtualMachine(debugUIEnvironment);
+    LOG.assertTrue(debugContentDescriptor != null);
+    ProcessHandler processHandler = debugContentDescriptor.getProcessHandler();
+    LOG.assertTrue(processHandler != null);
+    processHandler.startNotify();
+    ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, debugContentDescriptor,
+                                                                             executionEnvironment.getContentToReuse());
+  }
+
+  private static class RemoteServerDebugUIEnvironment implements DebugUIEnvironment {
+    private final DebugEnvironment myEnvironment;
+    private final ExecutionEnvironment myExecutionEnvironment;
+
+    public RemoteServerDebugUIEnvironment(DebugEnvironment environment, ExecutionEnvironment executionEnvironment) {
+      myEnvironment = environment;
+      myExecutionEnvironment = executionEnvironment;
+    }
+
+    @Override
+    public DebugEnvironment getEnvironment() {
+      return myEnvironment;
+    }
+
+    @Nullable
+    @Override
+    public RunContentDescriptor getReuseContent() {
+      return myExecutionEnvironment.getContentToReuse();
+    }
+
+    @Nullable
+    @Override
+    public Icon getIcon() {
+      return myExecutionEnvironment.getRunProfile().getIcon();
+    }
+
+    @Override
+    public void initLogs(RunContentDescriptor content, LogFilesManager logFilesManager) {
+    }
+
+    @Override
+    public void initActions(RunContentDescriptor content, DefaultActionGroup actionGroup) {
+      actionGroup.add(new CloseAction(myExecutionEnvironment.getExecutor(), content, myExecutionEnvironment.getProject()));
+    }
+
+    @Nullable
+    @Override
+    public RunProfile getRunProfile() {
+      return myExecutionEnvironment.getRunProfile();
+    }
+  }
+
+  private static class RemoteServerDebugEnvironment implements DebugEnvironment {
+    private final Project myProject;
+    private final GlobalSearchScope mySearchScope;
+    private final RemoteConnection myRemoteConnection;
+    private final RunProfile myRunProfile;
+
+    public RemoteServerDebugEnvironment(Project project, RemoteConnection remoteConnection, RunProfile runProfile) {
+      myProject = project;
+      mySearchScope = RunContentBuilder.createSearchScope(project, runProfile);
+      myRemoteConnection = remoteConnection;
+      myRunProfile = runProfile;
+    }
+
+    @Nullable
+    @Override
+    public ExecutionResult createExecutionResult() throws ExecutionException {
+      ConsoleViewImpl consoleView = new ConsoleViewImpl(myProject, false);
+      RemoteDebugProcessHandler process = new RemoteDebugProcessHandler(myProject);
+      consoleView.attachToProcess(process);
+      return new DefaultExecutionResult(consoleView, process);
+    }
+
+    @Override
+    public GlobalSearchScope getSearchScope() {
+      return mySearchScope;
+    }
+
+    @Override
+    public boolean isRemote() {
+      return true;
+    }
+
+    @Override
+    public RemoteConnection getRemoteConnection() {
+      return myRemoteConnection;
+    }
+
+    @Override
+    public boolean isPollConnection() {
+      return true;
+    }
+
+    @Override
+    public String getSessionName() {
+      return myRunProfile.getName();
+    }
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
index 1134d30..d6b428d 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
@@ -16,12 +16,12 @@
 package org.jetbrains.jps.client;
 
 import com.google.protobuf.MessageLite;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelStateEvent;
-import org.jboss.netty.channel.MessageEvent;
-import org.jboss.netty.channel.SimpleChannelHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.api.RequestFuture;
+import org.jetbrains.jps.javac.JavacRemoteProto;
 
 import java.util.ArrayList;
 import java.util.UUID;
@@ -32,7 +32,8 @@
 * @author Eugene Zhuravlev
 *         Date: 1/22/12
 */
-final class ProtobufClientMessageHandler<T extends ProtobufResponseHandler> extends SimpleChannelHandler {
+@ChannelHandler.Sharable
+final class ProtobufClientMessageHandler<T extends ProtobufResponseHandler> extends SimpleChannelInboundHandler<MessageLite> {
   private final ConcurrentHashMap<UUID, RequestFuture<T>> myHandlers = new ConcurrentHashMap<UUID, RequestFuture<T>>();
   @NotNull
   private final UUIDGetter myUuidGetter;
@@ -45,8 +46,9 @@
     myAsyncExec = asyncExec;
   }
 
-  public final void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-    final UUID messageUUID = myUuidGetter.getSessionUUID(e);
+  @Override
+  public final void channelRead0(ChannelHandlerContext context, MessageLite message) throws Exception {
+    final UUID messageUUID = myUuidGetter.getSessionUUID((JavacRemoteProto.Message)message);
     final RequestFuture<T> future = myHandlers.get(messageUUID);
     final T handler = future != null ? future.getMessageHandler() : null;
     if (handler == null) {
@@ -55,7 +57,7 @@
     else {
       boolean terminateSession = false;
       try {
-        terminateSession = handler.handleMessage((MessageLite)e.getMessage());
+        terminateSession = handler.handleMessage(message);
       }
       catch (Exception ex) {
         terminateSession = true;
@@ -78,8 +80,9 @@
           try {
             handler.sessionTerminated();
           }
-          catch (Throwable ignored) {
-            ignored.printStackTrace();
+          catch (Throwable e) {
+            //noinspection CallToPrintStackTrace
+            e.printStackTrace();
           }
         }
       }
@@ -89,30 +92,26 @@
     }
   }
 
-  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-    try {
-      super.channelClosed(ctx, e);
-    }
-    finally {
-      for (UUID uuid : new ArrayList<UUID>(myHandlers.keySet())) {
-        terminateSession(uuid);
-      }
-    }
-  }
-
   @Override
-  public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+  public void channelInactive(ChannelHandlerContext context) throws Exception {
     try {
-      super.channelDisconnected(ctx, e);
+      super.channelInactive(context);
     }
     finally {
-      // make sure the client is in disconnected state
-      myAsyncExec.execute(new Runnable() {
-        @Override
-        public void run() {
-          myClient.disconnect();
+      try {
+        for (UUID uuid : new ArrayList<UUID>(myHandlers.keySet())) {
+          terminateSession(uuid);
         }
-      });
+      }
+      finally {
+        // make sure the client is in disconnected state
+        myAsyncExec.execute(new Runnable() {
+          @Override
+          public void run() {
+            myClient.disconnect();
+          }
+        });
+      }
     }
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java
index 06f4175..19246ee 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java
@@ -17,17 +17,17 @@
 
 import com.google.protobuf.MessageLite;
 import com.intellij.openapi.diagnostic.Logger;
-import org.jboss.netty.bootstrap.ClientBootstrap;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
-import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.api.RequestFuture;
 
-import java.net.InetSocketAddress;
 import java.util.UUID;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicReference;
@@ -39,28 +39,27 @@
 public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
   private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.client.SimpleProtobufClient");
 
-  private static enum State {
+  private enum State {
     DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING
   }
 
   private final AtomicReference<State> myState = new AtomicReference<State>(State.DISCONNECTED);
-  protected final ChannelPipelineFactory myPipelineFactory;
-  protected final ChannelFactory myChannelFactory;
+  protected final ChannelInitializer myChannelInitializer;
+  protected final EventLoopGroup myEventLoopGroup;
   protected volatile ChannelFuture myConnectFuture;
   private final ProtobufClientMessageHandler<T> myMessageHandler;
 
   public SimpleProtobufClient(final MessageLite msgDefaultInstance, final Executor asyncExec, final UUIDGetter uuidGetter) {
     myMessageHandler = new ProtobufClientMessageHandler<T>(uuidGetter, this, asyncExec);
-    myChannelFactory = new NioClientSocketChannelFactory(asyncExec, asyncExec, 1);
-    myPipelineFactory = new ChannelPipelineFactory() {
-      public ChannelPipeline getPipeline() throws Exception {
-        return Channels.pipeline(
-          new ProtobufVarint32FrameDecoder(),
-          new ProtobufDecoder(msgDefaultInstance),
-          new ProtobufVarint32LengthFieldPrepender(),
-          new ProtobufEncoder(),
-          myMessageHandler
-        );
+    myEventLoopGroup = new NioEventLoopGroup(1, asyncExec);
+    myChannelInitializer = new ChannelInitializer() {
+      @Override
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(new ProtobufVarint32FrameDecoder(),
+                                   new ProtobufDecoder(msgDefaultInstance),
+                                   new ProtobufVarint32LengthFieldPrepender(),
+                                   new ProtobufEncoder(),
+                                   myMessageHandler);
       }
     };
   }
@@ -76,15 +75,10 @@
       boolean success = false;
 
       try {
-        final ClientBootstrap bootstrap = new ClientBootstrap(myChannelFactory);
-        bootstrap.setPipelineFactory(myPipelineFactory);
-        bootstrap.setOption("tcpNoDelay", true);
-        bootstrap.setOption("keepAlive", true);
-        final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
-        future.awaitUninterruptibly();
-
+        final Bootstrap bootstrap = new Bootstrap().group(myEventLoopGroup).channel(NioSocketChannel.class).handler(myChannelInitializer);
+        bootstrap.option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true);
+        final ChannelFuture future = bootstrap.connect(host, port).syncUninterruptibly();
         success = future.isSuccess();
-
         if (success) {
           myConnectFuture = future;
           try {
@@ -94,13 +88,6 @@
             LOG.error(e);
           }
         }
-        else {
-          final Throwable reason = future.getCause();
-          if (reason != null) {
-            throw reason;
-          }
-        }
-
         return success;
       }
       finally {
@@ -129,7 +116,7 @@
           catch (Throwable e) {
             LOG.error(e);
           }
-          final ChannelFuture closeFuture = future.getChannel().close();
+          final ChannelFuture closeFuture = future.channel().close();
           closeFuture.awaitUninterruptibly();
         }
       }
@@ -154,9 +141,10 @@
     final RequestFuture<T> requestFuture = new RequestFuture<T>(responseHandler, messageId, cancelAction);
     myMessageHandler.registerFuture(messageId, requestFuture);
     final ChannelFuture connectFuture = myConnectFuture;
-    final Channel channel = connectFuture != null? connectFuture.getChannel() : null;
-    if (channel != null && channel.isConnected()) {
-      Channels.write(channel, message).addListener(new ChannelFutureListener() {
+    final Channel channel = connectFuture != null? connectFuture.channel() : null;
+    if (channel != null && channel.isActive()) {
+      channel.writeAndFlush(message).addListener(new ChannelFutureListener() {
+        @Override
         public void operationComplete(ChannelFuture future) throws Exception {
           if (!future.isSuccess()) {
             notifyTerminated(messageId, requestFuture, responseHandler);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java b/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java
index 675a629..cba6db4 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/UUIDGetter.java
@@ -15,8 +15,8 @@
  */
 package org.jetbrains.jps.client;
 
-import org.jboss.netty.channel.MessageEvent;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.javac.JavacRemoteProto;
 
 import java.util.UUID;
 
@@ -25,5 +25,5 @@
 *         Date: 1/22/12
 */
 public interface UUIDGetter {
-  @NotNull UUID getSessionUUID(@NotNull MessageEvent e);
+  @NotNull UUID getSessionUUID(@NotNull JavacRemoteProto.Message message);
 }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
index 0bc2107..0e47e0c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
@@ -18,16 +18,17 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
 import org.apache.log4j.Level;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.xml.DOMConfigurator;
-import org.jboss.netty.bootstrap.ClientBootstrap;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
-import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -45,6 +46,7 @@
  * @author Eugene Zhuravlev
  *         Date: 4/16/12
  */
+@SuppressWarnings("UseOfSystemOutOrSystemErr")
 public class BuildMain {
   private static final String LOG_CONFIG_FILE_NAME = "build-log.xml";
   private static final String LOG_FILE_NAME = "build.log";
@@ -56,42 +58,37 @@
     LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildMain");
   }
 
-  private static NioClientSocketChannelFactory ourChannelFactory;
+  private static NioEventLoopGroup ourEventLoopGroup;
 
   public static void main(String[] args){
     System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path"));
     final String host = args[0];
     final int port = Integer.parseInt(args[1]);
     final UUID sessionId = UUID.fromString(args[2]);
+    @SuppressWarnings("ConstantConditions")
     final File systemDir = new File(FileUtil.toCanonicalPath(args[3]));
     Utils.setSystemRoot(systemDir);
 
-    ourChannelFactory = new NioClientSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
-    final ClientBootstrap bootstrap = new ClientBootstrap(ourChannelFactory);
-    bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
-      public ChannelPipeline getPipeline() throws Exception {
-        return Channels.pipeline(
-          new ProtobufVarint32FrameDecoder(),
-          new ProtobufDecoder(CmdlineRemoteProto.Message.getDefaultInstance()),
-          new ProtobufVarint32LengthFieldPrepender(),
-          new ProtobufEncoder(),
-          new MyMessageHandler(sessionId)
-        );
+    ourEventLoopGroup = new NioEventLoopGroup(1, SharedThreadPool.getInstance());
+    final Bootstrap bootstrap = new Bootstrap().group(ourEventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer() {
+      @Override
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(new ProtobufVarint32FrameDecoder(),
+                                   new ProtobufDecoder(CmdlineRemoteProto.Message.getDefaultInstance()),
+                                   new ProtobufVarint32LengthFieldPrepender(),
+                                   new ProtobufEncoder(),
+                                   new MyMessageHandler(sessionId));
       }
-    });
-    bootstrap.setOption("tcpNoDelay", true);
-    bootstrap.setOption("keepAlive", true);
+    }).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true);
 
-    final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
-    future.awaitUninterruptibly();
-
+    final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)).awaitUninterruptibly();
     final boolean success = future.isSuccess();
-
     if (success) {
-      Channels.write(future.getChannel(), CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest()));
+      future.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest()));
     }
     else {
-      final Throwable reason = future.getCause();
+      @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      final Throwable reason = future.cause();
       System.err.println("Error connecting to " + host + ":" + port + "; reason: " + (reason != null? reason.getMessage() : "unknown"));
       if (reason != null) {
         reason.printStackTrace(System.err);
@@ -101,7 +98,7 @@
     }
   }
 
-  private static class MyMessageHandler extends SimpleChannelHandler {
+  private static class MyMessageHandler extends SimpleChannelInboundHandler<CmdlineRemoteProto.Message> {
     private final UUID mySessionId;
     private volatile BuildSession mySession;
 
@@ -110,10 +107,9 @@
     }
 
     @Override
-    public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-      CmdlineRemoteProto.Message message = (CmdlineRemoteProto.Message)e.getMessage();
+    public void channelRead0(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
       final CmdlineRemoteProto.Message.Type type = message.getType();
-      final Channel channel = ctx.getChannel();
+      final Channel channel = context.channel();
 
       if (type == CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE) {
         final CmdlineRemoteProto.Message.ControllerMessage controllerMessage = message.getControllerMessage();
@@ -125,7 +121,9 @@
               final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta);
               mySession = session;
               SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
+                @Override
                 public void run() {
+                  //noinspection finally
                   try {
                     session.run();
                   }
@@ -172,19 +170,22 @@
         }
       }
 
-      Channels.write(channel, CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure("Unsupported message type: " + type.name(), null)));
+      channel.writeAndFlush(
+        CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure("Unsupported message type: " + type.name(), null)));
     }
 
     @Override
-    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+    public void channelInactive(ChannelHandlerContext context) throws Exception {
       try {
-        super.channelClosed(ctx, e);
+        super.channelInactive(context);
       }
       finally {
         new Thread("Shutdown thread") {
+          @Override
           public void run() {
+            //noinspection finally
             try {
-              ourChannelFactory.releaseExternalResources();
+              ourEventLoopGroup.shutdownGracefully();
             }
             finally {
               System.exit(0);
@@ -193,16 +194,6 @@
         }.start();
       }
     }
-
-    @Override
-    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-      try {
-        super.channelDisconnected(ctx, e);
-      }
-      finally {
-        ctx.getChannel().close();
-      }
-    }
   }
 
   private static void initLoggers() {
@@ -217,6 +208,7 @@
     }
     catch (IOException e) {
       System.err.println("Failed to configure logging: ");
+      //noinspection UseOfSystemOutOrSystemErr
       e.printStackTrace(System.err);
     }
 
@@ -278,6 +270,7 @@
   private static void ensureLogConfigExists(final File logConfig) throws IOException {
     if (!logConfig.exists()) {
       FileUtil.createIfDoesntExist(logConfig);
+      @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
       final InputStream in = BuildMain.class.getResourceAsStream("/" + DEFAULT_LOGGER_CONFIG);
       if (in != null) {
         try {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
index b841e32..f6d27c8 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
@@ -24,16 +24,15 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.concurrency.SequentialTaskExecutor;
 import com.intellij.util.io.DataOutputStream;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.Channels;
+import io.netty.channel.Channel;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.TimingLog;
 import org.jetbrains.jps.api.*;
 import org.jetbrains.jps.builders.*;
 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
 import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
 import org.jetbrains.jps.incremental.MessageHandler;
 import org.jetbrains.jps.incremental.TargetTypeRegistry;
-import org.jetbrains.jps.TimingLog;
 import org.jetbrains.jps.incremental.Utils;
 import org.jetbrains.jps.incremental.fs.BuildFSState;
 import org.jetbrains.jps.incremental.fs.FSState;
@@ -99,6 +98,7 @@
     myBuildRunner = new BuildRunner(loader, filePaths, builderParams);
   }
 
+  @Override
   public void run() {
     Throwable error = null;
     final Ref<Boolean> hasErrors = new Ref<Boolean>(false);
@@ -111,6 +111,7 @@
       }
 
       runBuild(new MessageHandler() {
+        @Override
         public void processMessage(BuildMessage buildMessage) {
           final CmdlineRemoteProto.Message.BuilderMessage response;
           if (buildMessage instanceof FileGeneratedEvent) {
@@ -151,7 +152,7 @@
             response = null;
           }
           if (response != null) {
-            Channels.write(myChannel, CmdlineProtoUtil.toMessage(mySessionId, response));
+            myChannel.writeAndFlush(CmdlineProtoUtil.toMessage(mySessionId, response));
           }
         }
       }, this);
@@ -441,9 +442,10 @@
   private static void saveOnDisk(BufferExposingByteArrayOutputStream bytes, final File file) throws IOException {
     FileOutputStream fos = null;
     try {
+      //noinspection IOResourceOpenedButNotSafelyClosed
       fos = new FileOutputStream(file);
     }
-    catch (FileNotFoundException e) {
+    catch (FileNotFoundException ignored) {
       FileUtil.createIfDoesntExist(file);
     }
 
@@ -541,7 +543,7 @@
     }
     finally {
       try {
-        Channels.write(myChannel, lastMessage).await();
+        myChannel.writeAndFlush(lastMessage).await();
       }
       catch (InterruptedException e) {
         LOG.info(e);
@@ -607,11 +609,8 @@
       if (prev != null) {
         prev.setDone();
       }
-      Channels.write(myChannel,
-        CmdlineProtoUtil.toMessage(
-          mySessionId, CmdlineRemoteProto.Message.BuilderMessage.newBuilder().setType(CmdlineRemoteProto.Message.BuilderMessage.Type.CONSTANT_SEARCH_TASK).setConstantSearchTask(task.build()).build()
-        )
-      );
+      myChannel.writeAndFlush(CmdlineProtoUtil.toMessage(mySessionId, CmdlineRemoteProto.Message.BuilderMessage.newBuilder()
+        .setType(CmdlineRemoteProto.Message.BuilderMessage.Type.CONSTANT_SEARCH_TASK).setConstantSearchTask(task.build()).build()));
       return future;
     }
   }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
index 6b9fef1..ecf2ba0 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
@@ -26,8 +26,8 @@
 import com.intellij.util.SystemProperties;
 import com.intellij.util.containers.ContainerUtil;
 import com.jgoodies.forms.layout.CellConstraints;
+import io.netty.util.NetUtil;
 import net.n3.nanoxml.IXMLBuilder;
-import org.jboss.netty.util.Version;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.asm4.ClassVisitor;
 import org.jetbrains.asm4.ClassWriter;
@@ -57,7 +57,7 @@
         @SuppressWarnings("unchecked") Class<StandardJavaFileManager> c = (Class<StandardJavaFileManager>)Class.forName(CLASS_NAME);
         aClass = c;
       }
-      catch (Throwable e) {
+      catch (Throwable ignored) {
         aClass = null;
       }
       managerClass = aClass;
@@ -76,7 +76,7 @@
         @SuppressWarnings("unchecked") Class<StandardJavaFileManager> c = (Class<StandardJavaFileManager>)Class.forName(CLASS_NAME);
         aClass = c;
       }
-      catch (Throwable e) {
+      catch (Throwable ignored) {
         aClass = null;
       }
       managerClass = aClass;
@@ -96,7 +96,7 @@
 
     cp.addAll(PathManager.getUtilClassPath()); // util
     cp.add(getResourcePath(Message.class)); // protobuf
-    cp.add(getResourcePath(Version.class)); // netty
+    cp.add(getResourcePath(NetUtil.class)); // netty
     cp.add(getResourcePath(ClassWriter.class));  // asm
     cp.add(getResourcePath(ClassVisitor.class));  // asm-commons
     cp.add(getResourcePath(JpsModel.class));  // jps-model-api
@@ -141,7 +141,7 @@
     cp.add(getResourceFile(JpsModel.class));  // jps-model-api
     cp.add(getResourceFile(JpsModelImpl.class));  // jps-model-impl
     cp.add(getResourceFile(Message.class)); // protobuf
-    cp.add(getResourceFile(Version.class)); // netty
+    cp.add(getResourceFile(NetUtil.class)); // netty
 
     final Class<StandardJavaFileManager> optimizedFileManagerClass = getOptimizedFileManagerClass();
     if (optimizedFileManagerClass != null) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
index 76a6fe9..b901f95 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
@@ -15,74 +15,60 @@
  */
 package org.jetbrains.jps.javac;
 
-import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.channel.group.ChannelGroupFuture;
-import org.jboss.netty.channel.group.DefaultChannelGroup;
-import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
-import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
-import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.*;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.ChannelGroupFuture;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import io.netty.util.concurrent.ImmediateEventExecutor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.api.CanceledStatus;
 import org.jetbrains.jps.service.SharedThreadPool;
 
 import javax.tools.*;
 import java.io.File;
-import java.net.InetSocketAddress;
 import java.util.*;
 
 /**
  * @author Eugene Zhuravlev
  *         Date: 1/22/12
  */
+@SuppressWarnings("UseOfSystemOutOrSystemErr")
 public class JavacServer {
   public static final int DEFAULT_SERVER_PORT = 7878;
   public static final String SERVER_SUCCESS_START_MESSAGE = "Javac server started successfully. Listening on port: ";
   public static final String SERVER_ERROR_START_MESSAGE = "Error starting Javac Server: ";
   public static final String USE_ECLIPSE_COMPILER_PROPERTY = "use.eclipse.compiler";
 
-  private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("javac-server");
-  private final ChannelFactory myChannelFactory;
-  private final ChannelPipelineFactory myPipelineFactory;
-
-  public JavacServer() {
-    myChannelFactory = new NioServerSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
-    final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
-    final ChannelHandler compilationRequestsHandler = new CompilationRequestsHandler();
-    myPipelineFactory = new ChannelPipelineFactory() {
-      public ChannelPipeline getPipeline() throws Exception {
-        return Channels.pipeline(
-          channelRegistrar,
-          new ProtobufVarint32FrameDecoder(),
-          new ProtobufDecoder(JavacRemoteProto.Message.getDefaultInstance()),
-          new ProtobufVarint32LengthFieldPrepender(),
-          new ProtobufEncoder(),
-          compilationRequestsHandler
-        );
-      }
-    };
-  }
+  private ChannelRegistrar myChannelRegistrar;
 
   public void start(int listenPort) {
-    final ServerBootstrap bootstrap = new ServerBootstrap(myChannelFactory);
-    bootstrap.setPipelineFactory(myPipelineFactory);
-    bootstrap.setOption("child.tcpNoDelay", true);
-    bootstrap.setOption("child.keepAlive", true);
-    final Channel serverChannel = bootstrap.bind(new InetSocketAddress(listenPort));
-    myAllOpenChannels.add(serverChannel);
+    final ServerBootstrap bootstrap = new ServerBootstrap().group(new NioEventLoopGroup(1, SharedThreadPool.getInstance())).channel(NioServerSocketChannel.class);
+    bootstrap.childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_KEEPALIVE, true);
+    myChannelRegistrar = new ChannelRegistrar();
+    final ChannelHandler compilationRequestsHandler = new CompilationRequestsHandler();
+    bootstrap.childHandler(new ChannelInitializer() {
+      @Override
+      protected void initChannel(Channel channel) throws Exception {
+        channel.pipeline().addLast(myChannelRegistrar,
+                                   new ProtobufVarint32FrameDecoder(),
+                                   new ProtobufDecoder(JavacRemoteProto.Message.getDefaultInstance()),
+                                   new ProtobufVarint32LengthFieldPrepender(),
+                                   new ProtobufEncoder(),
+                                   compilationRequestsHandler);
+      }
+    });
+    myChannelRegistrar.add(bootstrap.bind(listenPort).syncUninterruptibly().channel());
   }
 
   public void stop() {
-    try {
-      final ChannelGroupFuture closeFuture = myAllOpenChannels.close();
-      closeFuture.awaitUninterruptibly();
-    }
-    finally {
-      myChannelFactory.releaseExternalResources();
-    }
+    myChannelRegistrar.close().awaitUninterruptibly();
   }
 
   public static void main(String[] args) {
@@ -101,6 +87,7 @@
       final JavacServer server = new JavacServer();
       server.start(port);
       Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") {
+        @Override
         public void run() {
           server.stop();
         }
@@ -116,8 +103,7 @@
     }
   }
 
-
-  public static JavacRemoteProto.Message compile(final ChannelHandlerContext ctx,
+  public static JavacRemoteProto.Message compile(final ChannelHandlerContext context,
                                                  final UUID sessionId,
                                                  List<String> options,
                                                  Collection<File> files,
@@ -129,28 +115,31 @@
     final DiagnosticOutputConsumer diagnostic = new DiagnosticOutputConsumer() {
       @Override
       public void javaFileLoaded(File file) {
-        Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createSourceFileLoadedResponse(file)));
+        context.channel().writeAndFlush(JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createSourceFileLoadedResponse(file)));
       }
 
+      @Override
       public void outputLineAvailable(String line) {
-        Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createStdOutputResponse(line)));
+        context.channel().writeAndFlush(JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createStdOutputResponse(line)));
       }
 
+      @Override
       public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
         final JavacRemoteProto.Message.Response response = JavacProtoUtil.createBuildMessageResponse(diagnostic);
-        Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response));
+        context.channel().writeAndFlush(JavacProtoUtil.toMessage(sessionId, response));
       }
 
       @Override
       public void registerImports(String className, Collection<String> imports, Collection<String> staticImports) {
         final JavacRemoteProto.Message.Response response = JavacProtoUtil.createClassDataResponse(className, imports, staticImports);
-        Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response));
+        context.channel().writeAndFlush(JavacProtoUtil.toMessage(sessionId, response));
       }
     };
 
     final OutputFileConsumer outputSink = new OutputFileConsumer() {
+      @Override
       public void save(@NotNull OutputFileObject fileObject) {
-        Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createOutputObjectResponse(fileObject)));
+        context.channel().writeAndFlush(JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createOutputObjectResponse(fileObject)));
       }
     };
 
@@ -159,6 +148,7 @@
       return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createBuildCompletedResponse(rc));
     }
     catch (Throwable e) {
+      //noinspection UseOfSystemOutOrSystemErr
       e.printStackTrace(System.err);
       return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createFailure(e.getMessage(), e));
     }
@@ -182,18 +172,18 @@
     return files;
   }
 
-  private class CompilationRequestsHandler extends SimpleChannelHandler {
-
-    public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-      final JavacRemoteProto.Message msg = (JavacRemoteProto.Message)e.getMessage();
-      final UUID sessionId = JavacProtoUtil.fromProtoUUID(msg.getSessionId());
-      final JavacRemoteProto.Message.Type messageType = msg.getMessageType();
+  @ChannelHandler.Sharable
+  private class CompilationRequestsHandler extends SimpleChannelInboundHandler<JavacRemoteProto.Message> {
+    @Override
+    public void channelRead0(final ChannelHandlerContext context, JavacRemoteProto.Message message) throws Exception {
+      final UUID sessionId = JavacProtoUtil.fromProtoUUID(message.getSessionId());
+      final JavacRemoteProto.Message.Type messageType = message.getMessageType();
 
       JavacRemoteProto.Message reply = null;
 
       try {
         if (messageType == JavacRemoteProto.Message.Type.REQUEST) {
-          final JavacRemoteProto.Message.Request request = msg.getRequest();
+          final JavacRemoteProto.Message.Request request = message.getRequest();
           final JavacRemoteProto.Message.Request.Type requestType = request.getRequestType();
           if (requestType == JavacRemoteProto.Message.Request.Type.COMPILE) {
             final List<String> options = request.getOptionList();
@@ -214,11 +204,11 @@
             final CancelHandler cancelHandler = new CancelHandler();
             myCancelHandlers.add(cancelHandler);
             SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
+              @Override
               public void run() {
                 try {
-                  final JavacRemoteProto.Message exitMsg =
-                    compile(ctx, sessionId, options, files, cp, platformCp, srcPath, outs, cancelHandler);
-                  Channels.write(ctx.getChannel(), exitMsg);
+                  context.channel()
+                    .writeAndFlush(compile(context, sessionId, options, files, cp, platformCp, srcPath, outs, cancelHandler));
                 }
                 finally {
                   myCancelHandlers.remove(cancelHandler);
@@ -233,7 +223,9 @@
           else if (requestType == JavacRemoteProto.Message.Request.Type.SHUTDOWN){
             cancelBuilds();
             new Thread("StopThread") {
+              @Override
               public void run() {
+                //noinspection finally
                 try {
                   JavacServer.this.stop();
                 }
@@ -253,20 +245,51 @@
       }
       finally {
         if (reply != null) {
-          Channels.write(ctx.getChannel(), reply);
+          context.channel().writeAndFlush(reply);
         }
       }
     }
-
-    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
-      super.exceptionCaught(ctx, e);
-    }
   }
 
-  private class ChannelRegistrar extends SimpleChannelUpstreamHandler {
-    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-      myAllOpenChannels.add(e.getChannel());
-      super.channelOpen(ctx, e);
+  @ChannelHandler.Sharable
+  private static final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
+    private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
+
+    public boolean isEmpty() {
+      return openChannels.isEmpty();
+    }
+
+    public void add(@NotNull Channel serverChannel) {
+      assert serverChannel instanceof ServerChannel;
+      openChannels.add(serverChannel);
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext context) throws Exception {
+      // we don't need to remove channel on close - ChannelGroup do it
+      openChannels.add(context.channel());
+
+      super.channelActive(context);
+    }
+
+    public ChannelGroupFuture close() {
+      EventLoopGroup eventLoopGroup = null;
+      for (Channel channel : openChannels) {
+        if (channel instanceof ServerChannel) {
+          eventLoopGroup = channel.eventLoop().parent();
+          break;
+        }
+      }
+
+      ChannelGroupFuture future;
+      try {
+        future = openChannels.close();
+      }
+      finally {
+        assert eventLoopGroup != null;
+        eventLoopGroup.shutdownGracefully();
+      }
+      return future;
     }
   }
 
@@ -280,6 +303,7 @@
       myIsCanceled = true;
     }
 
+    @Override
     public boolean isCanceled() {
       return myIsCanceled;
     }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java
index d9103ed..bb553a9 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java
@@ -15,7 +15,6 @@
  */
 package org.jetbrains.jps.javac;
 
-import org.jboss.netty.channel.MessageEvent;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.api.RequestFuture;
 import org.jetbrains.jps.client.SimpleProtobufClient;
@@ -33,9 +32,9 @@
 
   public JavacServerClient() {
     super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.getInstance(), new UUIDGetter() {
+      @Override
       @NotNull
-      public UUID getSessionUUID(@NotNull MessageEvent e) {
-        final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage();
+      public UUID getSessionUUID(@NotNull JavacRemoteProto.Message message) {
         final JavacRemoteProto.Message.UUID uuid = message.getSessionId();
         return new UUID(uuid.getMostSigBits(), uuid.getLeastSigBits());
       }
@@ -46,6 +45,7 @@
     final JavacServerResponseHandler rh = new JavacServerResponseHandler(diagnosticSink, outputSink);
     final JavacRemoteProto.Message.Request request = JavacProtoUtil.createCompilationRequest(options, files, classpath, platformCp, sourcePath, outs);
     return sendRequest(request, rh, new RequestFuture.CancelAction<JavacServerResponseHandler>() {
+      @Override
       public void cancel(RequestFuture<JavacServerResponseHandler> javacServerResponseHandlerRequestFuture) throws Exception {
         sendRequest(JavacProtoUtil.createCancelRequest(), null, null);
       }
diff --git a/lib/netty-3.6.6.Final.jar b/lib/netty-3.6.6.Final.jar
deleted file mode 100644
index 35cb073..0000000
--- a/lib/netty-3.6.6.Final.jar
+++ /dev/null
Binary files differ
diff --git a/lib/netty-all.jar b/lib/netty-all.jar
new file mode 100644
index 0000000..847efe5
--- /dev/null
+++ b/lib/netty-all.jar
Binary files differ
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index 5e07e02..6f98799 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -47,7 +47,7 @@
 xpp3-1.1.4-min.jar
 xstream-1.4.3.jar
 swingx-core-1.6.2.jar
-netty-3.6.6.Final.jar
+netty-all.jar
 protobuf-2.5.0.jar
 rhino-js-1_7R4.jar
 proxy-vole_20120920.jar
diff --git a/lib/src/netty-3.6.6.Final-sources.jar b/lib/src/netty-3.6.6.Final-sources.jar
deleted file mode 100644
index 4144cf5..0000000
--- a/lib/src/netty-3.6.6.Final-sources.jar
+++ /dev/null
Binary files differ
diff --git a/lib/src/netty-all-sources.jar b/lib/src/netty-all-sources.jar
new file mode 100644
index 0000000..07ac406
--- /dev/null
+++ b/lib/src/netty-all-sources.jar
Binary files differ
diff --git a/platform/analysis-api/src/com/intellij/packageDependencies/DependencyRule.java b/platform/analysis-api/src/com/intellij/packageDependencies/DependencyRule.java
index fb2fdd0..99acb49 100644
--- a/platform/analysis-api/src/com/intellij/packageDependencies/DependencyRule.java
+++ b/platform/analysis-api/src/com/intellij/packageDependencies/DependencyRule.java
@@ -21,6 +21,7 @@
 import com.intellij.psi.search.scope.packageSet.ComplementPackageSet;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
 import com.intellij.psi.search.scope.packageSet.PackageSet;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class DependencyRule {
@@ -34,7 +35,7 @@
     myDenyRule = isDenyRule;
   }
 
-  public boolean isForbiddenToUse(PsiFile from, PsiFile to) {
+  public boolean isForbiddenToUse(@NotNull PsiFile from, @NotNull PsiFile to) {
     if (myFromScope == null || myToScope == null) return false;
     final PackageSet fromSet = myFromScope.getValue();
     final PackageSet toSet = myToScope.getValue();
@@ -46,7 +47,7 @@
            && toSet.contains(to, holder);
   }
 
-  public boolean isApplicable(PsiFile file){
+  public boolean isApplicable(@NotNull PsiFile file){
     if (myFromScope == null || myToScope == null) return false;
     final PackageSet fromSet = myFromScope.getValue();
     if (fromSet == null) return false;
diff --git a/platform/analysis-api/src/com/intellij/packageDependencies/DependencyValidationManager.java b/platform/analysis-api/src/com/intellij/packageDependencies/DependencyValidationManager.java
index d1818b3..723aef8 100644
--- a/platform/analysis-api/src/com/intellij/packageDependencies/DependencyValidationManager.java
+++ b/platform/analysis-api/src/com/intellij/packageDependencies/DependencyValidationManager.java
@@ -41,24 +41,26 @@
   public abstract boolean hasRules();
 
   @Nullable
-  public abstract DependencyRule getViolatorDependencyRule(PsiFile from, PsiFile to);
+  public abstract DependencyRule getViolatorDependencyRule(@NotNull PsiFile from, @NotNull PsiFile to);
 
   @NotNull
-  public abstract DependencyRule[] getViolatorDependencyRules(PsiFile from, PsiFile to);
+  public abstract DependencyRule[] getViolatorDependencyRules(@NotNull PsiFile from, @NotNull PsiFile to);
 
   @NotNull
-  public abstract DependencyRule[] getApplicableRules(PsiFile file);
+  public abstract DependencyRule[] getApplicableRules(@NotNull PsiFile file);
 
+  @NotNull
   public abstract DependencyRule[] getAllRules();
 
   public abstract void removeAllRules();
 
-  public abstract void addRule(DependencyRule rule);
+  public abstract void addRule(@NotNull DependencyRule rule);
 
   public abstract boolean skipImportStatements();
 
   public abstract void setSkipImportStatements(boolean skip);
 
+  @NotNull
   public abstract Map<String,PackageSet> getUnnamedScopes();
 
   public abstract void reloadRules();
diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedScopesHolder.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedScopesHolder.java
index 58e66d9..61bd320 100644
--- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedScopesHolder.java
+++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedScopesHolder.java
@@ -156,9 +156,9 @@
   @Override
   public void loadState(final Element state) {
     myScopes.clear();
-    List sets = state.getChildren(SCOPE_TAG);
-    for (Object set : sets) {
-      addScope(readScope((Element)set));
+    List<Element> sets = state.getChildren(SCOPE_TAG);
+    for (Element set : sets) {
+      myScopes.add(readScope(set));
     }
     fireScopeListeners();
   }
diff --git a/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java b/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java
index 190aaca..85215739 100644
--- a/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java
+++ b/platform/analysis-impl/src/com/intellij/packageDependencies/DependencyValidationManagerImpl.java
@@ -25,7 +25,9 @@
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.search.scope.packageSet.*;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.text.UniqueNameGenerator;
+import com.intellij.util.ui.UIUtil;
 import org.jdom.Attribute;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
@@ -46,6 +48,7 @@
   private static final Logger LOG = Logger.getInstance("#com.intellij.packageDependencies.DependencyValidationManagerImpl");
 
   private final List<DependencyRule> myRules = new ArrayList<DependencyRule>();
+  private final NamedScopeManager myNamedScopeManager;
 
   public boolean SKIP_IMPORT_STATEMENTS = false;
 
@@ -59,8 +62,15 @@
 
   private final Map<String, PackageSet> myUnnamedScopes = new HashMap<String, PackageSet>();
 
-  public DependencyValidationManagerImpl(final Project project) {
+  public DependencyValidationManagerImpl(final Project project, NamedScopeManager namedScopeManager) {
     super(project);
+    myNamedScopeManager = namedScopeManager;
+    namedScopeManager.addScopeListener(new ScopeListener() {
+      @Override
+      public void scopesChanged() {
+        reloadScopes();
+      }
+    });
   }
 
   @Override
@@ -95,7 +105,7 @@
 
   @Override
   @Nullable
-  public DependencyRule getViolatorDependencyRule(PsiFile from, PsiFile to) {
+  public DependencyRule getViolatorDependencyRule(@NotNull PsiFile from, @NotNull PsiFile to) {
     for (DependencyRule dependencyRule : myRules) {
       if (dependencyRule.isForbiddenToUse(from, to)) return dependencyRule;
     }
@@ -105,7 +115,7 @@
 
   @Override
   @NotNull
-  public DependencyRule[] getViolatorDependencyRules(PsiFile from, PsiFile to) {
+  public DependencyRule[] getViolatorDependencyRules(@NotNull PsiFile from, @NotNull PsiFile to) {
     ArrayList<DependencyRule> result = new ArrayList<DependencyRule>();
     for (DependencyRule dependencyRule : myRules) {
       if (dependencyRule.isForbiddenToUse(from, to)) {
@@ -117,7 +127,7 @@
 
   @NotNull
   @Override
-  public DependencyRule[] getApplicableRules(PsiFile file) {
+  public DependencyRule[] getApplicableRules(@NotNull PsiFile file) {
     ArrayList<DependencyRule> result = new ArrayList<DependencyRule>();
     for (DependencyRule dependencyRule : myRules) {
       if (dependencyRule.isApplicable(file)) {
@@ -137,11 +147,13 @@
     SKIP_IMPORT_STATEMENTS = skip;
   }
 
+  @NotNull
   @Override
   public Map<String, PackageSet> getUnnamedScopes() {
     return myUnnamedScopes;
   }
 
+  @NotNull
   @Override
   public DependencyRule[] getAllRules() {
     return myRules.toArray(new DependencyRule[myRules.size()]);
@@ -153,7 +165,7 @@
   }
 
   @Override
-  public void addRule(DependencyRule rule) {
+  public void addRule(@NotNull DependencyRule rule) {
     appendUnnamedScope(rule.getFromScope());
     appendUnnamedScope(rule.getToScope());
     myRules.add(rule);
@@ -193,8 +205,8 @@
     catch (InvalidDataException e) {
       LOG.info(e);
     }
-    super.loadState(element);
 
+    super.loadState(element);
     myUnnamedScopes.clear();
     final List unnamedScopes = element.getChildren(UNNAMED_SCOPE);
     final PackageSetFactory packageSetFactory = PackageSetFactory.getInstance();
@@ -212,7 +224,8 @@
   }
 
   private void readRules(Element element) {
-    myRules.clear();
+    removeAllRules();
+
     List rules = element.getChildren(DENY_RULE_KEY);
     for (Object rule1 : rules) {
       DependencyRule rule = readRule((Element)rule1);
@@ -336,4 +349,40 @@
     }
   }
 
+
+  private final List<Pair<NamedScope, NamedScopesHolder>> myScopes = ContainerUtil.createLockFreeCopyOnWriteList();
+
+  private void reloadScopes() {
+    UIUtil.invokeLaterIfNeeded(new Runnable() {
+      @Override
+      public void run() {
+        if (getProject().isDisposed()) return;
+        List<Pair<NamedScope, NamedScopesHolder>> scopeList = new ArrayList<Pair<NamedScope, NamedScopesHolder>>();
+        addScopesToList(scopeList, DependencyValidationManagerImpl.this);
+        addScopesToList(scopeList, myNamedScopeManager);
+        myScopes.clear();
+        myScopes.addAll(scopeList);
+        reloadRules();
+      }
+    });
+  }
+
+  private static void addScopesToList(@NotNull final List<Pair<NamedScope, NamedScopesHolder>> scopeList,
+                                      @NotNull final NamedScopesHolder holder) {
+    NamedScope[] scopes = holder.getScopes();
+    for (NamedScope scope : scopes) {
+      scopeList.add(Pair.create(scope, holder));
+    }
+  }
+
+  @NotNull
+  public List<Pair<NamedScope, NamedScopesHolder>> getScopeBasedHighlightingCachedScopes() {
+    return myScopes;
+  }
+
+  @Override
+  public void fireScopeListeners() {
+    super.fireScopeListeners();
+    reloadScopes();
+  }
 }
diff --git a/platform/annotations/annotations.iml b/platform/annotations/annotations.iml
index c053808..262fa56 100644
--- a/platform/annotations/annotations.iml
+++ b/platform/annotations/annotations.iml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
diff --git a/platform/platform-api/src/com/intellij/openapi/application/WriteAction.java b/platform/core-api/src/com/intellij/openapi/application/WriteAction.java
similarity index 71%
rename from platform/platform-api/src/com/intellij/openapi/application/WriteAction.java
rename to platform/core-api/src/com/intellij/openapi/application/WriteAction.java
index 4396c2b..b8c5e16 100644
--- a/platform/platform-api/src/com/intellij/openapi/application/WriteAction.java
+++ b/platform/core-api/src/com/intellij/openapi/application/WriteAction.java
@@ -16,10 +16,11 @@
 package com.intellij.openapi.application;
 
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.ui.GuiUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
+
 public abstract class WriteAction<T> extends BaseActionRunnable<T> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.WriteAction");
   @NotNull
@@ -27,27 +28,36 @@
   public RunResult<T> execute() {
     final RunResult<T> result = new RunResult<T>(this);
 
-    if (canWriteNow()) {
+    final Application application = ApplicationManager.getApplication();
+    if (application.isWriteAccessAllowed()) {
       result.run();
       return result;
     }
 
     try {
-      if (!ApplicationManager.getApplication().isDispatchThread() && ApplicationManager.getApplication().isReadAccessAllowed()) {
+      if (!application.isDispatchThread() && application.isReadAccessAllowed()) {
         LOG.error("Must not start write action from within read action in the other thread - deadlock is coming");
       }
-      GuiUtils.runOrInvokeAndWait(new Runnable() {
+      Runnable runnable = new Runnable() {
         @Override
         public void run() {
-          final AccessToken accessToken = start();
-          try {
-            result.run();
-          }
-          finally {
-            accessToken.finish();
-          }
+          application.runWriteAction(new Runnable() {
+            @Override
+            public void run() {
+              result.run();
+            }
+          });
         }
-      });
+      };
+      if (application.isDispatchThread()) {
+        runnable.run();
+      }
+      else if (application.isReadAccessAllowed()) {
+        LOG.error("Calling write action from read-action leads to deadlock.");
+      }
+      else {
+        SwingUtilities.invokeAndWait(runnable);
+      }
     }
     catch (Exception e) {
       if (isSilentExecution()) {
diff --git a/platform/lang-api/src/com/intellij/openapi/command/WriteCommandAction.java b/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
similarity index 83%
rename from platform/lang-api/src/com/intellij/openapi/command/WriteCommandAction.java
rename to platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
index b7887d1..4be6c35 100644
--- a/platform/lang-api/src/com/intellij/openapi/command/WriteCommandAction.java
+++ b/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
@@ -15,23 +15,19 @@
  */
 package com.intellij.openapi.command;
 
+import com.intellij.codeInsight.FileModificationService;
 import com.intellij.openapi.application.*;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.ReadonlyStatusHandler;
-import com.intellij.openapi.vfs.VfsUtilCore;
-import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
-import com.intellij.ui.GuiUtils;
-import com.intellij.util.SmartList;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 
 public abstract class WriteCommandAction<T> extends BaseActionRunnable<T> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.command.WriteCommandAction");
@@ -84,11 +80,14 @@
         }
       };
       Application application = ApplicationManager.getApplication();
-      if (application.isWriteAccessAllowed() || application.isDispatchThread()) {
+      if (application.isDispatchThread()) {
         runnable.run();
       }
+      else if (application.isReadAccessAllowed()) {
+        LOG.error("Calling write command from read-action leads to deadlock.");
+      }
       else {
-        GuiUtils.invokeAndWait(runnable);
+        SwingUtilities.invokeAndWait(runnable);
       }
     }
     catch (InvocationTargetException e) {
@@ -99,26 +98,11 @@
   }
 
   public static boolean ensureFilesWritable(@NotNull final Project project, @NotNull final Collection<PsiFile> psiFiles) {
-    if (!psiFiles.isEmpty()) {
-      List<VirtualFile> list = new SmartList<VirtualFile>();
-      for (final PsiFile psiFile : psiFiles) {
-        if (psiFile == null) continue;
-        final VirtualFile virtualFile = psiFile.getVirtualFile();
-        if (virtualFile != null) {
-            list.add(virtualFile);
-          }
-      }
-      if (!list.isEmpty()) {
-        if (ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(VfsUtilCore.toVirtualFileArray(list)).hasReadonlyFiles()) {
-          return false;
-        }
-      }
-    }
-    return true;
+    return FileModificationService.getInstance().preparePsiElementsForWrite(psiFiles);
   }
 
   private void performWriteCommandAction(final RunResult<T> result) {
-    if (myProject != null && !ensureFilesWritable(myProject, Arrays.asList(myPsiFiles))) return;
+    if (!FileModificationService.getInstance().preparePsiElementsForWrite(Arrays.asList(myPsiFiles))) return;
 
     //this is needed to prevent memory leak, since command
     // is put into undo queue
diff --git a/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java b/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java
index 0f556dc..7b94ad1 100644
--- a/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java
+++ b/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java
@@ -22,7 +22,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
-import com.intellij.psi.stubs.StubElement;
+import com.intellij.psi.StubBasedPsiElement;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtilCore;
 import org.jetbrains.annotations.NotNull;
@@ -74,7 +74,7 @@
           localScope.add(file);
         }
       }
-      else if (element instanceof StubElement || element.getTextRange() != null){
+      else if (element instanceof StubBasedPsiElement || element.getTextRange() != null){
         localScope.add(element);
       }
     }
diff --git a/platform/core-api/src/com/intellij/psi/tree/IElementType.java b/platform/core-api/src/com/intellij/psi/tree/IElementType.java
index ed349f7..b64d761 100644
--- a/platform/core-api/src/com/intellij/psi/tree/IElementType.java
+++ b/platform/core-api/src/com/intellij/psi/tree/IElementType.java
@@ -51,7 +51,7 @@
   };
 
   public static final short FIRST_TOKEN_INDEX = 1;
-  public static final short MAX_INDEXED_TYPES = 20000;
+  public static final short MAX_INDEXED_TYPES = 15000;
 
   private static short ourCounter = FIRST_TOKEN_INDEX;
   private static IElementType[] ourRegistry = new IElementType[700];
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java b/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java
index 334feb7..1948ff4 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java
@@ -476,9 +476,10 @@
     final PsiElement element = originalFile.findElementAt(range.getStartOffset());
     final int maxLength = range.getLength();
     T parent = PsiTreeUtil.getParentOfType(element, elementClass, false);
-    for (T next = parent ;
-         next != null && next.getTextLength() <= maxLength;
-         parent = next, next = PsiTreeUtil.getParentOfType(next, elementClass, true)) {
+    T next = parent ;
+    while (next != null && next.getTextLength() <= maxLength) {
+      parent = next;
+      next = PsiTreeUtil.getParentOfType(next, elementClass, true);
     }
     return parent;
   }
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
index d914256..c3b770a 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
@@ -35,9 +35,13 @@
   private final boolean isDirectory;
 
   public CoreLocalVirtualFile(@NotNull CoreLocalFileSystem fileSystem, @NotNull File ioFile) {
+    this(fileSystem, ioFile, ioFile.isDirectory());
+  }
+
+  public CoreLocalVirtualFile(@NotNull CoreLocalFileSystem fileSystem, @NotNull File ioFile, boolean isDirectory) {
     myFileSystem = fileSystem;
     myIoFile = ioFile;
-    isDirectory = ioFile.isDirectory();
+    this.isDirectory = isDirectory;
   }
 
   @NotNull
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
index 5fefd4f..3e8c237 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
@@ -39,9 +39,7 @@
     final MessageBus bus = project.getMessageBus();
     myPublisher = bus.syncPublisher(TOPIC);
     bus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() {
-
-      @Override
-      public void enteredDumbMode() {
+      private void doIncCounter() {
         ApplicationManager.getApplication().runWriteAction(new Runnable() {
           @Override
           public void run() {
@@ -51,8 +49,13 @@
       }
 
       @Override
+      public void enteredDumbMode() {
+        doIncCounter();
+      }
+
+      @Override
       public void exitDumbMode() {
-        enteredDumbMode();
+        doIncCounter();
       }
     });
   }
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LightTreeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LightTreeUtil.java
index c490e67..ccfa8b0 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LightTreeUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LightTreeUtil.java
@@ -19,6 +19,7 @@
 import com.intellij.lang.LighterASTNode;
 import com.intellij.lang.LighterASTTokenNode;
 import com.intellij.lang.LighterLazyParseableNode;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
 import com.intellij.util.SmartList;
@@ -86,7 +87,12 @@
 
   @NotNull
   public static String toFilteredString(@NotNull LighterAST tree, @NotNull LighterASTNode node, @Nullable TokenSet skipTypes) {
-    StringBuilder buffer = new StringBuilder(node.getEndOffset() - node.getStartOffset());
+    int length = node.getEndOffset() - node.getStartOffset();
+    if (length < 0) {
+      length = 0;
+      Logger.getInstance(LightTreeUtil.class).error("tree=" + tree + " node=" + node);
+    }
+    StringBuilder buffer = new StringBuilder(length);
     toBuffer(tree, node, buffer, skipTypes);
     return buffer.toString();
   }
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
index 03e2758..7ce253c 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
@@ -541,13 +541,15 @@
    * <p/>
    * However, we do allow to explicitly configure the ide to work with third-party external system api from the ide process.
    * <p/>
-   * This method allows to check whether the ide is configured to use 'out of process' or 'in process' mode.
-   * 
+   * This method allows to check whether the ide is configured to use 'out of process' or 'in process' mode for the system.
+   *
+   * @param externalSystemId     target external system
+   *
    * @return   <code>true</code> if the ide is configured to work with external system api from the ide process;
-   *           <code>false</code> otherwise 
+   *           <code>false</code> otherwise
    */
-  public static boolean isInProcessMode() {
-    return Registry.is(ExternalSystemConstants.USE_IN_PROCESS_COMMUNICATION_REGISTRY_KEY, false);
+  public static boolean isInProcessMode(ProjectSystemId externalSystemId) {
+    return Registry.is(externalSystemId.getId() + ExternalSystemConstants.USE_IN_PROCESS_COMMUNICATION_REGISTRY_KEY_SUFFIX, false);
   }
 
   /**
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
index 659a32d..c7232c0 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
@@ -33,7 +33,7 @@
   @NonNls @NotNull public static final String TOOL_WINDOW_PLACE       = "ExternalSystem.ToolWindow";
   @NonNls @NotNull public static final String TREE_CONTEXT_MENU_PLACE = "ExternalSystem.Tree.Context.Menu";
 
-  @NotNull @NonNls public static final String USE_IN_PROCESS_COMMUNICATION_REGISTRY_KEY = "external.system.in.process";
+  @NotNull @NonNls public static final String USE_IN_PROCESS_COMMUNICATION_REGISTRY_KEY_SUFFIX = ".system.in.process";
 
   @NotNull public static final String DEBUG_RUNNER_ID = "ExternalSystemTaskDebugRunner";
   @NotNull public static final String RUNNER_ID       = "ExternalSystemTaskRunner";
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
index 862d603..edf4fee 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
@@ -28,7 +28,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -51,11 +50,6 @@
     = ContainerUtil.newConcurrentMap();
 
   @NotNull private final Lock          myLock                   = new ReentrantLock();
-  @NotNull private final AtomicBoolean myInProcessCommunication = new AtomicBoolean();
-
-  @NotNull private final AtomicReference<ExternalSystemCommunicationManager> myCommunicationManager =
-    new AtomicReference<ExternalSystemCommunicationManager>();
-
 
   @NotNull private final RemoteExternalSystemProgressNotificationManager myProgressManager;
   @NotNull private final RemoteExternalSystemCommunicationManager        myRemoteCommunicationManager;
@@ -68,9 +62,6 @@
     myProgressManager = (RemoteExternalSystemProgressNotificationManager)notificationManager;
     myRemoteCommunicationManager = remoteCommunicationManager;
     myInProcessCommunicationManager = inProcessCommunicationManager;
-    boolean inProcessCommunication = ExternalSystemApiUtil.isInProcessMode();
-    myInProcessCommunication.set(inProcessCommunication);
-    myCommunicationManager.set(inProcessCommunication ? myInProcessCommunicationManager : myRemoteCommunicationManager);
   }
 
   @NotNull
@@ -157,33 +148,29 @@
   @SuppressWarnings("ConstantConditions")
   @NotNull
   private RemoteExternalSystemFacade doGetFacade(@NotNull IntegrationKey key, @NotNull Project project) throws Exception {
-    boolean currentInProcess = ExternalSystemApiUtil.isInProcessMode();
-    if (myInProcessCommunication.getAndSet(currentInProcess) != currentInProcess) {
-      myCommunicationManager.get().clear();
-      myCommunicationManager.set(currentInProcess ? myInProcessCommunicationManager : myRemoteCommunicationManager);
-    }
+    final boolean currentInProcess = ExternalSystemApiUtil.isInProcessMode(key.getExternalSystemId());
+    final ExternalSystemCommunicationManager myCommunicationManager = currentInProcess ? myInProcessCommunicationManager : myRemoteCommunicationManager;
     
     ExternalSystemManager manager = ExternalSystemApiUtil.getManager(key.getExternalSystemId());
     if (project.isDisposed() || manager == null) {
       return RemoteExternalSystemFacade.NULL_OBJECT;
     }
     Pair<RemoteExternalSystemFacade, ExternalSystemExecutionSettings> pair = myRemoteFacades.get(key);
-    if (pair != null && prepare(project, key, pair)) {
+    if (pair != null && prepare(myCommunicationManager, project, key, pair)) {
       return pair.first;
     }
     
     myLock.lock();
     try {
       pair = myRemoteFacades.get(key);
-      if (pair != null && prepare(project, key, pair)) {
+      if (pair != null && prepare(myCommunicationManager, project, key, pair)) {
         return pair.first;
       }
       if (pair != null) {
-        myCommunicationManager.get().clear();
         myFacadeWrappers.clear();
         myRemoteFacades.clear();
       }
-      return doCreateFacade(key, project);
+      return doCreateFacade(key, project, myCommunicationManager);
     }
     finally {
       myLock.unlock();
@@ -192,15 +179,15 @@
 
   @SuppressWarnings("unchecked")
   @NotNull
-  private RemoteExternalSystemFacade doCreateFacade(@NotNull IntegrationKey key, @NotNull Project project) throws Exception {
-    final RemoteExternalSystemFacade facade = myCommunicationManager.get().acquire(project.getName(), key.getExternalSystemId());
+  private RemoteExternalSystemFacade doCreateFacade(@NotNull IntegrationKey key, @NotNull Project project,
+                                                    @NotNull ExternalSystemCommunicationManager communicationManager) throws Exception {
+    final RemoteExternalSystemFacade facade = communicationManager.acquire(project.getName(), key.getExternalSystemId());
     if (facade == null) {
       throw new IllegalStateException("Can't obtain facade to working with external api at the remote process. Project: " + project);
     }
     Disposer.register(project, new Disposable() {
       @Override
       public void dispose() {
-        myCommunicationManager.get().clear();
         myFacadeWrappers.clear();
         myRemoteFacades.clear();
       }
@@ -215,11 +202,11 @@
   }
 
   @SuppressWarnings("unchecked")
-  private boolean prepare(@NotNull Project project,
-                          @NotNull IntegrationKey key,
+  private boolean prepare(@NotNull ExternalSystemCommunicationManager communicationManager,
+                          @NotNull Project project, @NotNull IntegrationKey key,
                           @NotNull Pair<RemoteExternalSystemFacade, ExternalSystemExecutionSettings> pair)
   {
-     if (!myCommunicationManager.get().isAlive(pair.first)) {
+     if (!communicationManager.isAlive(pair.first)) {
       return false;
     }
     try {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java
index 061a88c..a0ea3e4 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java
@@ -148,7 +148,7 @@
       }
       String vmOptions;
       if (myDebugPort > 0) {
-        String debuggerSetup = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + myDebugPort;
+        String debuggerSetup = "-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=" + myDebugPort;
         String regular = mySettings.getVmOptions();
         vmOptions = regular == null ? debuggerSetup : regular + " " + debuggerSetup;
       }
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
index b0d18c6..71b74f6 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
@@ -59,7 +59,7 @@
     if (state instanceof ExternalSystemRunConfiguration.MyRunnableState) {
       int port = ((ExternalSystemRunConfiguration.MyRunnableState)state).getDebugPort();
       if (port > 0) {
-        RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", String.valueOf(port), false);
+        RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", String.valueOf(port), true);
         return attachVirtualMachine(project, state, contentToReuse, env, connection, true);
       }
       else {
diff --git a/platform/icons/src/fileTypes/manifest.png b/platform/icons/src/fileTypes/manifest.png
new file mode 100644
index 0000000..df581b3
--- /dev/null
+++ b/platform/icons/src/fileTypes/manifest.png
Binary files differ
diff --git a/platform/icons/src/fileTypes/manifest@2x.png b/platform/icons/src/fileTypes/manifest@2x.png
new file mode 100644
index 0000000..8513230
--- /dev/null
+++ b/platform/icons/src/fileTypes/manifest@2x.png
Binary files differ
diff --git a/platform/lang-api/src/com/intellij/lang/findUsages/package.html b/platform/indexing-api/src/com/intellij/lang/findUsages/package.html
similarity index 100%
rename from platform/lang-api/src/com/intellij/lang/findUsages/package.html
rename to platform/indexing-api/src/com/intellij/lang/findUsages/package.html
diff --git a/platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java b/platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java
index 8aacbce..0e4cd6b 100644
--- a/platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java
+++ b/platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java
@@ -33,4 +33,8 @@
   public KeyDescriptor<String> getKeyDescriptor() {
     return new EnumeratorStringDescriptor();
   }
+
+  public boolean traceKeyHashToVirtualFileMapping() {
+    return false;
+  }
 }
\ No newline at end of file
diff --git a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
index eee5e64..bbe7324 100644
--- a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
+++ b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
@@ -28,7 +28,9 @@
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.Processor;
 import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.IdFilter;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.Iterator;
@@ -59,6 +61,10 @@
 
   public abstract <K> boolean processAllKeys(@NotNull StubIndexKey<K, ?> indexKey, @NotNull Project project, Processor<K> processor);
 
+  public <K> boolean processAllKeys(@NotNull StubIndexKey<K, ?> indexKey, Processor<K> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) {
+    return processAllKeys(indexKey, scope.getProject(), processor);
+  }
+
   public <Key, Psi extends PsiElement> Collection<Psi> safeGet(@NotNull StubIndexKey<Key, Psi> indexKey,
                                                                @NotNull Key key,
                                                                @NotNull final Project project,
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 6d07a27..9260714 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
@@ -126,6 +126,10 @@
    */
   public abstract <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, Processor<K> processor, @Nullable Project project);
 
+  public <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, @NotNull Processor<K> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) {
+    return processAllKeys(indexId, processor, scope.getProject());
+  }
+
   public interface ValueProcessor<V> {
     /**
      * @param value a value to process
@@ -145,4 +149,7 @@
   public interface FileTypeSpecificInputFilter extends InputFilter {
     void registerFileTypesUsedForIndexing(@NotNull Consumer<FileType> fileTypeSink);
   }
+
+  // TODO: remove once changes becomes permamnent
+  public static final boolean ourEnableTracingOfKeyHashToVirtualFileMapping = ApplicationManager.getApplication().isInternal();
 }
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
index 14fcf80..0dc808f 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
@@ -80,6 +80,10 @@
     return false;
   }
 
+  public boolean traceKeyHashToVirtualFileMapping() {
+    return false;
+  }
+
   /** Per-filetype index version support */
   public Map<FileType, Integer> getVersionMap() {
     return Collections.emptyMap();
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java
new file mode 100644
index 0000000..c4b7550
--- /dev/null
+++ b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java
@@ -0,0 +1,23 @@
+/*
+ * 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.util.indexing;
+
+/**
+* Created by Maxim.Mossienko on 8/14/13.
+*/
+public abstract class IdFilter {
+  public abstract boolean contains(int id);
+}
diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
index ededc778..641751a 100644
--- a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
+++ b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
@@ -71,7 +71,7 @@
 
   @Override
   public int getVersion() {
-    return 1;
+    return 1 + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 1 : 0);
   }
 
   public static String[] getAllFilenames(Project project) {
@@ -160,4 +160,9 @@
     }
     return files;
   }
+
+  @Override
+  public boolean traceKeyHashToVirtualFileMapping() {
+    return FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
+  }
 }
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionConfidence.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionConfidence.java
index 6ba89a9..ab7b43c 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionConfidence.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionConfidence.java
@@ -31,6 +31,10 @@
   @NotNull
   public abstract ThreeState shouldFocusLookup(@NotNull CompletionParameters parameters);
 
+  /**
+   * This method is invoked first when a completion autopopup is scheduled. Extensions are able to cancel this completion process based on location.
+   * For example, in string literals or comments completion autopopup may do more harm than good.
+   */
   @NotNull
   public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
     return ThreeState.UNSURE;
diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/QuickFixActionRegistrar.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/QuickFixActionRegistrar.java
index ea79f57..2194bbe 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/daemon/QuickFixActionRegistrar.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/QuickFixActionRegistrar.java
@@ -19,15 +19,16 @@
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
 
 public interface QuickFixActionRegistrar {
-  void register(IntentionAction action);
-  void register(TextRange fixRange, IntentionAction action, HighlightDisplayKey key);
+  void register(@NotNull IntentionAction action);
+  void register(@NotNull TextRange fixRange, @NotNull IntentionAction action, HighlightDisplayKey key);
 
   /**
    * Allows to replace some of the built-in quickfixes.
    * @param condition condition for quickfixes to remove
    * @since 9.0
    */
-  void unregister(Condition<IntentionAction> condition);
+  void unregister(@NotNull Condition<IntentionAction> condition);
 }
diff --git a/platform/lang-api/src/com/intellij/codeInsight/generation/actions/GenerateActionPopupTemplateInjector.java b/platform/lang-api/src/com/intellij/codeInsight/generation/actions/GenerateActionPopupTemplateInjector.java
new file mode 100644
index 0000000..56868fe
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/codeInsight/generation/actions/GenerateActionPopupTemplateInjector.java
@@ -0,0 +1,28 @@
+/*
+ * 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.generation.actions;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.DataContext;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Generate action could provide an action to edit corresponding file template. It would appear then in the subMenu of the Generate... popup 
+ */
+public interface GenerateActionPopupTemplateInjector {
+  @Nullable
+  AnAction createEditTemplateAction(DataContext dataContext);
+}
diff --git a/platform/lang-api/src/com/intellij/lang/annotation/AnnotationHolder.java b/platform/lang-api/src/com/intellij/lang/annotation/AnnotationHolder.java
index 3fcbc8c..ea076d2 100644
--- a/platform/lang-api/src/com/intellij/lang/annotation/AnnotationHolder.java
+++ b/platform/lang-api/src/com/intellij/lang/annotation/AnnotationHolder.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.
@@ -27,7 +27,6 @@
  * @author max
  * @see Annotator#annotate(com.intellij.psi.PsiElement, AnnotationHolder)
  */
-
 public interface AnnotationHolder {
   /**
    * Creates an error annotation with the specified message over the specified PSI element.
@@ -84,35 +83,34 @@
   Annotation createWarningAnnotation(@NotNull TextRange range, @Nullable String message);
 
   /**
-      * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
-      * message over the specified PSI element.
-      *
-      * @param elt     the element over which the annotation is created.
-      * @param message the info message.
-      * @return the annotation (which can be modified to set additional annotation parameters)
-      */
-    Annotation createWeakWarningAnnotation(@NotNull PsiElement elt, @Nullable String message);
+   * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
+   * message over the specified PSI element.
+   *
+   * @param elt     the element over which the annotation is created.
+   * @param message the info message.
+   * @return the annotation (which can be modified to set additional annotation parameters)
+   */
+  Annotation createWeakWarningAnnotation(@NotNull PsiElement elt, @Nullable String message);
 
-     /**
-      * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
-      * message over the specified AST node.
-      *
-      * @param node    the node over which the annotation is created.
-      * @param message the info message.
-      * @return the annotation (which can be modified to set additional annotation parameters)
-      */
-     Annotation createWeakWarningAnnotation(@NotNull ASTNode node, @Nullable String message);
+  /**
+   * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
+   * message over the specified AST node.
+   *
+   * @param node    the node over which the annotation is created.
+   * @param message the info message.
+   * @return the annotation (which can be modified to set additional annotation parameters)
+   */
+  Annotation createWeakWarningAnnotation(@NotNull ASTNode node, @Nullable String message);
 
-     /**
-      * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
-      * message over the specified text range.
-      *
-      * @param range   the text range over which the annotation is created.
-      * @param message the info message.
-      * @return the annotation (which can be modified to set additional annotation parameters)
-      */
-     Annotation createWeakWarningAnnotation(@NotNull TextRange range, @Nullable String message);
-
+  /**
+   * Creates an annotation with severity {@link HighlightSeverity#WEAK_WARNING} ('weak warning') with the specified
+   * message over the specified text range.
+   *
+   * @param range   the text range over which the annotation is created.
+   * @param message the info message.
+   * @return the annotation (which can be modified to set additional annotation parameters)
+   */
+  Annotation createWeakWarningAnnotation(@NotNull TextRange range, @Nullable String message);
 
   /**
    * Creates an information annotation (colored highlighting only, with no gutter mark and not participating in
@@ -144,7 +142,6 @@
    */
   Annotation createInfoAnnotation(@NotNull TextRange range, @Nullable String message);
 
-
   @NotNull
   AnnotationSession getCurrentAnnotationSession();
 
diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
index 4f2f65b..ccc4fed 100644
--- a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
+++ b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.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.
@@ -44,7 +44,7 @@
    * @param element the element for which Safe Delete was invoked
    * @return true if Safe Delete is available, false otherwise.
    */
-  public boolean isSafeDeleteAvailable(PsiElement element) { return false; }
+  public boolean isSafeDeleteAvailable(@NotNull PsiElement element) { return false; }
 
   /**
    * @return handler for introducing local variables in this language
@@ -123,9 +123,9 @@
   @Nullable
   public ChangeSignatureHandler getChangeSignatureHandler() { return null; }
 
-  public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) { return false; }
+  public boolean isInplaceRenameAvailable(@NotNull PsiElement element, PsiElement context) { return false; }
 
-  public boolean isInplaceIntroduceAvailable(PsiElement element, PsiElement context) {
+  public boolean isInplaceIntroduceAvailable(@NotNull PsiElement element, PsiElement context) {
     return false;
   }
 
@@ -138,7 +138,7 @@
     return null;
   }
 
-  public boolean isMemberInplaceRenameAvailable(PsiElement element, PsiElement context) {
+  public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement element, @Nullable PsiElement context) {
     return false;
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
index 5d7ae51..cf5d538 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
@@ -19,7 +19,6 @@
 import com.intellij.application.options.OptionsContainingConfigurable;
 import com.intellij.application.options.editor.EditorOptionsProvider;
 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
-import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
 import com.intellij.execution.impl.ConsoleViewUtil;
 import com.intellij.ide.ui.LafManager;
 import com.intellij.ide.ui.laf.darcula.DarculaInstaller;
@@ -56,6 +55,8 @@
 import com.intellij.openapi.vcs.FileStatus;
 import com.intellij.openapi.vcs.FileStatusFactory;
 import com.intellij.openapi.vcs.FileStatusManager;
+import com.intellij.packageDependencies.DependencyValidationManager;
+import com.intellij.packageDependencies.DependencyValidationManagerImpl;
 import com.intellij.psi.codeStyle.DisplayPriority;
 import com.intellij.psi.codeStyle.DisplayPrioritySortable;
 import com.intellij.psi.search.scope.packageSet.NamedScope;
@@ -151,15 +152,16 @@
     return mySelectedScheme.getDescriptors();
   }
 
-  public static boolean isReadOnly(final EditorColorsScheme scheme) {
+  public static boolean isReadOnly(@NotNull final EditorColorsScheme scheme) {
     return ((MyColorScheme)scheme).isReadOnly();
   }
 
+  @NotNull
   public String[] getSchemeNames() {
-    ArrayList<MyColorScheme> schemes = new ArrayList<MyColorScheme>(mySchemes.values());
+    List<MyColorScheme> schemes = new ArrayList<MyColorScheme>(mySchemes.values());
     Collections.sort(schemes, new Comparator<MyColorScheme>() {
       @Override
-      public int compare(MyColorScheme o1, MyColorScheme o2) {
+      public int compare(@NotNull MyColorScheme o1, @NotNull MyColorScheme o2) {
         if (isReadOnly(o1) && !isReadOnly(o2)) return -1;
         if (!isReadOnly(o1) && isReadOnly(o2)) return 1;
 
@@ -167,7 +169,7 @@
       }
     });
 
-    ArrayList<String> names = new ArrayList<String>(schemes.size());
+    List<String> names = new ArrayList<String>(schemes.size());
     for (MyColorScheme scheme : schemes) {
       names.add(scheme.getName());
     }
@@ -175,6 +177,7 @@
     return ArrayUtil.toStringArray(names);
   }
 
+  @NotNull
   public Collection<EditorColorsScheme> getSchemes() {
     return new ArrayList<EditorColorsScheme>(mySchemes.values());
   }
@@ -198,7 +201,7 @@
     resetSchemesCombo(null);
   }
 
-  public void addImportedScheme(final EditorColorsScheme imported) {
+  public void addImportedScheme(@NotNull final EditorColorsScheme imported) {
     MyColorScheme newScheme = new MyColorScheme(imported);
     initScheme(newScheme);
 
@@ -312,6 +315,7 @@
     return true;
   }
 
+  @NotNull
   @Override
   public Configurable[] buildConfigurables() {
     myDisposeCompleted = false;
@@ -329,6 +333,7 @@
     return result.toArray(new Configurable[result.size()]);
   }
 
+  @NotNull
   private Set<NewColorAndFontPanel> getPanels() {
     Set<NewColorAndFontPanel> result = new HashSet<NewColorAndFontPanel>();
     for (InnerSearchableConfigurable configurable : mySubPanelFactories.values()) {
@@ -341,7 +346,7 @@
   }
 
   protected List<ColorAndFontPanelFactory> createPanelFactories() {
-    ArrayList<ColorAndFontPanelFactory> result = new ArrayList<ColorAndFontPanelFactory>();
+    List<ColorAndFontPanelFactory> result = new ArrayList<ColorAndFontPanelFactory>();
     result.add(new FontConfigurableFactory());
 
     List<ColorAndFontPanelFactory> extensions = new ArrayList<ColorAndFontPanelFactory>();
@@ -443,6 +448,7 @@
       return "Console Font";
     }
 
+     @NotNull
      @Override
      public DisplayPriority getPriority() {
        return DisplayPriority.COMMON_SETTINGS;
@@ -499,8 +505,8 @@
     assert mySelectedScheme != null : EditorColorsManager.getInstance().getGlobalScheme().getName() + "; myschemes=" + mySchemes;
   }
 
-  private static void initScheme(MyColorScheme scheme) {
-    ArrayList<EditorSchemeAttributeDescriptor> descriptions = new ArrayList<EditorSchemeAttributeDescriptor>();
+  private static void initScheme(@NotNull MyColorScheme scheme) {
+    List<EditorSchemeAttributeDescriptor> descriptions = new ArrayList<EditorSchemeAttributeDescriptor>();
     initPluggedDescriptions(descriptions, scheme);
     initDiffDescriptors(descriptions, scheme);
     initFileStatusDescriptors(descriptions, scheme);
@@ -509,7 +515,7 @@
     scheme.setDescriptors(descriptions.toArray(new EditorSchemeAttributeDescriptor[descriptions.size()]));
   }
 
-  private static void initPluggedDescriptions(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
+  private static void initPluggedDescriptions(@NotNull List<EditorSchemeAttributeDescriptor> descriptions, @NotNull MyColorScheme scheme) {
     ColorSettingsPage[] pages = ColorSettingsPages.getInstance().getRegisteredPages();
     for (ColorSettingsPage page : pages) {
       initDescriptions(page, descriptions, scheme);
@@ -519,9 +525,9 @@
     }
   }
 
-  private static void initDescriptions(ColorAndFontDescriptorsProvider provider,
-                                       ArrayList<EditorSchemeAttributeDescriptor> descriptions,
-                                       MyColorScheme scheme) {
+  private static void initDescriptions(@NotNull ColorAndFontDescriptorsProvider provider,
+                                       @NotNull List<EditorSchemeAttributeDescriptor> descriptions,
+                                       @NotNull MyColorScheme scheme) {
     String group = provider.getDisplayName();
     List<AttributesDescriptor> attributeDescriptors = ColorSettingsUtil.getAllAttributeDescriptors(provider);
     for (AttributesDescriptor descriptor : attributeDescriptors) {
@@ -536,11 +542,11 @@
     }
   }
 
-  private static void initDiffDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
+  private static void initDiffDescriptors(@NotNull List<EditorSchemeAttributeDescriptor> descriptions, @NotNull MyColorScheme scheme) {
     DiffOptionsPanel.addSchemeDescriptions(descriptions, scheme);
   }
 
-  private static void initFileStatusDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
+  private static void initFileStatusDescriptors(@NotNull List<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
 
     FileStatus[] statuses = FileStatusFactory.getInstance().getAllFileStatuses();
 
@@ -554,22 +560,22 @@
 
     }
   }
-  private static void initScopesDescriptors(ArrayList<EditorSchemeAttributeDescriptor> descriptions, MyColorScheme scheme) {
+  private static void initScopesDescriptors(@NotNull List<EditorSchemeAttributeDescriptor> descriptions, @NotNull MyColorScheme scheme) {
     Set<Pair<NamedScope,NamedScopesHolder>> namedScopes = new THashSet<Pair<NamedScope,NamedScopesHolder>>(new TObjectHashingStrategy<Pair<NamedScope,NamedScopesHolder>>() {
       @Override
-      public int computeHashCode(final Pair<NamedScope, NamedScopesHolder> object) {
+      public int computeHashCode(@NotNull final Pair<NamedScope, NamedScopesHolder> object) {
         return object.getFirst().getName().hashCode();
       }
 
       @Override
-      public boolean equals(final Pair<NamedScope, NamedScopesHolder> o1, final Pair<NamedScope, NamedScopesHolder> o2) {
+      public boolean equals(@NotNull final Pair<NamedScope, NamedScopesHolder> o1, @NotNull final Pair<NamedScope, NamedScopesHolder> o2) {
         return o1.getFirst().getName().equals(o2.getFirst().getName());
       }
     });
     Project[] projects = ProjectManager.getInstance().getOpenProjects();
     for (Project project : projects) {
-      DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
-      List<Pair<NamedScope,NamedScopesHolder>> cachedScopes = codeAnalyzer.getScopeBasedHighlightingCachedScopes();
+      DependencyValidationManagerImpl validationManager = (DependencyValidationManagerImpl)DependencyValidationManager.getInstance(project);
+      List<Pair<NamedScope,NamedScopesHolder>> cachedScopes = validationManager.getScopeBasedHighlightingCachedScopes();
       namedScopes.addAll(cachedScopes);
     }
 
@@ -577,14 +583,14 @@
 
     Collections.sort(list, new Comparator<Pair<NamedScope,NamedScopesHolder>>() {
       @Override
-      public int compare(final Pair<NamedScope,NamedScopesHolder> o1, final Pair<NamedScope,NamedScopesHolder> o2) {
+      public int compare(@NotNull final Pair<NamedScope,NamedScopesHolder> o1, @NotNull final Pair<NamedScope,NamedScopesHolder> o2) {
         return o1.getFirst().getName().compareToIgnoreCase(o2.getFirst().getName());
       }
     });
     for (Pair<NamedScope,NamedScopesHolder> pair : list) {
       NamedScope namedScope = pair.getFirst();
       String name = namedScope.getName();
-      TextAttributesKey textAttributesKey = getScopeTextAttributeKey(name);
+      TextAttributesKey textAttributesKey = ScopeAttributesUtil.getScopeTextAttributeKey(name);
       if (scheme.getAttributes(textAttributesKey) == null) {
         scheme.setAttributes(textAttributesKey, new TextAttributes());
       }
@@ -600,16 +606,12 @@
     }
   }
 
-  public static TextAttributesKey getScopeTextAttributeKey(final String scope) {
-    return TextAttributesKey.find("SCOPE_KEY_" + scope);
-  }
-
-  private static void addEditorSettingDescription(ArrayList<EditorSchemeAttributeDescriptor> array,
-                                                                     String name,
-                                                                     String group,
-                                                                     ColorKey backgroundKey,
-                                                                     ColorKey foregroundKey,
-                                                                     EditorColorsScheme scheme) {
+  private static void addEditorSettingDescription(@NotNull List<EditorSchemeAttributeDescriptor> array,
+                                                  String name,
+                                                  String group,
+                                                  @Nullable ColorKey backgroundKey,
+                                                  @Nullable ColorKey foregroundKey,
+                                                  EditorColorsScheme scheme) {
     String type = null;
     if (foregroundKey != null) {
       type = foregroundKey.getExternalName();
@@ -623,8 +625,11 @@
     array.add(descr);
   }
 
-  private static void addSchemedDescription(ArrayList<EditorSchemeAttributeDescriptor> array, String name, String group, TextAttributesKey key,
-                                            MyColorScheme scheme,
+  private static void addSchemedDescription(@NotNull List<EditorSchemeAttributeDescriptor> array,
+                                            String name,
+                                            String group,
+                                            @NotNull TextAttributesKey key,
+                                            @NotNull MyColorScheme scheme,
                                             Icon icon,
                                             String toolTip) {
     ColorAndFontDescription descr = new SchemeTextAttributesDescription(name, group, key, scheme, icon, toolTip);
@@ -757,12 +762,12 @@
 
 
   private static class SchemeTextAttributesDescription extends TextAttributesDescription {
-    private final TextAttributes myAttributesToApply;
-    private final TextAttributesKey key;
+    @NotNull private final TextAttributes myAttributesToApply;
+    @NotNull private final TextAttributesKey key;
     private TextAttributes myFallbackAttributes;
     private Pair<ColorSettingsPage,AttributesDescriptor> myBaseAttributeDescriptor;
 
-    private SchemeTextAttributesDescription(String name, String group, TextAttributesKey key, MyColorScheme  scheme, Icon icon,
+    private SchemeTextAttributesDescription(String name, String group, @NotNull TextAttributesKey key, @NotNull MyColorScheme  scheme, Icon icon,
                                            String toolTip) {
       super(name, group,
             getInitialAttributes(scheme, key).clone(),
@@ -783,7 +788,7 @@
 
 
     @NotNull
-    private static TextAttributes getInitialAttributes(MyColorScheme scheme, TextAttributesKey key) {
+    private static TextAttributes getInitialAttributes(@NotNull MyColorScheme scheme, @NotNull TextAttributesKey key) {
       TextAttributes attributes = scheme.getAttributes(key);
       TextAttributesKey fallbackKey = key.getFallbackAttributeKey();
       if (fallbackKey != null && !scheme.containsKey(key)) {
@@ -798,9 +803,7 @@
     @Override
     public void apply(EditorColorsScheme scheme) {
       if (scheme == null) scheme = getScheme();
-      if (myAttributesToApply != null) {
-        scheme.setAttributes(key, getTextAttributes());
-      }
+      scheme.setAttributes(key, getTextAttributes());
     }
 
     @Override
@@ -900,6 +903,7 @@
     public void setExternalEffectType(EffectType type) {
     }
 
+    @NotNull
     @Override
     public EffectType getExternalEffectType() {
       return EffectType.LINE_UNDERSCORE;
@@ -995,7 +999,7 @@
     private String                            myName;
     private boolean myIsNew = false;
 
-    private MyColorScheme(EditorColorsScheme parentScheme) {
+    private MyColorScheme(@NotNull EditorColorsScheme parentScheme) {
       super(parentScheme, DefaultColorSchemesManager.getInstance());
       parentScheme.getFontPreferences().copyTo(getFontPreferences());
       setLineSpacing(parentScheme.getLineSpacing());
@@ -1052,21 +1056,19 @@
     private boolean isFontModified() {
       if (!getFontPreferences().equals(myParentScheme.getFontPreferences())) return true;
       if (getLineSpacing() != myParentScheme.getLineSpacing()) return true;
-      if (getQuickDocFontSize() != myParentScheme.getQuickDocFontSize()) return true;
-      return false;
+      return getQuickDocFontSize() != myParentScheme.getQuickDocFontSize();
     }
 
     private boolean isConsoleFontModified() {
       if (!getConsoleFontPreferences().equals(myParentScheme.getConsoleFontPreferences())) return true;
-      if (getConsoleLineSpacing() != myParentScheme.getConsoleLineSpacing()) return true;
-      return false;
+      return getConsoleLineSpacing() != myParentScheme.getConsoleLineSpacing();
     }
 
     public void apply() {
       apply(myParentScheme);
     }
 
-    public void apply(EditorColorsScheme scheme) {
+    public void apply(@NotNull EditorColorsScheme scheme) {
       scheme.setFontPreferences(getFontPreferences());
       scheme.setLineSpacing(myLineSpacing);
       scheme.setQuickDocFontSize(getQuickDocFontSize());
@@ -1095,6 +1097,7 @@
       return myIsNew;
     }
 
+    @NotNull
     @Override
     public String toString() {
       return "temporary scheme for " + myName;
@@ -1114,7 +1117,7 @@
   }
 
   @Nullable
-  public InnerSearchableConfigurable findSubConfigurable(final Class pageClass) {
+  public InnerSearchableConfigurable findSubConfigurable(@NotNull final Class pageClass) {
     if (mySubPanelFactories == null) {
       buildConfigurables();
     }
@@ -1142,12 +1145,13 @@
   private class InnerSearchableConfigurable implements SearchableConfigurable, OptionsContainingConfigurable, NoScroll {
     private NewColorAndFontPanel mySubPanel;
     private boolean mySubInitInvoked = false;
-    private final ColorAndFontPanelFactory myFactory;
+    @NotNull private final ColorAndFontPanelFactory myFactory;
 
     private InnerSearchableConfigurable(@NotNull ColorAndFontPanelFactory factory) {
       myFactory = factory;
     }
 
+    @NotNull
     @Override
     @Nls
     public String getDisplayName() {
@@ -1255,11 +1259,13 @@
       return createPanel().showOption(option);
     }
 
+    @NotNull
     @Override
     public Set<String> processListOptions() {
       return createPanel().processListOptions();
     }
 
+    @NotNull
     @NonNls
     @Override
     public String toString() {
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ScopeAttributesUtil.java b/platform/lang-impl/src/com/intellij/application/options/colors/ScopeAttributesUtil.java
new file mode 100644
index 0000000..4466f68
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ScopeAttributesUtil.java
@@ -0,0 +1,26 @@
+/*
+ * 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.colors;
+
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import org.jetbrains.annotations.NotNull;
+
+public class ScopeAttributesUtil {
+  @NotNull
+  public static TextAttributesKey getScopeTextAttributeKey(@NotNull String scope) {
+    return TextAttributesKey.find("SCOPE_KEY_" + scope);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
index f788b04..7e9b614 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
@@ -49,23 +49,20 @@
     final VirtualFile file = psiFile.getVirtualFile();
     final Project project = psiFile.getProject();
 
-    final Editor editor =
-      psiFile.isWritable() ? null : FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file), true);
-    if (!ReadonlyStatusHandler.ensureFilesWritable(project, file)) {
-      ApplicationManager.getApplication().invokeLater(new Runnable() {
-        @Override
-        public void run() {
-          if (editor != null && editor.getComponent().isDisplayable()) {
-            HintManager.getInstance()
-              .showErrorHint(editor, CodeInsightBundle.message("error.hint.file.is.readonly", file.getPresentableUrl()));
-          }
-        }
-      });
-
-      return false;
+    if (ReadonlyStatusHandler.ensureFilesWritable(project, file)) {
+      return true;
     }
+    ApplicationManager.getApplication().invokeLater(new Runnable() {
+      @Override
+      public void run() {
+        final Editor editor = FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file), true);
+        if (editor != null && editor.getComponent().isDisplayable()) {
+          HintManager.getInstance().showErrorHint(editor, CodeInsightBundle.message("error.hint.file.is.readonly", file.getPresentableUrl()));
+        }
+      }
+    }, project.getDisposed());
 
-    return true;
+    return false;
   }
 
   @Override
@@ -85,8 +82,9 @@
     Set<VirtualFile> files = new THashSet<VirtualFile>();
     Project project = null;
     for (PsiElement element : elements) {
+      if (element == null) continue;
       PsiFile file = element.getContainingFile();
-      if (file == null) continue;
+      if (file == null || !file.isPhysical()) continue;
       project = file.getProject();
       VirtualFile virtualFile = file.getVirtualFile();
       if (virtualFile == null) continue;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
index 5185944..76416e7 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
@@ -226,7 +226,7 @@
     ArrayList<LookupElement> result = new ArrayList<LookupElement>(model);
     if (result.size() > 1) {
       LookupElement first = result.get(0);
-      if (isLiveTemplate(first) && isPrefixItem(lookup, first, true)) {
+      if (isLiveTemplate(first) && isPrefixItem(lookup, first, true) && CompletionServiceImpl.isStartMatch(result.get(1), lookup)) {
         ContainerUtil.swapElements(result, 0, 1);
       }
     }
@@ -351,10 +351,14 @@
     String selectedText = lookup.getEditor().getSelectionModel().getSelectedText();
     for (int i = 0; i < items.size(); i++) {
       LookupElement item = items.get(i);
-      if (isAlphaSorted() && isPrefixItem(lookup, item, true) && !isLiveTemplate(item) ||
+      boolean isTemplate = isLiveTemplate(item);
+      if (isAlphaSorted() && isPrefixItem(lookup, item, true) && !isTemplate ||
           item.getLookupString().equals(selectedText)) {
         return i;
       }
+      if (i == 0 && isTemplate && items.size() > 1 && !CompletionServiceImpl.isStartMatch(items.get(1), lookup)) {
+        return 0;
+      }
     }
 
     return Math.max(0, ContainerUtil.indexOfIdentity(items, mostRelevant));
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 23f337b..1062bd4 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
@@ -57,15 +57,12 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiFileSystemItem;
 import com.intellij.psi.impl.PsiDocumentManagerImpl;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
 import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
-import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.Alarm;
 import com.intellij.util.CommonProcessors;
 import com.intellij.util.Processor;
 import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.UIUtil;
 import gnu.trove.THashMap;
 import gnu.trove.THashSet;
@@ -146,14 +143,6 @@
     assert !myInitialized : "Double Initializing";
     Disposer.register(myProject, new StatusBarUpdater(myProject));
 
-    ApplicationManager.getApplication().invokeLater(new Runnable() {
-      @Override
-      public void run() {
-        reloadScopes(dependencyValidationManager, namedScopeManager);
-      }
-    }, project.getDisposed());
-
-
     myInitialized = true;
     myDisposed = false;
     myFileStatusMap.markAllFilesDirty();
@@ -261,6 +250,7 @@
           if (callbackWhileWaiting != null) {
             callbackWhileWaiting.run();
           }
+          myPassExecutorService.waitFor(50);
           UIUtil.dispatchAllInvocationEvents();
           Throwable savedException = PassExecutorService.getSavedException(progress);
           if (savedException != null) throw savedException;
@@ -323,31 +313,6 @@
     TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markup, myProject, document, psiFile);
   }
 
-  private final List<Pair<NamedScope, NamedScopesHolder>> myScopes = ContainerUtil.createLockFreeCopyOnWriteList();
-
-  void reloadScopes(@NotNull DependencyValidationManager dependencyValidationManager, @NotNull NamedScopeManager namedScopeManager) {
-    ApplicationManager.getApplication().assertIsDispatchThread();
-    List<Pair<NamedScope, NamedScopesHolder>> scopeList = new ArrayList<Pair<NamedScope, NamedScopesHolder>>();
-    addScopesToList(scopeList, namedScopeManager);
-    addScopesToList(scopeList, dependencyValidationManager);
-    myScopes.clear();
-    myScopes.addAll(scopeList);
-    dependencyValidationManager.reloadRules();
-  }
-
-  private static void addScopesToList(@NotNull final List<Pair<NamedScope, NamedScopesHolder>> scopeList,
-                                      @NotNull final NamedScopesHolder holder) {
-    NamedScope[] scopes = holder.getScopes();
-    for (NamedScope scope : scopes) {
-      scopeList.add(Pair.create(scope, holder));
-    }
-  }
-
-  @NotNull
-  public List<Pair<NamedScope, NamedScopesHolder>> getScopeBasedHighlightingCachedScopes() {
-    return myScopes;
-  }
-
   @Override
   public void settingsChanged() {
     DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
index 95dc71a..dc09785 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
@@ -71,11 +71,9 @@
 import com.intellij.psi.impl.PsiDocumentManagerImpl;
 import com.intellij.psi.impl.PsiManagerEx;
 import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
-import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
 import com.intellij.util.messages.MessageBus;
 import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.ui.UIUtil;
-import gnu.trove.THashSet;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -85,7 +83,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 
 
 /**
@@ -328,21 +325,6 @@
 
     ((EditorEventMulticasterEx)eventMulticaster).addErrorStripeListener(new ErrorStripeHandler(myProject), this);
 
-    Set<NamedScopesHolder> holders = new THashSet<NamedScopesHolder>(Arrays.asList(NamedScopesHolder.getAllNamedScopeHolders(project)));
-    // to ensure initialization dependency
-    holders.add(namedScopeManager);
-    holders.add(dependencyValidationManager);
-
-    NamedScopesHolder.ScopeListener scopeListener = new NamedScopesHolder.ScopeListener() {
-      @Override
-      public void scopesChanged() {
-        myDaemonCodeAnalyzer.reloadScopes(dependencyValidationManager, namedScopeManager);
-      }
-    };
-    for (NamedScopesHolder holder : holders) {
-      holder.addScopeListener(scopeListener);
-    }
-
     ModalityStateListener modalityStateListener = new ModalityStateListener() {
       @Override
       public void beforeModalityStateChanged(boolean entering) {
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 f2825cb..f704286 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
@@ -102,7 +102,7 @@
   private final List<HighlightInfo> myHighlights = new ArrayList<HighlightInfo>();
 
   protected volatile boolean myHasErrorElement;
-  private boolean myErrorFound;
+  private volatile boolean myErrorFound;
   private static final Comparator<HighlightVisitor> VISITOR_ORDER_COMPARATOR = new Comparator<HighlightVisitor>() {
     @Override
     public int compare(final HighlightVisitor o1, final HighlightVisitor o2) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java
index 6b8cfb5..f9488aa 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java
@@ -47,12 +47,10 @@
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 import java.util.*;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
+import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -519,4 +517,21 @@
   public static Throwable getSavedException(DaemonProgressIndicator indicator) {
     return indicator.getUserData(THROWABLE_KEY);
   }
+
+  @TestOnly
+  public void waitFor(int millis) throws Exception {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    try {
+      for (Job<Void> job : mySubmittedPasses.values()) {
+        if (!job.isDone()) {
+          for (FutureTask task : ((JobImpl)job).getTasks()) {
+            task.get(millis, TimeUnit.MILLISECONDS);
+          }
+        }
+      }
+    }
+    catch (TimeoutException ignored) {
+
+    }
+  }
 }
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 56f9745..3890dd4 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
@@ -22,26 +22,30 @@
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class QuickFixActionRegistrarImpl implements QuickFixActionRegistrar {
   private final HighlightInfo myInfo;
 
-  public QuickFixActionRegistrarImpl(HighlightInfo info) {
+  public QuickFixActionRegistrarImpl(@Nullable HighlightInfo info) {
     myInfo = info;
   }
 
   @Override
-  public void register(IntentionAction action) {
+  public void register(@NotNull IntentionAction action) {
     QuickFixAction.registerQuickFixAction(myInfo, action);
   }
 
   @Override
-  public void register(TextRange fixRange, IntentionAction action, HighlightDisplayKey key) {
+  public void register(@NotNull TextRange fixRange, @NotNull IntentionAction action, HighlightDisplayKey key) {
     QuickFixAction.registerQuickFixAction(myInfo, fixRange, action, key);
   }
 
   @Override
-  public void unregister(Condition<IntentionAction> condition) {
-    QuickFixAction.unregisterQuickFixAction(myInfo, condition);
+  public void unregister(@NotNull Condition<IntentionAction> condition) {
+    if (myInfo != null) {
+      QuickFixAction.unregisterQuickFixAction(myInfo, condition);
+    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameFileFix.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameFileFix.java
index e7ff019..6b58579 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameFileFix.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RenameFileFix.java
@@ -20,7 +20,6 @@
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.CodeInsightBundle;
-import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInspection.LocalQuickFix;
 import com.intellij.codeInspection.ProblemDescriptor;
@@ -29,7 +28,6 @@
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.ex.MessagesEx;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -74,7 +72,7 @@
       new WriteCommandAction(project) {
         @Override
         protected void run(Result result) throws Throwable {
-          invoke(project, FileEditorManager.getInstance(project).getSelectedTextEditor(), file);
+          invoke(project, null, file);
         }
       }.execute();
     }
@@ -100,12 +98,9 @@
     try {
       vFile.rename(file.getManager(), myNewFileName);
     }
-    catch(IOException e){
+    catch (IOException e) {
       MessagesEx.error(project, e.getMessage()).showLater();
     }
-    if (editor != null) {
-      DaemonCodeAnalyzer.getInstance(project).updateVisibleHighlighters(editor);
-    }
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java
index 1c81a50..0371eb1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java
@@ -34,6 +34,7 @@
 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.ui.content.*;
+import com.intellij.util.ui.UIUtil;
 import com.intellij.util.ui.update.Activatable;
 import com.intellij.util.ui.update.UiNotifyConnector;
 import org.jetbrains.annotations.NotNull;
@@ -169,7 +170,12 @@
           }
         };
 
-        IdeEventQueue.getInstance().addIdleListener(myAutoUpdateRequest, 500);
+        UIUtil.invokeLaterIfNeeded(new Runnable() {
+          @Override
+          public void run() {
+            IdeEventQueue.getInstance().addIdleListener(myAutoUpdateRequest, 500);
+          }
+        });
       }
     }
     else {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/actions/GenerateAction.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/actions/GenerateAction.java
index 81e1619..d909be6 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/actions/GenerateAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/actions/GenerateAction.java
@@ -24,6 +24,8 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.ui.popup.ListPopup;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class GenerateAction extends DumbAwareAction implements PreloadableAction {
   @Override
@@ -33,7 +35,7 @@
     final ListPopup popup =
       JBPopupFactory.getInstance().createActionGroupPopup(
           CodeInsightBundle.message("generate.list.popup.title"),
-                                                          getGroup(),
+                                                          wrapGroup(getGroup(), dataContext),
                                                           dataContext,
                                                           JBPopupFactory.ActionSelectionAid.SPEEDSEARCH,
                                                           false);
@@ -65,8 +67,56 @@
     return (DefaultActionGroup)ActionManager.getInstance().getAction(IdeActions.GROUP_GENERATE);
   }
 
+  private static DefaultActionGroup wrapGroup(DefaultActionGroup actionGroup, DataContext dataContext) {
+    final DefaultActionGroup copy = new DefaultActionGroup();
+    for (final AnAction action : actionGroup.getChildren(null)) {
+      if (action instanceof GenerateActionPopupTemplateInjector) {
+        final AnAction editTemplateAction = ((GenerateActionPopupTemplateInjector)action).createEditTemplateAction(dataContext);
+        if (editTemplateAction != null) {
+          copy.add(new GenerateWrappingGroup(action, editTemplateAction));
+          continue;
+        }
+      }
+      if (action instanceof DefaultActionGroup) {
+        copy.add(wrapGroup((DefaultActionGroup)action, dataContext));
+      } else {
+        copy.add(action);
+      }
+    }
+    return copy;
+  }
+
   @Override
   public void preload() {
     ((ActionManagerImpl) ActionManager.getInstance()).preloadActionGroup(IdeActions.GROUP_GENERATE);
   }
+
+  private static class GenerateWrappingGroup extends ActionGroup {
+
+    private final AnAction myAction;
+    private final AnAction myEditTemplateAction;
+
+    public GenerateWrappingGroup(AnAction action, AnAction editTemplateAction) {
+      myAction = action;
+      myEditTemplateAction = editTemplateAction;
+      copyFrom(action);
+      setPopup(true);
+    }
+
+    @Override
+    public boolean canBePerformed(DataContext context) {
+      return true;
+    }
+
+    @NotNull
+    @Override
+    public AnAction[] getChildren(@Nullable AnActionEvent e) {
+      return new AnAction[] {myEditTemplateAction};
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      myAction.actionPerformed(e);
+    }
+  }
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
index ab4cc84..2e1d2a5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
@@ -47,7 +47,6 @@
   private final OneElementComponent[] myPanels;
 
   private static final Color BACKGROUND_COLOR = HintUtil.INFORMATION_COLOR;
-  private static final Color FOREGROUND_COLOR = JBColor.foreground();
   private static final Color HIGHLIGHTED_BORDER_COLOR = new JBColor(new Color(231, 254, 234), Gray._100);
   private final Font NORMAL_FONT;
   private final Font BOLD_FONT;
@@ -338,7 +337,7 @@
       myLabel.setBackground(background);
       setBackground(background);
 
-      myLabel.setForeground(FOREGROUND_COLOR);
+      myLabel.setForeground(JBColor.foreground());
 
       if (flagsMap.isEmpty()) {
         myLabel.setText(XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(text)));
@@ -347,6 +346,11 @@
         String labelText = buildLabelText(text, flagsMap);
         myLabel.setText(labelText);
       }
+
+      //IDEA-95904 Darcula parameter info pop-up colors hard to read
+      if (UIUtil.isUnderDarcula()) {
+        myLabel.setText(myLabel.getText().replace("<b>", "<b color=ffC800>"));
+      }
     }
     private String buildLabelText(@NotNull final String text, @NotNull final Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap) {
       final StringBuilder labelText = new StringBuilder(text);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
index 0d8a17c..8a813b8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
@@ -22,12 +22,15 @@
 import com.intellij.codeInsight.lookup.RealLookupElementPresentation;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.codeStyle.MinusculeMatcher;
 import com.intellij.psi.codeStyle.NameUtil;
 import com.intellij.ui.*;
+import com.intellij.ui.components.JBList;
 import com.intellij.ui.speedSearch.SpeedSearchUtil;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.FList;
 import com.intellij.util.ui.EmptyIcon;
 import com.intellij.util.ui.GraphicsUtil;
@@ -39,6 +42,7 @@
 import java.awt.*;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * @author peter
@@ -87,11 +91,9 @@
 
     myTailComponent = new MySimpleColoredComponent();
     myTailComponent.setIpad(new Insets(0, 0, 0, 0));
-    myTailComponent.setFont(myNormalFont);
 
     myTypeLabel = new MySimpleColoredComponent();
     myTypeLabel.setIpad(new Insets(0, 0, 0, 0));
-    myTypeLabel.setFont(myNormalFont);
 
     myPanel = new LookupPanel();
     myPanel.add(myNameComponent, BorderLayout.WEST);
@@ -127,7 +129,11 @@
                              isSelected ? SELECTED_BACKGROUND_COLOR : BACKGROUND_COLOR;
 
     int allowedWidth = list.getWidth() - AFTER_TAIL - AFTER_TYPE - getIconIndent();
-    final LookupElementPresentation presentation = new RealLookupElementPresentation(isSelected ? getMaxWidth() : allowedWidth, myNormalMetrics, myBoldMetrics, myLookup);
+
+    FontMetrics normalMetrics = getRealFontMetrics(item, false);
+    FontMetrics boldMetrics = getRealFontMetrics(item, true);
+    final LookupElementPresentation presentation = new RealLookupElementPresentation(isSelected ? getMaxWidth() : allowedWidth, 
+                                                                                     normalMetrics, boldMetrics, myLookup);
     if (item.isValid()) {
       item.renderElement(presentation);
     } else {
@@ -140,15 +146,20 @@
     myNameComponent.setBackground(background);
     allowedWidth -= setItemTextLabel(item, new JBColor(isSelected ? SELECTED_FOREGROUND_COLOR : presentation.getItemTextForeground(), foreground), isSelected, presentation, allowedWidth);
 
+    Font customFont = myLookup.getCustomFont(item, false);
+    myTailComponent.setFont(customFont != null ? customFont : myNormalFont);
+    myTypeLabel.setFont(customFont != null ? customFont : myNormalFont);
+
     myTypeLabel.clear();
     if (allowedWidth > 0) {
-      allowedWidth -= setTypeTextLabel(item, background, foreground, presentation, isSelected ? getMaxWidth() : allowedWidth, isSelected, nonFocusedSelection);
+      allowedWidth -= setTypeTextLabel(item, background, foreground, presentation, isSelected ? getMaxWidth() : allowedWidth, isSelected, nonFocusedSelection, normalMetrics);
     }
 
     myTailComponent.clear();
     myTailComponent.setBackground(background);
     if (isSelected || allowedWidth >= 0) {
-      setTailTextLabel(isSelected, presentation, foreground, isSelected ? getMaxWidth() : allowedWidth, nonFocusedSelection);
+      setTailTextLabel(isSelected, presentation, foreground, isSelected ? getMaxWidth() : allowedWidth, nonFocusedSelection,
+                       normalMetrics);
     }
 
     if (mySelected.containsKey(index)) {
@@ -162,17 +173,20 @@
                      myTailComponent.getPreferredSize().getWidth() +
                      myTypeLabel.getPreferredSize().getWidth();
 
-    myPanel.removeAll();
-    if (isSelected && w > list.getWidth()) {
-      myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.X_AXIS));
-      myPanel.add(myNameComponent);
-      myPanel.add(myTailComponent);
-      myPanel.add(myTypeLabel);
-    } else {
-      myPanel.setLayout(new BorderLayout());
-      myPanel.add(myNameComponent, BorderLayout.WEST);
-      myPanel.add(myTailComponent, BorderLayout.CENTER);
-      myPanel.add(myTypeLabel, BorderLayout.EAST);
+    boolean useBoxLayout = isSelected && w > list.getWidth() && ((JBList)list).getExpandableItemsHandler().isEnabled();
+    if (useBoxLayout != myPanel.getLayout() instanceof BoxLayout) {
+      myPanel.removeAll();
+      if (useBoxLayout) {
+        myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.X_AXIS));
+        myPanel.add(myNameComponent);
+        myPanel.add(myTailComponent);
+        myPanel.add(myTypeLabel);
+      } else {
+        myPanel.setLayout(new BorderLayout());
+        myPanel.add(myNameComponent, BorderLayout.WEST);
+        myPanel.add(myTailComponent, BorderLayout.CENTER);
+        myPanel.add(myTypeLabel, BorderLayout.EAST);
+      }
     }
 
     return myPanel;
@@ -191,7 +205,11 @@
     return myMaxWidth;
   }
 
-  private void setTailTextLabel(boolean isSelected, LookupElementPresentation presentation, Color foreground, int allowedWidth, boolean nonFocusedSelection) {
+  private void setTailTextLabel(boolean isSelected,
+                                LookupElementPresentation presentation,
+                                Color foreground,
+                                int allowedWidth,
+                                boolean nonFocusedSelection, FontMetrics fontMetrics) {
     int style = getStyle(false, presentation.isStrikeout(), false);
 
     for (LookupElementPresentation.TextFragment fragment : presentation.getTailFragments()) {
@@ -199,9 +217,9 @@
         return;
       }
 
-      String trimmed = trimLabelText(fragment.text, allowedWidth, myNormalMetrics);
+      String trimmed = trimLabelText(fragment.text, allowedWidth, fontMetrics);
       myTailComponent.append(trimmed, new SimpleTextAttributes(style, getTailTextColor(isSelected, fragment, foreground, nonFocusedSelection)));
-      allowedWidth -= RealLookupElementPresentation.getStringWidth(trimmed, myNormalMetrics);
+      allowedWidth -= RealLookupElementPresentation.getStringWidth(trimmed, fontMetrics);
     }
   }
 
@@ -269,11 +287,11 @@
   private int setItemTextLabel(LookupElement item, final Color foreground, final boolean selected, LookupElementPresentation presentation, int allowedWidth) {
     boolean bold = presentation.isItemTextBold();
 
-    myNameComponent.setFont(bold ? myBoldFont : myNormalFont);
-
+    Font customItemFont = myLookup.getCustomFont(item, bold);
+    myNameComponent.setFont(customItemFont != null ? customItemFont : bold ? myBoldFont : myNormalFont);
     int style = getStyle(bold, presentation.isStrikeout(), presentation.isItemTextUnderlined());
 
-    final FontMetrics metrics = bold ? myBoldMetrics : myNormalMetrics;
+    final FontMetrics metrics = getRealFontMetrics(item, bold);
     final String name = trimLabelText(presentation.getItemText(), allowedWidth, metrics);
     int used = RealLookupElementPresentation.getStringWidth(name, metrics);
 
@@ -281,6 +299,15 @@
     return used;
   }
 
+  private FontMetrics getRealFontMetrics(LookupElement item, boolean bold) {
+    Font customFont = myLookup.getCustomFont(item, bold);
+    if (customFont != null) {
+      return myLookup.getEditor().getComponent().getFontMetrics(customFont);
+    }
+
+    return bold ? myBoldMetrics : myNormalMetrics;
+  }
+
   @SimpleTextAttributes.StyleAttributeConstant
   private static int getStyle(boolean bold, boolean strikeout, boolean underlined) {
     int style = bold ? SimpleTextAttributes.STYLE_BOLD : SimpleTextAttributes.STYLE_PLAIN;
@@ -323,11 +350,11 @@
                                Color foreground,
                                final LookupElementPresentation presentation,
                                int allowedWidth,
-                               boolean selected, boolean nonFocusedSelection) {
+                               boolean selected, boolean nonFocusedSelection, FontMetrics normalMetrics) {
     final String givenText = presentation.getTypeText();
-    final String labelText = trimLabelText(StringUtil.isEmpty(givenText) ? "" : " " + givenText, allowedWidth, myNormalMetrics);
+    final String labelText = trimLabelText(StringUtil.isEmpty(givenText) ? "" : " " + givenText, allowedWidth, normalMetrics);
 
-    int used = RealLookupElementPresentation.getStringWidth(labelText, myNormalMetrics);
+    int used = RealLookupElementPresentation.getStringWidth(labelText, normalMetrics);
 
     final Icon icon = presentation.getTypeIcon();
     if (icon != null) {
@@ -346,7 +373,7 @@
         sampleBackground = proposedBackground;
       }
       myTypeLabel.append("  ");
-      used += myNormalMetrics.stringWidth("WW");
+      used += normalMetrics.stringWidth("WW");
     } else {
       myTypeLabel.append(labelText);
     }
@@ -371,13 +398,37 @@
     return icon;
   }
 
-  public int updateMaximumWidth(final LookupElementPresentation p) {
+  @Nullable
+  Font getFontAbleToDisplay(LookupElementPresentation p) {
+    String sampleString = p.getItemText() + p.getTailText() + p.getTypeText();
+
+    // assume a single font can display all lookup item chars
+    Set<Font> fonts = ContainerUtil.newHashSet();
+    for (int i = 0; i < sampleString.length(); i++) {
+      fonts.add(EditorUtil.fontForChar(sampleString.charAt(i), Font.PLAIN, myLookup.getEditor()).getFont());
+    }
+
+    eachFont: for (Font font : fonts) {
+      if (font.equals(myNormalFont)) continue;
+      
+      for (int i = 0; i < sampleString.length(); i++) {
+        if (!font.canDisplay(sampleString.charAt(i))) {
+          continue eachFont;
+        }
+      }
+      return font;
+    }
+    return null;
+  }
+
+
+  int updateMaximumWidth(final LookupElementPresentation p, LookupElement item) {
     final Icon icon = p.getIcon();
     if (icon != null && (icon.getIconWidth() > myEmptyIcon.getIconWidth() || icon.getIconHeight() > myEmptyIcon.getIconHeight())) {
       myEmptyIcon = new EmptyIcon(Math.max(icon.getIconWidth(), myEmptyIcon.getIconWidth()), Math.max(icon.getIconHeight(), myEmptyIcon.getIconHeight()));
     }
 
-    return RealLookupElementPresentation.calculateWidth(p, myNormalMetrics, myBoldMetrics) + AFTER_TAIL + AFTER_TYPE;
+    return RealLookupElementPresentation.calculateWidth(p, getRealFontMetrics(item, false), getRealFontMetrics(item, true)) + AFTER_TAIL + AFTER_TYPE;
   }
 
   public int getIconIndent() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 3f22987..7e09225 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -17,6 +17,7 @@
 package com.intellij.codeInsight.lookup.impl;
 
 import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.FileModificationService;
 import com.intellij.codeInsight.completion.CodeCompletionFeatures;
 import com.intellij.codeInsight.completion.CompletionLookupArranger;
 import com.intellij.codeInsight.completion.PrefixMatcher;
@@ -38,7 +39,6 @@
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.application.WriteAction;
 import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.event.*;
@@ -68,6 +68,7 @@
 import com.intellij.util.CollectConsumer;
 import com.intellij.util.PlatformIcons;
 import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.containers.ConcurrentWeakHashMap;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.AbstractLayoutManager;
 import com.intellij.util.ui.AsyncProcessIcon;
@@ -139,6 +140,8 @@
   private LookupArranger myPresentableArranger;
   private final Map<LookupElement, PrefixMatcher> myMatchers = new ConcurrentHashMap<LookupElement, PrefixMatcher>(
     ContainerUtil.<LookupElement>identityStrategy());
+  private final Map<LookupElement, Font> myCustomFonts = new ConcurrentWeakHashMap<LookupElement, Font>(
+    ContainerUtil.<LookupElement>identityStrategy());
   private LookupHint myElementHint = null;
   private final Alarm myHintAlarm = new Alarm();
   private final JLabel mySortingLabel = new JLabel();
@@ -337,11 +340,21 @@
 
   public LookupElementPresentation updateLookupWidth(LookupElement item) {
     final LookupElementPresentation presentation = renderItemApproximately(item);
-    int maxWidth = myCellRenderer.updateMaximumWidth(presentation);
+    final Font customFont = myCellRenderer.getFontAbleToDisplay(presentation);
+    if (customFont != null) {
+      myCustomFonts.put(item, customFont);
+    }
+    int maxWidth = myCellRenderer.updateMaximumWidth(presentation, item);
     myLookupTextWidth = Math.max(maxWidth, myLookupTextWidth);
     return presentation;
   }
 
+  @Nullable
+  public Font getCustomFont(LookupElement item, boolean bold) {
+    Font font = myCustomFonts.get(item);
+    return font == null ? null : bold ? font.deriveFont(Font.BOLD) : font;
+  }
+
   public void requestResize() {
     ApplicationManager.getApplication().assertIsDispatchThread();
     myResizePending = true;
@@ -570,7 +583,7 @@
     }
     Rectangle candidate = new Rectangle(location, dim);
     ScreenUtil.cropRectangleToFitTheScreen(candidate);
-    
+
     SwingUtilities.convertPointFromScreen(location, rootPane.getLayeredPane());
     return new Rectangle(location.x, location.y, dim.width, candidate.height);
   }
@@ -596,7 +609,7 @@
     }
 
     final PsiFile file = getPsiFile();
-    boolean writableOk = file == null || WriteCommandAction.ensureFilesWritable(myProject, Arrays.asList(file));
+    boolean writableOk = file == null || FileModificationService.getInstance().prepareFileForWrite(file);
     if (myDisposed) { // ensureFilesWritable could close us by showing a dialog
       return;
     }
@@ -676,14 +689,14 @@
       EditorModificationUtil.deleteSelectedText(myEditor);
       final int caretOffset = myEditor.getCaretModel().getOffset();
       int lookupStart = caretOffset - prefix;
-  
+
       int len = document.getTextLength();
       LOG.assertTrue(lookupStart >= 0 && lookupStart <= len,
                      "ls: " + lookupStart + " caret: " + caretOffset + " prefix:" + prefix + " doc: " + len);
       LOG.assertTrue(caretOffset >= 0 && caretOffset <= len, "co: " + caretOffset + " doc: " + len);
 
       document.replaceString(lookupStart, caretOffset, lookupString);
-  
+
       int offset = lookupStart + lookupString.length();
       myEditor.getCaretModel().moveToOffset(offset);
       myEditor.getSelectionModel().removeSelection();
@@ -697,7 +710,7 @@
     if (item.isCaseSensitive()) {
       return lookupString;
     }
-    
+
     final String prefix = itemPattern(item);
     final int length = prefix.length();
     if (length == 0 || !StringUtil.startsWithIgnoreCase(lookupString, prefix)) return lookupString;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
index 904c3da..eea5a21 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.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.
@@ -63,6 +63,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.startup.StartupManager;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
@@ -100,6 +101,8 @@
 
 public class CtrlMouseHandler extends AbstractProjectComponent {
   private static final AbstractDocumentationTooltipAction[] ourTooltipActions = {new ShowQuickDocAtPinnedWindowFromTooltipAction()};
+  private static Key<Boolean> ourDebuggerHighlighterKey;
+  private static Key<Boolean> ourXDebuggerHighlighterKey;
   private final EditorColorsManager myEditorColorsManager;
 
   private       HighlightersSet myHighlighter;
@@ -894,9 +897,11 @@
     List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
     TextAttributes attributes = myEditorColorsManager.getGlobalScheme().getAttributes(EditorColors.REFERENCE_HYPERLINK_COLOR);
     for (TextRange range : info.getRanges()) {
+      TextAttributes attr = patchAttributesColor(attributes, range, editor, getOrInitDebuggerHighlighterKey());
+      attr = patchAttributesColor(attributes, range, editor, getOrInitXDebuggerHighlighterKey());
       final RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(range.getStartOffset(), range.getEndOffset(),
                                                                                        HighlighterLayer.SELECTION + 1,
-                                                                                       attributes,
+                                                                                       attr,
                                                                                        HighlighterTargetArea.EXACT_RANGE);
       highlighters.add(highlighter);
     }
@@ -904,6 +909,43 @@
     return new HighlightersSet(highlighters, editor, cursor, info);
   }
 
+
+  /**
+   * Patches attributes to be visible under debugger active line
+   */
+  @SuppressWarnings("UseJBColor")
+  private static TextAttributes patchAttributesColor(TextAttributes attributes, TextRange range, Editor editor, Key<Boolean> key) {
+    if (key != null) {
+      int line = editor.offsetToLogicalPosition(range.getStartOffset()).line;
+      for (RangeHighlighter highlighter : editor.getMarkupModel().getAllHighlighters()) {
+
+        Boolean hasKey = highlighter.getUserData(key);
+        if (hasKey != null && hasKey) {
+          if (editor.offsetToLogicalPosition(highlighter.getStartOffset()).line == line) {
+            TextAttributes clone = attributes.clone();
+            clone.setForegroundColor(Color.orange);
+            clone.setEffectColor(Color.orange);
+            return clone;
+          }
+        }
+      }
+    }
+    return attributes;
+  }
+
+  private static Key<Boolean> getOrInitDebuggerHighlighterKey() {
+    if (ourDebuggerHighlighterKey == null) {
+      ourDebuggerHighlighterKey = Key.findKeyByName("HIGHLIGHTER_USERDATA_KEY");
+    }
+    return ourDebuggerHighlighterKey;
+  }
+  private static Key<Boolean> getOrInitXDebuggerHighlighterKey() {
+    if (ourXDebuggerHighlighterKey == null) {
+      ourXDebuggerHighlighterKey = Key.findKeyByName("EXECUTION_POINT_HIGHLIGHTER_KEY");
+    }
+    return ourXDebuggerHighlighterKey;
+  }
+
   private class HighlightersSet {
     private final List<RangeHighlighter> myHighlighters;
     private final Editor myHighlighterView;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java
index e5c419d..07022bc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java
@@ -24,9 +24,7 @@
 import org.jetbrains.annotations.NotNull;
 
 public abstract class UnresolvedReferenceQuickFixProvider<T extends PsiReference> {
-
-  public static <T extends PsiReference> void registerReferenceFixes(T ref, QuickFixActionRegistrar registrar) {
-
+  public static <T extends PsiReference> void registerReferenceFixes(@NotNull T ref, @NotNull QuickFixActionRegistrar registrar) {
     final boolean dumb = DumbService.getInstance(ref.getElement().getProject()).isDumb();
     UnresolvedReferenceQuickFixProvider[] fixProviders = Extensions.getExtensions(EXTENSION_NAME);
     Class<? extends PsiReference> referenceClass = ref.getClass();
@@ -40,10 +38,9 @@
     }
   }
 
-  private static final ExtensionPointName<UnresolvedReferenceQuickFixProvider> EXTENSION_NAME =
-      ExtensionPointName.create("com.intellij.codeInsight.unresolvedReferenceQuickFixProvider");
+  private static final ExtensionPointName<UnresolvedReferenceQuickFixProvider> EXTENSION_NAME = ExtensionPointName.create("com.intellij.codeInsight.unresolvedReferenceQuickFixProvider");
 
-  public abstract void registerFixes(T ref, QuickFixActionRegistrar registrar);
+  public abstract void registerFixes(@NotNull T ref, @NotNull QuickFixActionRegistrar registrar);
 
   @NotNull
   public abstract Class<T> getReferenceClass();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
index dc9a918..6daa7bd3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
@@ -183,8 +183,7 @@
   @Nullable
   public TextResult getVariableValue(@NotNull String variableName) {
     if (variableName.equals(TemplateImpl.SELECTION)) {
-      final String selection = (String)getProperties().get(ExpressionContext.SELECTION);
-      return new TextResult(selection == null ? "" : selection);
+      return new TextResult(StringUtil.notNullize(getSelectionBeforeTemplate()));
     }
     if (variableName.equals(TemplateImpl.END)) {
       return new TextResult("");
@@ -207,6 +206,11 @@
   }
 
   @Nullable
+  private String getSelectionBeforeTemplate() {
+    return (String)getProperties().get(ExpressionContext.SELECTION);
+  }
+
+  @Nullable
   public TextRange getCurrentVariableRange() {
     int number = getCurrentSegmentNumber();
     if (number == -1) return null;
@@ -838,7 +842,8 @@
   }
 
   private void setFinalEditorState() {
-    int endSegmentNumber = myTemplate.getEndSegmentNumber();
+    int selectionSegment = myTemplate.getVariableSegmentNumber(TemplateImpl.SELECTION);
+    int endSegmentNumber = selectionSegment >= 0 && getSelectionBeforeTemplate() == null ? selectionSegment : myTemplate.getEndSegmentNumber();
     int offset = -1;
     if (endSegmentNumber >= 0) {
       offset = mySegments.getSegmentStart(endSegmentNumber);
@@ -846,11 +851,6 @@
     else {
       if (!myTemplate.isSelectionTemplate() && !myTemplate.isInline()) { //do not move caret to the end of range for selection templates
         offset = myTemplateRange.getEndOffset();
-      } else {
-        int selectionSegment = myTemplate.getVariableSegmentNumber(TemplateImpl.SELECTION);
-        if (selectionSegment >= 0 && mySegments.getSegmentStart(selectionSegment) == mySegments.getSegmentEnd(selectionSegment)) {
-          offset = mySegments.getSegmentStart(selectionSegment);
-        }
       }
     }
 
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
index 82eb306..7e7024a 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
@@ -77,7 +77,7 @@
     final Presentation presentation = event.getPresentation();
     final Project project = event.getData(PlatformDataKeys.PROJECT);
     presentation.setEnabled(project != null);
-    presentation.setVisible(ActionPlaces.MAIN_MENU.equals(event.getPlace()) && !PlatformUtils.isAppCode());
+    presentation.setVisible(ActionPlaces.MAIN_MENU.equals(event.getPlace()) && !PlatformUtils.isCidr());
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
index 74a162a..74e53ce 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
@@ -653,18 +653,21 @@
         myFoldingAlarm.cancelAllRequests();
         cancelHeavyAlarm();
       }
-      CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
-        @Override
-        public void run() {
-          document.setInBulkUpdate(true);
-          try {
-            document.deleteString(0, document.getTextLength());
+      final int documentTextLength = document.getTextLength();
+      if (documentTextLength > 0) {
+        CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+          @Override
+          public void run() {
+            document.setInBulkUpdate(true);
+            try {
+              document.deleteString(0, documentTextLength);
+            }
+            finally {
+              document.setInBulkUpdate(false);
+            }
           }
-          finally {
-            document.setInBulkUpdate(false);
-          }
-        }
-      }, null, DocCommandGroupId.noneGroupId(document));
+        }, null, DocCommandGroupId.noneGroupId(document));
+      }
     }
 
 
@@ -1164,7 +1167,11 @@
 
     @Override
     public void update(AnActionEvent e) {
-      final boolean enabled = e.getData(LangDataKeys.CONSOLE_VIEW) != null;
+      boolean enabled = e.getData(LangDataKeys.CONSOLE_VIEW) != null;
+      Editor editor = e.getData(PlatformDataKeys.EDITOR);
+      if (editor != null && editor.getDocument().getTextLength() == 0) {
+        enabled = false;
+      }
       e.getPresentation().setEnabled(enabled);
     }
 
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 3fe5aaf..2610b38 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ModuleRunConfigurationManager.java
@@ -27,8 +27,9 @@
 import com.intellij.openapi.module.ModuleComponent;
 import com.intellij.openapi.project.ModuleAdapter;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.*;
-import com.intellij.util.containers.ContainerUtil;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.util.containers.HashSet;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
@@ -36,7 +37,6 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -51,24 +51,19 @@
 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";
-  @NotNull
-  private final Condition<RunnerAndConfigurationSettings> myModuleConfigCondition = new Condition<RunnerAndConfigurationSettings>() {
-    @Override
-    public boolean value(@Nullable RunnerAndConfigurationSettings settings) {
-      return settings != null && usesMyModule(settings.getConfiguration());
-    }
-  };
 
+  final Object myRemoverKey;
   @NotNull
   private final Module myModule;
   @NotNull
-  private final RunManagerImpl myManager;
+  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
@@ -123,11 +118,6 @@
     }
   }
 
-  @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());
@@ -135,7 +125,7 @@
 
   public void writeExternal(@NotNull final Element element) throws WriteExternalException {
     LOG.debug("writeExternal(" + myModule + ")");
-    for (final RunnerAndConfigurationSettings settings : getModuleRunConfigurationSettings()) {
+    for (final RunnerAndConfigurationSettings settings : myManager.getExternalSettings(myRemoverKey)) {
       myManager.addConfigurationElement(element, settings);
     }
     if (myUnloadedElements != null) {
@@ -152,7 +142,7 @@
 
     final List children = element.getChildren();
     for (final Object child : children) {
-      final RunnerAndConfigurationSettings configuration = myManager.loadConfiguration((Element)child, true);
+      final RunnerAndConfigurationSettings configuration = myManager.loadConfiguration(myRemoverKey, (Element)child, true);
       if (configuration == null && Comparing.strEqual(element.getName(), RunManagerImpl.CONFIGURATION)) {
         if (myUnloadedElements == null) myUnloadedElements = new ArrayList<Element>(2);
         myUnloadedElements.add(element);
@@ -178,13 +168,9 @@
   }
 
   @Override
-  public void beforeModuleRemoved(Project project, Module module) {
-    if (!myModule.equals(module)) {
-      return;
-    }
-    LOG.debug("time to remove something from project (" + project + ")");
-    for (final RunnerAndConfigurationSettings settings : getModuleRunConfigurationSettings()) {
-      myManager.removeConfiguration(settings);
+  public void moduleRemoved(Project project, Module module) {
+    if (myModule.equals(module)) {
+      myManager.removeExternalSettings(myRemoverKey);
     }
   }
 }
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 74ff235..f645686 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
@@ -49,6 +49,8 @@
     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>>();
 
@@ -222,6 +224,11 @@
   }
 
   @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()));
@@ -233,7 +240,6 @@
     for (RunnerAndConfigurationSettings settings : getSortedConfigurations()) {
       if (settings.getConfiguration() == configuration) return settings;
     }
-    LOG.warn("Cannot find settings for RunConfiguration " + configuration.getName());
     return null;
   }
 
@@ -397,6 +403,9 @@
   @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();
@@ -522,7 +531,7 @@
 
   @Override
   public void writeExternal(@NotNull final Element parentNode) throws WriteExternalException {
-    writeContext(parentNode);
+    writeContext(parentNode);//writes temporary configurations here
     for (final RunnerAndConfigurationSettings runnerAndConfigurationSettings : myTemplateConfigurationsMap.values()) {
       if (runnerAndConfigurationSettings.getConfiguration() instanceof UnknownRunConfiguration) {
         if (((UnknownRunConfiguration)runnerAndConfigurationSettings.getConfiguration()).isDoNotStore()) {
@@ -777,15 +786,35 @@
     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 {
-    RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this);
+    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();
     if (factory == null) {
       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()) {
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
index 5cb729d..901a500 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
@@ -26,6 +26,7 @@
  */
 public class RerunTestsAction extends DumbAwareAction implements AnAction.TransparentUpdate {
 
+  public static final String ID = "RerunTests";
   private static final List<RerunInfo> REGISTRY = ContainerUtil.createLockFreeCopyOnWriteList();
 
   public static void register(@NotNull RunContentDescriptor descriptor,
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java
new file mode 100644
index 0000000..04f5bdc
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java
@@ -0,0 +1,80 @@
+package com.intellij.execution.runners;
+
+import com.intellij.execution.ui.ExecutionConsole;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
+import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.ui.GotItMessage;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.Alarm;
+import com.intellij.util.ui.update.UiNotifyConnector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+/**
+* @author Sergey Simonchik
+*/
+public class RerunTestsNotification {
+
+  private static final String KEY = "rerun.tests.notification.shown";
+
+  public static void showRerunNotification(@Nullable RunContentDescriptor contentToReuse,
+                                           @NotNull final ExecutionConsole executionConsole) {
+    if (contentToReuse == null) {
+      return;
+    }
+    String lastActionId = ActionManagerEx.getInstanceEx().getPrevPreformedActionId();
+    boolean showNotification = !RerunTestsAction.ID.equals(lastActionId);
+    if (showNotification && !PropertiesComponent.getInstance().isTrueValue(KEY)) {
+      UiNotifyConnector.doWhenFirstShown(executionConsole.getComponent(), new Runnable() {
+        @Override
+        public void run() {
+          doShow(executionConsole);
+        }
+      });
+    }
+  }
+
+  private static void doShow(@NotNull final ExecutionConsole executionConsole) {
+    final Alarm alarm = new Alarm();
+    alarm.addRequest(new Runnable() {
+      @Override
+      public void run() {
+        String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(
+          ActionManager.getInstance().getAction(RerunTestsAction.ID)
+        );
+        if (shortcutText.isEmpty()) {
+          return;
+        }
+
+        GotItMessage message = GotItMessage.createMessage("Press " + shortcutText + " to rerun tests", "");
+        message.setDisposable(executionConsole);
+        message.setCallback(new Runnable() {
+          @Override
+          public void run() {
+            PropertiesComponent.getInstance().setValue(KEY, String.valueOf(true));
+          }
+        });
+        message.setShowCallout(false);
+        Dimension consoleSize = executionConsole.getComponent().getSize();
+
+        message.show(
+          new RelativePoint(
+            executionConsole.getComponent(),
+            new Point(consoleSize.width - 185, consoleSize.height - 60)
+          ),
+          Balloon.Position.below
+        );
+
+        Disposer.dispose(alarm);
+      }
+    }, 1000);
+  }
+
+}
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 b6b24d8..a02e77f 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -67,7 +67,9 @@
 import com.intellij.util.Consumer;
 import com.intellij.util.ui.EmptyIcon;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.border.CompoundBorder;
@@ -171,7 +173,7 @@
             }
             rebuildList(pattern);
           }
-        }, 400);
+        }, Registry.intValue("ide.goto.rebuild.delay"));
       }
     });
     editor.addFocusListener(new FocusAdapter() {
@@ -307,7 +309,7 @@
     return field;
   }
 
-  private static class MySearchTextField extends SearchTextField {
+  private static class MySearchTextField extends SearchTextField implements DataProvider {
     public MySearchTextField() {
       super(false);
       setOpaque(false);
@@ -317,6 +319,15 @@
     @Override
     protected void showPopup() {
     }
+
+    @Nullable
+    @Override
+    public Object getData(@NonNls String dataId) {
+      if (PlatformDataKeys.PREDEFINED_TEXT.is(dataId)) {
+        return getTextEditor().getText();
+      }
+      return null;
+    }
   }
 
   private class MyListRenderer extends ColoredListCellRenderer {
diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java
index 4d63f14..9764b18 100644
--- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java
@@ -605,7 +605,7 @@
     if (helper.supportsFlattenPackages()) {
       group.addAction(new FavoritesAbbreviatePackageNamesAction(myProject, myBuilder));
     }
-    if (!PlatformUtils.isAppCode()) {
+    if (!PlatformUtils.isCidr()) {
       group.add(new FavoritesShowMembersAction(myProject, myBuilder));
     }
 
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
index 0460ca3..c9cb262 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
@@ -28,6 +28,8 @@
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.Splitter;
@@ -630,4 +632,21 @@
   public Runnable enableSearch(String option) {
     return null;
   }
+
+  public static void editCodeTemplate(@NotNull final String templateId, Project project) {
+    final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
+    final AllFileTemplatesConfigurable configurable = new AllFileTemplatesConfigurable();
+    util.editConfigurable(project, configurable, new Runnable() {
+      @Override
+      public void run() {
+        configurable.myTabbedPane.setSelectedIndex(ArrayUtil.indexOf(configurable.myTabs, configurable.myCodeTemplatesList));
+        for (FileTemplate template : configurable.myCodeTemplatesList.getTemplates()) {
+          if (Comparing.equal(templateId, template.getName())) {
+            configurable.myCodeTemplatesList.selectTemplate(template);
+            break;
+          }
+        }
+      }
+    });
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/impl/dataRules/ModuleRule.java b/platform/lang-impl/src/com/intellij/ide/impl/dataRules/ModuleRule.java
index 4c34aa3..646e671 100644
--- a/platform/lang-impl/src/com/intellij/ide/impl/dataRules/ModuleRule.java
+++ b/platform/lang-impl/src/com/intellij/ide/impl/dataRules/ModuleRule.java
@@ -21,7 +21,8 @@
 import com.intellij.openapi.actionSystem.DataProvider;
 import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiElement;
@@ -40,22 +41,42 @@
     Project project = PlatformDataKeys.PROJECT.getData(dataProvider);
     if (project == null) {
       PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataProvider);
+      if (element == null) {
+        PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataProvider);
+        if (psiElements != null && psiElements.length > 0) {
+          element = psiElements[0];
+        }
+      }
       if (element == null || !element.isValid()) return null;
       project = element.getProject();
     }
 
-    VirtualFile virtualFile = PlatformDataKeys.VIRTUAL_FILE.getData(dataProvider);
-    if (virtualFile == null) {
-      GetDataRule dataRule = ((DataManagerImpl)DataManager.getInstance()).getDataRule(PlatformDataKeys.VIRTUAL_FILE.getName());
+    VirtualFile[] files = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataProvider);
+    if (files == null) {
+      GetDataRule dataRule = ((DataManagerImpl)DataManager.getInstance()).getDataRule(PlatformDataKeys.VIRTUAL_FILE_ARRAY.getName());
       if (dataRule != null) {
-        virtualFile = (VirtualFile)dataRule.getData(dataProvider);
+        files = (VirtualFile[])dataRule.getData(dataProvider);
       }
     }
 
-    if (virtualFile == null) {
+    if (files == null) {
       return null;
     }
 
-    return ModuleUtil.findModuleForFile(virtualFile, project);
+    Module singleModule = null;
+    for (VirtualFile file : files) {
+      Module module = ModuleUtilCore.findModuleForFile(file, project);
+      if (module == null) {
+        return null;
+      }
+      if (singleModule == null) {
+        singleModule = module;
+      }
+      else if (module != singleModule) {
+        return null;
+      }
+    }
+
+    return singleModule;
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
index 85c2181..de1dcd7 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
@@ -521,7 +521,7 @@
     return myNodePopup != null && myNodePopup.isVisible();
   }
 
-  void navigateInsideBar(final Object object) {
+  protected void navigateInsideBar(final Object object) {
     final Object obj = optimizeTarget(object);
     myContextObject = null;
 
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java
index fb9ac1d..e0c820e 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.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.
@@ -211,6 +211,9 @@
         if (myNavigationBar != null && !Disposer.isDisposed(myNavigationBar)) {
           Disposer.dispose(myNavigationBar);
         }
+        if (myProject == null) {
+          return;
+        }
         myNavigationBar = new NavBarPanel(myProject, true);
         myWrapperPanel.putClientProperty("NavBarPanel", myNavigationBar);
         myNavigationBar.getModel().setFixedComponent(true);
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
index e0d1c9c..5760e5b 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
@@ -394,17 +394,36 @@
         content.setSeparator("");
       }
     }
+
+    String selectID = null;
+    String selectSubID = null;
+
+    // try to find saved selected view...
     for (Content content : contents) {
       final String id = content.getUserData(ID_KEY);
       final String subId = content.getUserData(SUB_ID_KEY);
-      if (id != null && id.equals(mySavedPaneId) &&
-          StringUtil.equals(subId, content.getUserData(SUB_ID_KEY))) {
-        changeView(mySavedPaneId, mySavedPaneSubId);
-        mySavedPaneId = null;
-        mySavedPaneSubId = null;
+      if (id != null &&
+          id.equals(mySavedPaneId) &&
+          StringUtil.equals(subId, mySavedPaneSubId)) {
+        selectID = id;
+        selectSubID = subId;
         break;
       }
     }
+
+    // saved view not found (plugin disabled, ID changed etc.) - select first available view...
+    if (selectID == null && contents.length > 0) {
+      Content content = contents[0];
+      selectID = content.getUserData(ID_KEY);
+      selectSubID = content.getUserData(SUB_ID_KEY);
+    }
+
+    if (selectID != null) {
+      changeView(selectID, selectSubID);
+      mySavedPaneId = null;
+      mySavedPaneSubId = null;
+    }
+
     myUninitializedPanes.clear();
   }
 
@@ -678,7 +697,7 @@
       }).setAsSecondary(true);
     }
 
-    if (!PlatformUtils.isAppCode()) {
+    if (!PlatformUtils.isCidr()) {
       myActionGroup.addAction(new PaneOptionAction(myShowMembers, IdeBundle.message("action.show.members"),
                                                    IdeBundle.message("action.show.hide.members"),
                                                    AllIcons.ObjectBrowser.ShowMembers, ourShowMembersDefaults))
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
index c8d3ba2..877d064 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
@@ -62,7 +62,7 @@
   }
 
   protected boolean shouldShowModuleName() {
-    return !PlatformUtils.isAppCode();
+    return !PlatformUtils.isCidr();
   }
 
   @Override
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 1dd3972..aa34383 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
@@ -17,10 +17,12 @@
 
 import com.intellij.ide.util.treeView.TreeAnchorizer;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Key;
-import com.intellij.psi.PsiAnchor;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.SmartPsiElementPointer;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -28,7 +30,7 @@
  */
 public class PsiTreeAnchorizer extends TreeAnchorizer {
 
-  private static final Key<PsiAnchor> PSI_ANCHORIZER_ANCHOR = Key.create("PSI_ANCHORIZER_ANCHOR");
+  private static final Key<SmartPointerWrapper> PSI_ANCHORIZER_POINTER = Key.create("PSI_ANCHORIZER_POINTER");
 
   @Override
   public Object createAnchor(Object element) {
@@ -38,15 +40,17 @@
       return ApplicationManager.getApplication().runReadAction(new Computable<Object>() {
         @Override
         public Object compute() {
-          PsiAnchor anchor = psiElement.getUserData(PSI_ANCHORIZER_ANCHOR);
+          SmartPointerWrapper pointer = psiElement.getUserData(PSI_ANCHORIZER_POINTER);
           if (!psiElement.isValid()) {
-            return anchor != null ? anchor : psiElement;
+            return pointer != null ? pointer : psiElement;
           }
 
-          if (anchor == null || anchor.retrieve() != psiElement) {
-            psiElement.putUserData(PSI_ANCHORIZER_ANCHOR, anchor = PsiAnchor.create(psiElement));
+          if (pointer == null || pointer.myPointer.getElement() != psiElement) {
+            Project project = psiElement.getProject();
+            pointer = new SmartPointerWrapper(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiElement));
+            psiElement.putUserData(PSI_ANCHORIZER_POINTER, pointer);
           }
-          return anchor;
+          return pointer;
         }
       });
     }
@@ -55,14 +59,35 @@
   @Override
   @Nullable
   public Object retrieveElement(Object pointer) {
-    if (pointer instanceof PsiAnchor) {
-      PsiElement retrieve = ((PsiAnchor)pointer).retrieve();
-      if (retrieve == null) {
-        //System.out.println("Null anchor: " + pointer);
-      }
-      return retrieve;
+    if (pointer instanceof SmartPointerWrapper) {
+      return ((SmartPointerWrapper)pointer).myPointer.getElement();
     }
 
     return super.retrieveElement(pointer);
   }
+  
+  private static class SmartPointerWrapper {
+    private final SmartPsiElementPointer myPointer;
+
+    private SmartPointerWrapper(SmartPsiElementPointer pointer) {
+      myPointer = pointer;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (!(o instanceof SmartPointerWrapper)) return false;
+
+      SmartPointerWrapper wrapper = (SmartPointerWrapper)o;
+
+      if (!myPointer.equals(wrapper.myPointer)) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return myPointer.hashCode();
+    }
+  }
 }
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 fe1a9f9..9903fbd 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
@@ -70,6 +70,7 @@
 import com.intellij.util.Consumer;
 import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.FileBasedIndex;
 import com.intellij.util.text.Matcher;
 import com.intellij.util.text.MatcherHolder;
 import com.intellij.util.ui.AsyncProcessIcon;
@@ -153,6 +154,7 @@
   private String myFindUsagesTitle;
   private ShortcutSet myCheckBoxShortcut;
   protected boolean myInitIsDone;
+  static final boolean ourLoadNamesEachTime = FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
 
   public boolean checkDisposed() {
     if (myDisposedFlag && myPostponedOkAction != null && !myPostponedOkAction.isProcessed()) {
@@ -795,7 +797,10 @@
       }
     }
 
-    if (index == 1 && myModel instanceof ContributorsBasedGotoByModel && myNames[0] != null) {
+    if (index == 1 &&
+        myModel instanceof ContributorsBasedGotoByModel &&
+        ((ContributorsBasedGotoByModel)myModel).sameNamesForProjectAndLibraries() &&
+        myNames[0] != null) {
       // there is no way in indices to have different keys for project symbols vs libraries, we always have same ones
       myNames[1] = myNames[0];
       return;
@@ -814,6 +819,10 @@
 
   @NotNull
   public String[] getNames(boolean checkboxState) {
+    if (ourLoadNamesEachTime) {
+      myNames[checkboxState ? 1 : 0] = null;
+      ensureNamesLoaded(checkboxState);
+    }
     return checkboxState ? myNames[1] : myNames[0];
   }
 
@@ -1193,8 +1202,9 @@
     }
 
     final String text = myTextField.getText();
+    if (text.length() == 0) return Collections.emptyList();
     final boolean checkBoxState = myCheckBox.isSelected();
-    //ensureNamesLoaded(checkBoxState);
+    if (ourLoadNamesEachTime) ensureNamesLoaded(checkBoxState);
     final String[] names = checkBoxState ? myNames[1] : myNames[0];
     if (names == null) return Collections.emptyList();
 
@@ -1489,7 +1499,7 @@
                 public void run() {
                   try {
                     boolean everywhere = myCheckboxState;
-                    ensureNamesLoaded(everywhere);
+                    if (!ourLoadNamesEachTime) ensureNamesLoaded(everywhere);
                     addElementsByPattern(myPattern, elements, myCancelled, everywhere);
                   }
                   catch (ProcessCanceledException e) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
index 1fc318a..b98d2e4 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
@@ -20,6 +20,7 @@
 import com.intellij.ide.plugins.PluginManager;
 import com.intellij.ide.util.NavigationItemListCellRenderer;
 import com.intellij.navigation.ChooseByNameContributor;
+import com.intellij.navigation.EfficientChooseByNameContributor;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.application.ReadActionProcessor;
 import com.intellij.openapi.diagnostic.Logger;
@@ -32,9 +33,12 @@
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.CommonProcessors;
 import com.intellij.util.Processor;
+import com.intellij.util.containers.ConcurrentHashMap;
 import com.intellij.util.containers.ContainerUtil;
 import gnu.trove.THashSet;
+import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -47,7 +51,7 @@
 /**
  * Contributor-based goto model
  */
-public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel {
+public abstract class ContributorsBasedGotoByModel implements EfficientChooseByNameModel {
   public static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ContributorsBasedGotoByModel");
 
   protected final Project myProject;
@@ -74,11 +78,14 @@
     };
   }
 
-  @NotNull
-  @Override
-  public String[] getNames(final boolean checkBoxState) {
-    final THashSet<String> allNames = ContainerUtil.newTroveSet();
+  public boolean sameNamesForProjectAndLibraries() {
+    return !ChooseByNameBase.ourLoadNamesEachTime;
+  }
 
+  private final ConcurrentHashMap<ChooseByNameContributor, TIntHashSet> myContributorToItsSymbolsMap = new ConcurrentHashMap<ChooseByNameContributor, TIntHashSet>();
+
+  @Override
+  public void processNames(final Processor<String> nameProcessor, final boolean checkBoxState) {
     long start = System.currentTimeMillis();
     List<ChooseByNameContributor> liveContribs = filterDumb(myContributors);
     ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
@@ -87,10 +94,30 @@
       public boolean processInReadAction(ChooseByNameContributor contributor) {
         try {
           if (!myProject.isDisposed()) {
-            String[] names = contributor.getNames(myProject, checkBoxState);
-            synchronized (allNames) {
-              allNames.ensureCapacity(names.length);
-              ContainerUtil.addAll(allNames, names);
+            long contributorStarted = System.currentTimeMillis();
+            final TIntHashSet filter = new TIntHashSet(1000);
+            myContributorToItsSymbolsMap.put(contributor, filter);
+            if (contributor instanceof EfficientChooseByNameContributor) {
+              ((EfficientChooseByNameContributor)contributor).processNames(new Processor<String>() {
+                @Override
+                public boolean process(String s) {
+                  if (nameProcessor.process(s)) {
+                    filter.add(s.hashCode());
+                  }
+                  return true;
+                }
+              }, DefaultFileNavigationContributor.getScope(myProject, checkBoxState), DefaultFileNavigationContributor.getFilter(myProject, checkBoxState));
+            } else {
+              String[] names = contributor.getNames(myProject, checkBoxState);
+              for (String element : names) {
+                if (nameProcessor.process(element)) {
+                  filter.add(element.hashCode());
+                }
+              }
+            }
+
+            if (LOG.isDebugEnabled()) {
+              LOG.debug(contributor + " for " + (System.currentTimeMillis() - contributorStarted));
             }
           }
         }
@@ -114,7 +141,18 @@
     }
     long finish = System.currentTimeMillis();
     if (LOG.isDebugEnabled()) {
-      LOG.debug("getNames(): "+(finish-start)+"ms; (got "+allNames.size()+" elements)");
+      LOG.debug("processNames(): "+(finish-start)+"ms;");
+    }
+  }
+
+  @NotNull
+  @Override
+  public String[] getNames(final boolean checkBoxState) {
+    final THashSet<String> allNames = ContainerUtil.newTroveSet();
+
+    processNames(new CommonProcessors.CollectProcessor<String>(allNames), checkBoxState);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("getNames(): (got "+allNames.size()+" elements)");
     }
     return ArrayUtil.toStringArray(allNames);
   }
@@ -133,6 +171,7 @@
 
   @NotNull
   public Object[] getElementsByName(final String name, final boolean checkBoxState, final String pattern, @NotNull final ProgressIndicator canceled) {
+    long elementByNameStarted = System.currentTimeMillis();
     final List<NavigationItem> items = Collections.synchronizedList(new ArrayList<NavigationItem>());
 
     Processor<ChooseByNameContributor> processor = new Processor<ChooseByNameContributor>() {
@@ -141,8 +180,12 @@
         if (myProject.isDisposed()) {
           return true;
         }
+        TIntHashSet filter = myContributorToItsSymbolsMap.get(contributor);
+        if (!filter.contains(name.hashCode())) return true;
         try {
-          for (NavigationItem item : contributor.getItemsByName(name, pattern, myProject, checkBoxState)) {
+          long contributorStarted = System.currentTimeMillis();
+          NavigationItem[] itemsByName = contributor.getItemsByName(name, pattern, myProject, checkBoxState);
+          for (NavigationItem item : itemsByName) {
             canceled.checkCanceled();
             if (item == null) {
               PluginId pluginId = PluginManager.getPluginByClassName(contributor.getClass().getName());
@@ -159,6 +202,10 @@
               items.add(item);
             }
           }
+
+          if (LOG.isDebugEnabled()) {
+            LOG.debug(System.currentTimeMillis() - contributorStarted + "," + contributor + "," + itemsByName.length);
+          }
         }
         catch (ProcessCanceledException ex) {
           // index corruption detected, ignore
@@ -173,6 +220,9 @@
       canceled.cancel();
     }
     canceled.checkCanceled(); // if parallel job execution was canceled because of PCE, rethrow it from here
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Retrieving " + name + ":" + items.size() + " for " + (System.currentTimeMillis() - elementByNameStarted));
+    }
     return ArrayUtil.toObjectArray(items);
   }
 
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index 00de48d..d3dfe99 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -47,11 +47,11 @@
   }
 
   @Override
-  public boolean filterElements(@NotNull ChooseByNameBase base,
-                                @NotNull String pattern,
+  public boolean filterElements(@NotNull final ChooseByNameBase base,
+                                @NotNull final String pattern,
                                 boolean everywhere,
                                 @NotNull ProgressIndicator indicator,
-                                @NotNull Processor<Object> consumer) {
+                                @NotNull final Processor<Object> consumer) {
     String namePattern = getNamePattern(base, pattern);
     String qualifierPattern = getQualifierPattern(base, pattern);
 
@@ -60,13 +60,46 @@
     final ChooseByNameModel model = base.getModel();
     String matchingPattern = convertToMatchingPattern(base, namePattern);
     List<MatchResult> namesList = new ArrayList<MatchResult>();
-    String[] names = base.getNames(everywhere);
-    CollectConsumer<MatchResult> collect = new SynchronizedCollectConsumer<MatchResult>(namesList);
-    processNamesByPattern(base, names, matchingPattern, indicator, collect);
+
+    final CollectConsumer<MatchResult> collect = new SynchronizedCollectConsumer<MatchResult>(namesList);
+    long started;
+
+    if (model instanceof EfficientChooseByNameModel) {
+      indicator.checkCanceled();
+      started = System.currentTimeMillis();
+      final MinusculeMatcher matcher = buildPatternMatcher(matchingPattern, NameUtil.MatchingCaseSensitivity.NONE);
+      ((EfficientChooseByNameModel)model).processNames(new Processor<String>() {
+        @Override
+        public boolean process(String sequence) {
+          ProgressManager.checkCanceled();
+          MatchResult result = matches(base, pattern, matcher, sequence);
+          if (result != null) {
+            collect.consume(result);
+            return true;
+          }
+          return false;
+        }
+      }, everywhere);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("loaded + matched:"+ (System.currentTimeMillis() - started)+ "," + collect.getResult().size());
+      }
+    } else {
+      String[] names = base.getNames(everywhere);
+      started = System.currentTimeMillis();
+      processNamesByPattern(base, names, matchingPattern, indicator, collect);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("matched:"+ (System.currentTimeMillis() - started)+ "," + names.length);
+      }
+    }
 
     indicator.checkCanceled();
-    sortNamesList(matchingPattern, (List<MatchResult>)collect.getResult());
+    started = System.currentTimeMillis();
+    List<MatchResult> results = (List<MatchResult>)collect.getResult();
+    sortNamesList(matchingPattern, results);
 
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("sorted:"+ (System.currentTimeMillis() - started) + ",results:" + results.size());
+    }
     indicator.checkCanceled();
 
     List<Object> sameNameElements = new SmartList<Object>();
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java
index 7b0e73b..4c796da 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java
@@ -16,21 +16,83 @@
 package com.intellij.ide.util.gotoByName;
 
 import com.intellij.navigation.ChooseByNameContributor;
+import com.intellij.navigation.EfficientChooseByNameContributor;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ContentIterator;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.psi.PsiFileSystemItem;
 import com.intellij.psi.search.FilenameIndex;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.ProjectScope;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileBasedIndexImpl;
+import com.intellij.util.indexing.IdFilter;
+import gnu.trove.THashSet;
+import gnu.trove.TIntArrayList;
+import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 
-public class DefaultFileNavigationContributor implements ChooseByNameContributor, DumbAware {
+import java.util.BitSet;
+
+public class DefaultFileNavigationContributor implements EfficientChooseByNameContributor, DumbAware {
 
   @Override
   @NotNull
   public String[] getNames(Project project, boolean includeNonProjectItems) {
-    return FilenameIndex.getAllFilenames(project);
+    if (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping) {
+      final THashSet<String> names = new THashSet<String>(1000);
+      IdFilter filter = getFilter(project, includeNonProjectItems);
+      processNames(new Processor<String>() {
+        @Override
+        public boolean process(String s) {
+          names.add(s);
+          return true;
+        }
+      }, getScope(project, includeNonProjectItems), filter);
+      System.out.println("All names retrieved2:" + names.size());
+      return ArrayUtil.toStringArray(names);
+    } else {
+      return FilenameIndex.getAllFilenames(project);
+    }
+  }
+
+  public static GlobalSearchScope getScope(Project project, boolean includeNonProjectItems) {
+    return includeNonProjectItems ? GlobalSearchScope.projectScope(project) : GlobalSearchScope.allScope(project);
+  }
+
+  public static IdFilter getFilter(Project project, boolean includeNonProjectItems) {
+    long started = System.currentTimeMillis();
+    final BitSet idSet = new BitSet();
+
+    ContentIterator iterator = new ContentIterator() {
+      @Override
+      public boolean processFile(VirtualFile fileOrDir) {
+        idSet.set(
+          ((VirtualFileWithId)fileOrDir).getId()
+        );
+        return true;
+      }
+    };
+
+    if (!includeNonProjectItems) {
+      ProjectRootManager.getInstance(project).getFileIndex().iterateContent(iterator);
+    } else {
+      FileBasedIndex.getInstance().iterateIndexableFiles(iterator, project, null);
+    }
+
+    System.out.println("Done filter " + (System.currentTimeMillis()  -started) + ":" + idSet.size());
+    return new IdFilter() {
+      @Override
+      public boolean contains(int id) {
+        return idSet.get(id);
+      }
+    };
   }
 
   @Override
@@ -48,4 +110,16 @@
     }
     return items;
   }
+
+  @Override
+  public void processNames(final Processor<String> processor, GlobalSearchScope scope, IdFilter filter) {
+    long started = System.currentTimeMillis();
+    FileBasedIndex.getInstance().processAllKeys(FilenameIndex.NAME, new Processor<String>() {
+      @Override
+      public boolean process(String s) {
+        return processor.process(s);
+      }
+    }, scope, filter);
+    System.out.println("All names retrieved:" + (System.currentTimeMillis() - started));
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/EfficientChooseByNameModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/EfficientChooseByNameModel.java
new file mode 100644
index 0000000..c50d347
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/EfficientChooseByNameModel.java
@@ -0,0 +1,22 @@
+/*
+ * 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.gotoByName;
+
+import com.intellij.util.Processor;
+
+public interface EfficientChooseByNameModel extends ChooseByNameModel {
+  void processNames(Processor<String> processor, boolean inLibraries);
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java
index 329c190..8d80a1c 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java
@@ -22,9 +22,11 @@
 import com.intellij.navigation.ChooseByNameRegistry;
 import com.intellij.navigation.GotoClassContributor;
 import com.intellij.navigation.NavigationItem;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.psi.PsiElement;
+import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -146,4 +148,9 @@
   public boolean willOpenEditor() {
     return true;
   }
+
+  @Override
+  public boolean sameNamesForProjectAndLibraries() {
+    return !FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
+  }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
index adc943ea..82ecacb 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
@@ -30,6 +30,7 @@
 import com.intellij.openapi.wm.ex.WindowManagerEx;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiFileSystemItem;
+import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -115,6 +116,11 @@
   }
 
   @Override
+  public boolean sameNamesForProjectAndLibraries() {
+    return !FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
+  }
+
+  @Override
   @Nullable
   public String getFullName(final Object element) {
     if (element instanceof PsiFileSystemItem) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java
index 8abcde7..f594893 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java
@@ -237,7 +237,7 @@
       result.add(GlobalSearchScope.allScope(project));
     }
 
-    if (!PlatformUtils.isAppCode()) { // TODO: fix these scopes in AppCode
+    if (!PlatformUtils.isCidr()) { // TODO: fix these scopes in AppCode
       result.add(GlobalSearchScopes.projectProductionScope(project));
       result.add(GlobalSearchScopes.projectTestScope(project));
     }
@@ -250,7 +250,7 @@
         dataContextElement = LangDataKeys.PSI_ELEMENT.getData(dataContext);
       }
       if (dataContextElement != null) {
-        if (!PlatformUtils.isAppCode()) { // TODO: have an API to disable module scopes.
+        if (!PlatformUtils.isCidr()) { // TODO: have an API to disable module scopes.
           Module module = ModuleUtilCore.findModuleForPsiElement(dataContextElement);
           if (module == null) {
             module = LangDataKeys.MODULE.getData(dataContext);
diff --git a/platform/lang-impl/src/com/intellij/navigation/EfficientChooseByNameContributor.java b/platform/lang-impl/src/com/intellij/navigation/EfficientChooseByNameContributor.java
new file mode 100644
index 0000000..d70bd7a
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/navigation/EfficientChooseByNameContributor.java
@@ -0,0 +1,25 @@
+/*
+ * 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.navigation;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.Processor;
+import com.intellij.util.indexing.IdFilter;
+
+public interface EfficientChooseByNameContributor extends ChooseByNameContributor {
+  void processNames(Processor<String> processor, GlobalSearchScope scope, IdFilter filter);
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffOptionsPanel.java b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffOptionsPanel.java
index d661a65..74e47bd 100644
--- a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffOptionsPanel.java
+++ b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffOptionsPanel.java
@@ -28,6 +28,7 @@
 import com.intellij.util.EventDispatcher;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.event.ListSelectionEvent;
@@ -35,7 +36,10 @@
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.*;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 public class DiffOptionsPanel implements OptionsPanel {
   private final ColorAndFontOptions myOptions;
@@ -242,7 +246,7 @@
     return myStripeMarkColorComponent.getComponent();
   }
 
-  public static void addSchemeDescriptions(ArrayList<EditorSchemeAttributeDescriptor> descriptions, EditorColorsScheme scheme) {
+  public static void addSchemeDescriptions(@NotNull List<EditorSchemeAttributeDescriptor> descriptions, @NotNull EditorColorsScheme scheme) {
     for (TextDiffType diffType : TextDiffType.MERGE_TYPES) {
       descriptions.add(new MyColorAndFontDescription(diffType, scheme));
     }
@@ -265,7 +269,7 @@
     private final EditorColorsScheme myScheme;
     private final TextDiffType myDiffType;
 
-    public MyColorAndFontDescription(TextDiffType diffType, EditorColorsScheme scheme) {
+    public MyColorAndFontDescription(@NotNull TextDiffType diffType, @NotNull EditorColorsScheme scheme) {
       myScheme = scheme;
       myDiffType = diffType;
       TextAttributes attrs = diffType.getTextAttributes(myScheme);
diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
index 145624c..7464c9f 100644
--- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
+++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
@@ -170,9 +170,9 @@
 
   public PsiDirectory getTargetDirectory() {
     DirectoryNode dirNode = this;
-    while (dirNode.getCompactedDirNode() != null) {
-      dirNode = dirNode.getCompactedDirNode();
-      assert dirNode != null;
+    DirectoryNode compacted;
+    while ((compacted = dirNode.getCompactedDirNode()) != null) {
+      dirNode = compacted;
     }
 
     return dirNode.getPsiDirectory();
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
index 62d1cb0..cfe75941 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
@@ -99,12 +99,11 @@
       final VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
       if (virtualFile != null && virtualFile.isValid()) {
         Collection<Project> projects = ProjectLocator.getInstance().getProjectsForFile(virtualFile);
-        LOG.assertTrue(projects.isEmpty() || projects.contains(myProject), "Trying to get PSI for an alien project. VirtualFile=" +
-                                                                           virtualFile +
-                                                                           ";\n myProject=" +
-                                                                           myProject +
-                                                                           ";\n projects returned: " +
-                                                                           projects);
+        if (!projects.isEmpty() && !projects.contains(myProject)) {
+          LOG.error("Trying to get PSI for an alien project. VirtualFile=" + virtualFile +
+                    ";\n myProject=" + myProject +
+                    ";\n projects returned: " + projects);
+        }
       }
     }
     return psiFile;
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
index 9d7a9e9..af96331 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
@@ -19,6 +19,7 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationAdapter;
 import com.intellij.openapi.application.ApplicationListener;
 import com.intellij.openapi.application.ApplicationManager;
@@ -53,6 +54,7 @@
 import org.jetbrains.annotations.TestOnly;
 
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class PostprocessReformattingAspect implements PomModelAspect {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PostprocessReformattingAspect");
@@ -62,8 +64,9 @@
   private final Map<FileViewProvider, List<ASTNode>> myReformatElements = new HashMap<FileViewProvider, List<ASTNode>>();
   private volatile int myDisabledCounter = 0;
   private final Set<FileViewProvider> myUpdatedProviders = new HashSet<FileViewProvider>();
+  private final AtomicInteger myPostponedCounter = new AtomicInteger();
 
-  public PostprocessReformattingAspect(Project project, PsiManager psiManager, TreeAspect treeAspect) {
+  public PostprocessReformattingAspect(Project project, PsiManager psiManager, TreeAspect treeAspect,final CommandProcessor processor) {
     myProject = project;
     myPsiManager = psiManager;
     myTreeAspect = treeAspect;
@@ -73,18 +76,16 @@
     ApplicationListener applicationListener = new ApplicationAdapter() {
       @Override
       public void writeActionStarted(final Object action) {
-        final CommandProcessor processor = CommandProcessor.getInstance();
         if (processor != null) {
           final Project project = processor.getCurrentCommandProject();
           if (project == myProject) {
-            myPostponedCounter++;
+            incrementPostponedCounter();
           }
         }
       }
 
       @Override
       public void writeActionFinished(final Object action) {
-        final CommandProcessor processor = CommandProcessor.getInstance();
         if (processor != null) {
           final Project project = processor.getCurrentCommandProject();
           if (project == myProject) {
@@ -117,8 +118,6 @@
     }
   }
 
-  private int myPostponedCounter = 0;
-
   public void postponeFormattingInside(final Runnable runnable) {
     postponeFormattingInside(new NullableComputable<Object>() {
       @Override
@@ -130,9 +129,10 @@
   }
 
   public <T> T postponeFormattingInside(Computable<T> computable) {
+    Application application = ApplicationManager.getApplication();
+    application.assertIsDispatchThread();
     try {
-      //if(myPostponedCounter == 0) myDisabled = false;
-      myPostponedCounter++;
+      incrementPostponedCounter();
       return computable.compute();
     }
     finally {
@@ -140,13 +140,19 @@
     }
   }
 
+  private void incrementPostponedCounter() {
+    myPostponedCounter.incrementAndGet();
+  }
+
   private void decrementPostponedCounter() {
-    if (--myPostponedCounter == 0) {
-      if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
+    Application application = ApplicationManager.getApplication();
+    application.assertIsDispatchThread();
+    if (myPostponedCounter.decrementAndGet() == 0) {
+      if (application.isWriteAccessAllowed()) {
         doPostponedFormatting();
       }
       else {
-        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+        application.runWriteAction(new Runnable() {
           @Override
           public void run() {
             doPostponedFormatting();
@@ -156,7 +162,7 @@
     }
   }
 
-  private static void atomic(Runnable r) {
+  private static void atomic(@NotNull Runnable r) {
     ProgressManager.getInstance().executeNonCancelableSection(r);
   }
 
@@ -165,7 +171,7 @@
     atomic(new Runnable() {
       @Override
       public void run() {
-        if (isDisabled() || myPostponedCounter == 0 && !ApplicationManager.getApplication().isUnitTestMode()) return;
+        if (isDisabled() || myPostponedCounter.get() == 0 && !ApplicationManager.getApplication().isUnitTestMode()) return;
         final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myTreeAspect);
         if (changeSet == null) return;
         final PsiElement psiElement = changeSet.getRootElement().getPsi();
@@ -287,8 +293,6 @@
   }
 
   private void doPostponedFormattingInner(final FileViewProvider key) {
-
-
     final List<ASTNode> astNodes = myReformatElements.remove(key);
     final Document document = key.getDocument();
     // Sort ranges by end offsets so that we won't need any offset adjustment after reformat or reindent
@@ -307,7 +311,7 @@
       // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges are sorted by end offset.
       if (astNodes != null) createActionsMap(astNodes, key, postProcessTasks);
 
-      if ("true".equals(System.getProperty("check.psi.is.valid")) && ApplicationManager.getApplication().isUnitTestMode()) {
+      if (Boolean.getBoolean("check.psi.is.valid") && ApplicationManager.getApplication().isUnitTestMode()) {
         checkPsiIsCorrect(key);
       }
 
@@ -316,7 +320,7 @@
         // (free reformatting -> reindent -> formatting under reindent)
         final List<PostponedAction> normalizedActions = normalizeAndReorderPostponedActions(postProcessTasks, document);
         toDispose.addAll(normalizedActions);
-  
+
         // only in following loop real changes in document are made
         for (final PostponedAction normalizedAction : normalizedActions) {
           CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myPsiManager.getProject());
@@ -649,6 +653,7 @@
       return myRange.getEndOffset();
     }
 
+    @Override
     public void dispose() {
       if (myRange.isValid()) {
         myRange.dispose();
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
index 744f910..7b5f9ff 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
@@ -142,7 +142,9 @@
           IndexInfrastructure.getStorageFile(indexKey),
           extension.getKeyDescriptor(),
           new StubIdExternalizer(),
-          extension.getCacheSize()
+          extension.getCacheSize(),
+          false,
+          extension instanceof StringStubIndexExtension && ((StringStubIndexExtension)extension).traceKeyHashToVirtualFileMapping()
         );
 
         final MemoryIndexStorage<K, StubIdList> memStorage = new MemoryIndexStorage<K, StubIdList>(storage);
@@ -285,11 +287,16 @@
 
   @Override
   public <K> boolean processAllKeys(@NotNull StubIndexKey<K, ?> indexKey, @NotNull Project project, Processor<K> processor) {
-    FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, GlobalSearchScope.allScope(project));
+    return processAllKeys(indexKey, processor, GlobalSearchScope.allScope(project), null);
+  }
+
+  public <K> boolean processAllKeys(@NotNull StubIndexKey<K, ?> indexKey, Processor<K> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) {
+
+    FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, scope.getProject(), scope);
 
     final MyIndex<K> index = (MyIndex<K>)myIndices.get(indexKey);
     try {
-      return index.processAllKeys(processor);
+      return index.processAllKeys(processor, idFilter);
     }
     catch (StorageException e) {
       forceRebuild(e);
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java
index 8f31703..1b4a4c2 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.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.
@@ -40,12 +40,16 @@
 public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler {
   @Override
   protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
-    final PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
+    PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
+    if (nameSuggestionContext == null && editor.getCaretModel().getOffset() > 0) {
+      nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset() - 1);
+    }
+
     if (element == null && LookupManager.getActiveLookup(editor) != null) {
       element = PsiTreeUtil.getParentOfType(nameSuggestionContext, PsiNamedElement.class);
     }
     final RefactoringSupportProvider
-      supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()) : null;
+      supportProvider = element == null ? null : LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage());
     return editor.getSettings().isVariableInplaceRenameEnabled()
            && supportProvider != null
            && supportProvider.isMemberInplaceRenameAvailable(element, nameSuggestionContext);
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java
index 0892f1e..ccdb0b0 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java
@@ -54,8 +54,8 @@
   protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
     final PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
 
-    final RefactoringSupportProvider
-      supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
+    RefactoringSupportProvider supportProvider =
+      element == null ? null : LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage());
     return supportProvider != null &&
            editor.getSettings().isVariableInplaceRenameEnabled() &&
            supportProvider.isInplaceRenameAvailable(element, nameSuggestionContext);
diff --git a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
index 2591fef..4e70241 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
@@ -435,7 +435,7 @@
     return super.isToBeChanged(usageInfo);
   }
 
-  public static boolean validElement(PsiElement element) {
+  public static boolean validElement(@NotNull PsiElement element) {
     if (element instanceof PsiFile) return true;
     if (!element.isPhysical()) return false;
     final RefactoringSupportProvider provider = LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage());
diff --git a/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java b/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java
index a55f4e90..9074e74 100644
--- a/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java
+++ b/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java
@@ -32,18 +32,23 @@
 
 public class LanguageTextField extends EditorTextField {
   private final Language myLanguage;
+  // Could be null to allow usage in UI designer, as EditorTextField permits
   private final Project myProject;
 
-  public LanguageTextField(Language language, @NotNull Project project, @NotNull String value) {
+  public LanguageTextField() {
+    this(null, null, "");
+  }
+
+  public LanguageTextField(Language language, @Nullable Project project, @NotNull String value) {
     this(language, project, value, true);
   }
 
-  public LanguageTextField(Language language, @NotNull Project project, @NotNull String value, boolean oneLineMode) {
+  public LanguageTextField(Language language, @Nullable Project project, @NotNull String value, boolean oneLineMode) {
     this(language, project, value, new SimpleDocumentCreator(), oneLineMode);
   }
 
   public LanguageTextField(@Nullable Language language,
-                           @NotNull Project project,
+                           @Nullable Project project,
                            @NotNull String value,
                            @NotNull DocumentCreator documentCreator)
   {
@@ -51,7 +56,7 @@
   }
 
   public LanguageTextField(@Nullable Language language,
-                           @NotNull Project project,
+                           @Nullable Project project,
                            @NotNull String value,
                            @NotNull DocumentCreator documentCreator,
                            boolean oneLineMode) {
diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
index f17beff..2690a2a 100644
--- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
+++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
@@ -36,45 +36,57 @@
 import java.util.Collection;
 
 /**
+ * <p/>
+ * It is text field with autocompletion from list of values.
+ * <p/>
+ * Autocompletion is implemented via {@code TextFieldWithAutoCompletionContributor}.
+ * Use {@code setVariants} set list of values for autocompletion.
+ *
  * @author Roman Chernyatchik
- *         <p/>
- *         It is text field with autocompletion from list of values.
- *         <p/>
- *         Autocompletion is implemented via LookupManager.
- *         Use setVariants(..) set list of values for autocompletion.
- *         For variants you can use not only instances of PresentableLookupValue, but
- *         also instances of LookupValueWithPriority and LookupValueWithUIHint
  */
 public class TextFieldWithAutoCompletion<T> extends LanguageTextField {
 
   public static final TextFieldWithAutoCompletionListProvider EMPTY_COMPLETION = new StringsCompletionProvider(null, null);
   private final boolean myShowAutocompletionIsAvailableHint;
+  private final TextFieldWithAutoCompletionListProvider<T> myProvider;
 
+  @SuppressWarnings("unchecked")
   public TextFieldWithAutoCompletion() {
-    // For UI designer
-    this(null, null, false, null);
+    this(null, EMPTY_COMPLETION, false, null);
   }
 
+
   public TextFieldWithAutoCompletion(final Project project,
-                                     @Nullable final TextFieldWithAutoCompletionListProvider<T> provider,
+                                     @NotNull final TextFieldWithAutoCompletionListProvider<T> provider,
                                      final boolean showAutocompletionIsAvailableHint, @Nullable final String text) {
     super(PlainTextLanguage.INSTANCE, project, text == null ? "" : text);
 
     myShowAutocompletionIsAvailableHint = showAutocompletionIsAvailableHint;
+    myProvider = provider;
 
-    if (provider != null) {
-      TextFieldWithAutoCompletionContributor.installCompletion(getDocument(), project, provider, true);
-    }
+    TextFieldWithAutoCompletionContributor.installCompletion(getDocument(), project, provider, true);
+  }
+
+  public static TextFieldWithAutoCompletion<String> create(final Project project,
+                                                           @NotNull final Collection<String> items,
+                                                           final boolean showAutocompletionIsAvailableHint,
+                                                           @Nullable final String text) {
+    return create(project, items, null, showAutocompletionIsAvailableHint, text);
   }
 
   public static TextFieldWithAutoCompletion<String> create(final Project project,
                                                            @NotNull final Collection<String> items,
                                                            @Nullable final Icon icon,
-                                                           final boolean showAutocompletionIsAvailableHint, @Nullable final String text) {
+                                                           final boolean showAutocompletionIsAvailableHint,
+                                                           @Nullable final String text) {
     return new TextFieldWithAutoCompletion<String>(project, new StringsCompletionProvider(items, icon), showAutocompletionIsAvailableHint,
                                                    text);
   }
 
+  public void setVariants(@NotNull Collection<T> variants) {
+    myProvider.setItems(variants);
+  }
+
   @Override
   protected EditorEx createEditor() {
     final EditorEx editor = super.createEditor();
@@ -83,8 +95,9 @@
       return editor;
     }
 
-    final String completionShortcutText = getCompletionShortcutText();
-    if (completionShortcutText == null) {
+    final String completionShortcutText =
+      KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION));
+    if (StringUtil.isEmpty(completionShortcutText)) {
       return editor;
     }
 
@@ -124,7 +137,7 @@
       final ShortcutSet shortcutSet = action.getShortcutSet();
       if (shortcutSet != null) {
         final Shortcut[] shortcuts = shortcutSet.getShortcuts();
-        if (shortcuts != null && shortcuts.length > 0) {
+        if (shortcuts.length > 0) {
           return KeymapUtil.getShortcutText(shortcuts[0]);
         }
       }
diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
index 834779f..753dc09 100644
--- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
+++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
@@ -43,16 +43,17 @@
 
   public static <T> void installCompletion(Document document,
                                            Project project,
-                                           @Nullable TextFieldWithAutoCompletionListProvider<T> consumer,
+                                           @Nullable TextFieldWithAutoCompletionListProvider<T> provider,
                                            boolean autoPopup) {
     PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
     if (psiFile != null) {
       //noinspection unchecked
-      psiFile.putUserData(KEY, consumer == null ? TextFieldWithAutoCompletion.EMPTY_COMPLETION : consumer);
+      psiFile.putUserData(KEY, provider == null ? TextFieldWithAutoCompletion.EMPTY_COMPLETION : provider);
       psiFile.putUserData(AUTO_POPUP_KEY, autoPopup);
     }
   }
 
+
   @Override
   public void fillCompletionVariants(final CompletionParameters parameters, CompletionResultSet result) {
     PsiFile file = parameters.getOriginalFile();
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
index 60949b8..10adf97 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
@@ -18,6 +18,7 @@
 
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author Eugene Zhuravlev
@@ -27,5 +28,5 @@
   @NotNull
   ValueContainer<Value> getData(Key key) throws StorageException;
 
-  boolean processAllKeys(Processor<Key> processor) throws StorageException;
+  boolean processAllKeys(Processor<Key> processor, @Nullable IdFilter idFilter) throws StorageException;
 }
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 642c455..c381c79 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -413,7 +413,8 @@
           extension.getKeyDescriptor(),
           extension.getValueExternalizer(),
           extension.getCacheSize(),
-          extension.isKeyHighlySelective()
+          extension.isKeyHighlySelective(),
+          extension.traceKeyHashToVirtualFileMapping()
         );
 
         final MemoryIndexStorage<K, V> memStorage = new MemoryIndexStorage<K, V>(storage);
@@ -722,13 +723,17 @@
 
   @Override
   public <K> boolean processAllKeys(@NotNull final ID<K, ?> indexId, Processor<K> processor, @Nullable Project project) {
+    return processAllKeys(indexId, processor, project != null ? GlobalSearchScope.allScope(project) : new EverythingGlobalScope(), null);
+  }
+
+  public <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, Processor<K> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) {
     try {
       final UpdatableIndex<K, ?, FileContent> index = getIndex(indexId);
       if (index == null) {
         return true;
       }
-      ensureUpToDate(indexId, project, project != null ? GlobalSearchScope.allScope(project) : new EverythingGlobalScope());
-      return index.processAllKeys(processor);
+      ensureUpToDate(indexId, scope.getProject(), scope);
+      return index.processAllKeys(processor, idFilter);
     }
     catch (StorageException e) {
       scheduleRebuild(indexId, e);
@@ -1014,7 +1019,7 @@
     myContentlessIndicesUpdateQueue.signalUpdateEnd();
   }
 
-  public static final class ProjectIndexableFilesFilter {
+  public static final class ProjectIndexableFilesFilter extends IdFilter {
     private static final int SHIFT = 6;
     private static final int MASK = (1 << SHIFT) - 1;
     private final long[] myBitMask;
@@ -1735,7 +1740,9 @@
     }
     FileType fileType = file.getFileType();
     if(isProjectOrWorkspaceFile(file, fileType)) return Collections.emptyList();
-
+    if (fileType == StdFileTypes.HTML || fileType == StdFileTypes.XML) {
+      int a = 1;
+    }
     List<ID<?, ?>> ids = myFileType2IndicesWithFileTypeInfoMap.get(fileType);
     if (ids == null) ids = myIndicesWithoutFileTypeInfo;
     return ids;
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
index 32abd28..900c6e3 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
@@ -95,16 +95,14 @@
         }
       }
     });
-
+    assert os != null;
     try {
-      if (os != null) {
-        os.writeInt(version);
-        os.writeInt(VERSION);
-      }
+      os.writeInt(version);
+      os.writeInt(VERSION);
     }
     finally {
       ourIndexIdToCreationStamp.clear();
-      if (os != null) os.close();
+      os.close();
       long max = Math.max(System.currentTimeMillis(), Math.max(prevLastModifiedValue, ourLastStamp) + 2000);
       ourLastStamp = max;
       file.setLastModified(max);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
index a268c0c..5e0296b 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
@@ -18,6 +18,7 @@
 
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.Flushable;
 import java.io.IOException;
@@ -38,7 +39,7 @@
   @NotNull
   ValueContainer<Value> read(Key key) throws StorageException;
 
-  boolean processKeys(Processor<Key> processor) throws StorageException;
+  boolean processKeys(Processor<Key> processor, @Nullable IdFilter idFilter) throws StorageException;
 
   Collection<Key> getKeys() throws StorageException;
 
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
index ffdc0ab..0448c65 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
@@ -22,12 +22,13 @@
 import com.intellij.util.CommonProcessors;
 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.PersistentMap;
+import com.intellij.util.io.*;
+import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.io.DataInput;
+import java.io.DataOutput;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -42,7 +43,9 @@
 */
 public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Value>{
   private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.MapIndexStorage");
+  private final boolean myBuildKeyHashToVirtualFileMapping;
   private PersistentMap<Key, ValueContainer<Value>> myMap;
+  private PersistentBTreeEnumerator<int[]> myKeyHashToVirtualFileMapping;
   private SLRUCache<Key, ChangeTrackingValueContainer<Value>> myCache;
   private final File myStorageFile;
   private final KeyDescriptor<Key> myKeyDescriptor;
@@ -71,20 +74,23 @@
                          @NotNull DataExternalizer<Value> valueExternalizer,
                          final int cacheSize
   ) throws IOException {
-    this(storageFile, keyDescriptor, valueExternalizer, cacheSize, false);
+    this(storageFile, keyDescriptor, valueExternalizer, cacheSize, false, false);
   }
 
   public MapIndexStorage(@NotNull File storageFile,
                          @NotNull KeyDescriptor<Key> keyDescriptor,
                          @NotNull DataExternalizer<Value> valueExternalizer,
                          final int cacheSize,
-                         boolean highKeySelectivity) throws IOException {
+                         boolean highKeySelectivity,
+                         boolean buildKeyHashToVirtualFileMapping
+                         ) throws IOException {
 
     myStorageFile = storageFile;
     myKeyDescriptor = keyDescriptor;
     myCacheSize = cacheSize;
     myDataExternalizer = valueExternalizer;
     myHighKeySelectivity = highKeySelectivity;
+    myBuildKeyHashToVirtualFileMapping = buildKeyHashToVirtualFileMapping && FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
     initMapAndCache();
   }
 
@@ -133,6 +139,37 @@
     };
 
     myMap = map;
+
+    myKeyHashToVirtualFileMapping = myBuildKeyHashToVirtualFileMapping ? new PersistentBTreeEnumerator<int[]>(getProjectFile(), new KeyDescriptor<int[]>() {
+      @Override
+      public void save(DataOutput out, int[] value) throws IOException {
+        DataInputOutputUtil.writeINT(out, value[0]);
+        DataInputOutputUtil.writeINT(out, value[1]);
+      }
+
+      @Override
+      public int[] read(DataInput in) throws IOException {
+        return new int[] {DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in)};
+      }
+
+      @Override
+      public int getHashCode(int[] value) {
+        return value[0] * 31 + value[1];
+      }
+
+      @Override
+      public boolean isEqual(int[] val1, int[] val2) {
+        return val1[0] == val2[0] && val1[1] == val2[1];
+      }
+    }, 4096) {
+      protected boolean serializationEquivalenceIsExhausting() {
+        return true;
+      }
+    }: null;
+  }
+
+  private File getProjectFile() {
+    return new File(myStorageFile.getPath() + ".project");
   }
 
   @Override
@@ -143,6 +180,7 @@
         myCache.clear();
         myMap.force();
       }
+      if (myKeyHashToVirtualFileMapping != null) myKeyHashToVirtualFileMapping.force();
     }
     finally {
       l.unlock();
@@ -154,6 +192,7 @@
     try {
       myLowMemoryFlusher.stop();
       flush();
+      if (myKeyHashToVirtualFileMapping != null) myKeyHashToVirtualFileMapping.close();
       myMap.close();
     }
     catch (IOException e) {
@@ -175,12 +214,14 @@
   public void clear() throws StorageException{
     try {
       myMap.close();
+      if (myKeyHashToVirtualFileMapping != null) myKeyHashToVirtualFileMapping.close();
     }
     catch (IOException e) {
       LOG.error(e);
     }
     try {
       FileUtil.delete(myStorageFile);
+      if (myKeyHashToVirtualFileMapping != null) IOUtil.deleteAllFilesStartingWith(getProjectFile());
       initMapAndCache();
     }
     catch (IOException e) {
@@ -199,10 +240,32 @@
   }
 
   @Override
-  public boolean processKeys(final Processor<Key> processor) throws StorageException {
+  public boolean processKeys(final Processor<Key> processor, final IdFilter idFilter) throws StorageException {
     l.lock();
     try {
       myCache.clear(); // this will ensure that all new keys are made into the map
+      if (myBuildKeyHashToVirtualFileMapping && idFilter != null) {
+        final TIntHashSet hashMaskSet = new TIntHashSet(1000);
+        long l = System.currentTimeMillis();
+        myKeyHashToVirtualFileMapping.iterateData(new Processor<int[]>() {
+          @Override
+          public boolean process(int[] key) {
+            if (!idFilter.contains(key[1])) return true;
+            hashMaskSet.add(key[0]);
+            return true;
+          }
+        });
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Scanned keyHashToVirtualFileMapping of " + myStorageFile + " for " + (System.currentTimeMillis() - l));
+        }
+        return myMap.processKeys(new Processor<Key>() {
+          @Override
+          public boolean process(Key key) {
+            if (!hashMaskSet.contains(myKeyDescriptor.getHashCode(key))) return true;
+            return processor.process(key);
+          }
+        });
+      }
       return myMap.processKeys(processor);
     }
     catch (IOException e) {
@@ -227,7 +290,7 @@
   @Override
   public Collection<Key> getKeys() throws StorageException {
     List<Key> keys = new ArrayList<Key>();
-    processKeys(new CommonProcessors.CollectProcessor<Key>(keys));
+    processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null);
     return keys;
   }
 
@@ -256,6 +319,10 @@
   @Override
   public void addValue(final Key key, final int inputId, final Value value) throws StorageException {
     try {
+      if (myKeyHashToVirtualFileMapping != null) {
+        myKeyHashToVirtualFileMapping.enumerate(new int[] { myKeyDescriptor.getHashCode(key), inputId });
+      }
+
       myMap.markDirty();
       if (!myHighKeySelectivity) {
         read(key).addValue(inputId, value);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
index e93ca8b..98b62a5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -155,11 +155,11 @@
   }
 
   @Override
-  public boolean processAllKeys(Processor<Key> processor) throws StorageException {
+  public boolean processAllKeys(Processor<Key> processor, IdFilter idFilter) throws StorageException {
     final Lock lock = getReadLock();
     try {
       lock.lock();
-      return myStorage.processKeys(processor);
+      return myStorage.processKeys(processor, idFilter);
     }
     finally {
       lock.unlock();
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
index 7a87af7..f07fc85 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
@@ -101,12 +101,12 @@
   @Override
   public Collection<Key> getKeys() throws StorageException {
     final Set<Key> keys = new HashSet<Key>();
-    processKeys(new CommonProcessors.CollectProcessor<Key>(keys));
+    processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null);
     return keys;
   }
 
   @Override
-  public boolean processKeys(final Processor<Key> processor) throws StorageException {
+  public boolean processKeys(final Processor<Key> processor, IdFilter idFilter) throws StorageException {
     final Set<Key> stopList = new HashSet<Key>();
 
     Processor<Key> decoratingProcessor = new Processor<Key>() {
@@ -128,7 +128,7 @@
       }
       stopList.add(key);
     }
-    return myBackendStorage.processKeys(decoratingProcessor);
+    return myBackendStorage.processKeys(stopList.size() == 0 && myMap.size() == 0 ? processor : decoratingProcessor, idFilter);
   }
 
   @Override
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 d5906e5..943cbbf 100644
--- a/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java
+++ b/platform/lang-impl/testSources/com/intellij/execution/impl/ModuleRunConfigurationManagerTest.java
@@ -68,6 +68,7 @@
       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);
   }
 
@@ -107,13 +108,13 @@
 
   public void testBeforeOtherModuleRemoved() throws Exception {
     myRemovedSettings.clear();
-    myManager.beforeModuleRemoved(getProject(), getModule());
+    myManager.moduleRemoved(getProject(), getModule());
     assertEmpty("No settings should be removed", myRemovedSettings);
   }
 
   public void testBeforeMyModuleRemoved() throws Exception {
     myRemovedSettings.clear();
-    myManager.beforeModuleRemoved(getProject(), myModule);
+    myManager.moduleRemoved(getProject(), myModule);
     assertSameElements("one run config should be removed", myRemovedSettings, Collections.singleton(mySettings));
   }
 
diff --git a/platform/platform-api/src/com/intellij/ide/XmlRpcServer.java b/platform/platform-api/src/com/intellij/ide/XmlRpcServer.java
index 24e06e6..16dafdc 100644
--- a/platform/platform-api/src/com/intellij/ide/XmlRpcServer.java
+++ b/platform/platform-api/src/com/intellij/ide/XmlRpcServer.java
@@ -16,8 +16,8 @@
 package com.intellij.ide;
 
 import com.intellij.openapi.components.ServiceManager;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.http.HttpRequest;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,7 +31,7 @@
 
   void removeHandler(String name);
 
-  boolean process(@NotNull String path, @NotNull HttpRequest request, @NotNull ChannelHandlerContext context, @Nullable Map<String, Object> handlers) throws IOException;
+  boolean process(@NotNull String path, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context, @Nullable Map<String, Object> handlers) throws IOException;
 
   final class SERVICE {
     private SERVICE() {
diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationAdapter.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationAdapter.java
index 00f38c9..ddeaa8c 100644
--- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationAdapter.java
+++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationAdapter.java
@@ -15,22 +15,25 @@
  */
 package com.intellij.openapi.application;
 
-import com.intellij.openapi.wm.IdeFrame;
-
 public abstract class ApplicationAdapter implements ApplicationListener {
+  @Override
   public boolean canExitApplication() {
     return true;
   }
 
+  @Override
   public void applicationExiting() {
   }
 
+  @Override
   public void beforeWriteActionStart(Object action) {
   }
 
+  @Override
   public void writeActionStarted(Object action) {
   }
 
+  @Override
   public void writeActionFinished(Object action) {
   }
 }
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/StatusBarWidget.java b/platform/platform-api/src/com/intellij/openapi/wm/StatusBarWidget.java
index 8382553..2e77707 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/StatusBarWidget.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/StatusBarWidget.java
@@ -130,7 +130,7 @@
     }
 
     public Insets getBorderInsets(Component c) {
-      return new Insets(2, 4, 2, 2);
+      return new Insets(0, 4, 0, 2);
     }
 
     public boolean isBorderOpaque() {
diff --git a/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandler.java b/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandler.java
index 4904b16..b9146bc 100644
--- a/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandler.java
+++ b/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandler.java
@@ -21,6 +21,8 @@
 
 public interface ExpandableItemsHandler<T> {
   void setEnabled(boolean enabled);
+  
+  boolean isEnabled();
 
   @NotNull
   Collection<T> getExpandedItems();
diff --git a/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandlerFactory.java b/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandlerFactory.java
index b9002b9..e6e2039 100644
--- a/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandlerFactory.java
+++ b/platform/platform-api/src/com/intellij/ui/ExpandableItemsHandlerFactory.java
@@ -58,6 +58,11 @@
     public void setEnabled(boolean enabled) {
     }
 
+    @Override
+    public boolean isEnabled() {
+      return false;
+    }
+
     @NotNull
     @Override
     public Collection<Object> getExpandedItems() {
diff --git a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
index 00300b3..8f46df3 100644
--- a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
+++ b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
@@ -15,7 +15,6 @@
  */
 package com.intellij.ui;
 
-import com.intellij.Patches;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.util.containers.WeakHashMap;
@@ -165,10 +164,6 @@
   }
 
   private static Insets calcInsets(GraphicsConfiguration gc) {
-    if (Patches.SUN_BUG_ID_9000030 && GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length > 1) {
-      return new Insets(0, 0, 0, 0);
-    }
-
     return Toolkit.getDefaultToolkit().getScreenInsets(gc);
   }
 
diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java
index 6b9a48d..56bab6e 100644
--- a/platform/platform-api/src/com/intellij/util/Alarm.java
+++ b/platform/platform-api/src/com/intellij/util/Alarm.java
@@ -253,9 +253,19 @@
     private Future<?> myFuture; // guarded by LOCK
     private final long myDelay;
 
-    private Request(@NotNull Runnable task, @Nullable ModalityState modalityState, long delayMillis) {
+    private Request(@NotNull final Runnable task, @Nullable ModalityState modalityState, long delayMillis) {
       synchronized (LOCK) {
-        myTask = task;
+        myTask = new Runnable() {
+          @Override
+          public void run() {
+            try {
+              task.run();
+            }
+            catch (Exception e) {
+              LOG.error("Exception in task " + task, e);
+            }
+          }
+        };
         myModalityState = modalityState;
         myDelay = delayMillis;
       }
@@ -284,16 +294,12 @@
               myFuture = null;
             }
 
-            try {
-              if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
-                SwingUtilities.invokeAndWait(task);
-              }
-              else {
-                task.run();
-              }
+            if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) {
+              //noinspection SSBasedInspection
+              SwingUtilities.invokeLater(task);
             }
-            catch (Exception e) {
-              LOG.error("Exception in task " + task, e);
+            else {
+              task.run();
             }
           }
         };
@@ -307,6 +313,7 @@
         else {
           final Application app = ApplicationManager.getApplication();
           if (app == null) {
+            //noinspection SSBasedInspection
             SwingUtilities.invokeLater(scheduledTask);
           }
           else {
diff --git a/platform/platform-api/src/com/intellij/util/PlatformUtils.java b/platform/platform-api/src/com/intellij/util/PlatformUtils.java
index b768cb4..ddc25df 100644
--- a/platform/platform-api/src/com/intellij/util/PlatformUtils.java
+++ b/platform/platform-api/src/com/intellij/util/PlatformUtils.java
@@ -56,6 +56,10 @@
     return RUBY_PREFIX.equals(getPlatformPrefix());
   }
 
+  public static boolean isCidr() {
+    return isAppCode() || isCppIde();
+  }
+
   public static boolean isAppCode() {
     return APPCODE_PREFIX.equals(getPlatformPrefix());
   }
diff --git a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
index aeccece..5368582 100644
--- a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
+++ b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
@@ -15,18 +15,18 @@
  */
 package org.jetbrains.ide;
 
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.http.HttpMethod;
-import org.jboss.netty.handler.codec.http.HttpRequest;
-import org.jboss.netty.handler.codec.http.QueryStringDecoder;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.QueryStringDecoder;
 
 import java.io.IOException;
 
 public abstract class HttpRequestHandler {
-  public boolean isSupported(HttpRequest request) {
+  public boolean isSupported(FullHttpRequest request) {
     return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD;
   }
 
-  public abstract boolean process(QueryStringDecoder urlDecoder, HttpRequest request, ChannelHandlerContext context)
+  public abstract boolean process(QueryStringDecoder urlDecoder, FullHttpRequest request, ChannelHandlerContext context)
     throws IOException;
 }
diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
index cfbe60e..2728c45 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
@@ -41,6 +41,6 @@
   }
 
   static boolean isApplicable() {
-    return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isAppCode() && !PlatformUtils.isCommunity();
+    return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils.isCommunity();
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
index f1c75e0..db1e782 100644
--- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
@@ -20,15 +20,14 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.CharsetToolkit;
 import gnu.trove.THashMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.QueryStringDecoder;
 import org.apache.xmlrpc.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBufferInputStream;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.http.HttpMethod;
-import org.jboss.netty.handler.codec.http.HttpRequest;
-import org.jboss.netty.handler.codec.http.HttpResponse;
-import org.jboss.netty.handler.codec.http.QueryStringDecoder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.ide.HttpRequestHandler;
@@ -57,13 +56,13 @@
 
   static final class XmlRpcRequestHandler extends HttpRequestHandler {
     @Override
-    public boolean isSupported(HttpRequest request) {
+    public boolean isSupported(FullHttpRequest request) {
       return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS;
     }
 
     @Override
-    public boolean process(QueryStringDecoder urlDecoder, HttpRequest request, ChannelHandlerContext context) throws IOException {
-      return SERVICE.getInstance().process(urlDecoder.getPath(), request, context, null);
+    public boolean process(QueryStringDecoder urlDecoder, FullHttpRequest request, ChannelHandlerContext context) throws IOException {
+      return SERVICE.getInstance().process(urlDecoder.path(), request, context, null);
     }
   }
 
@@ -83,14 +82,14 @@
   }
 
   @Override
-  public boolean process(@NotNull String path, @NotNull HttpRequest request, @NotNull ChannelHandlerContext context, @Nullable Map<String, Object> handlers) throws IOException {
+  public boolean process(@NotNull String path, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context, @Nullable Map<String, Object> handlers) throws IOException {
     if (!(path.isEmpty() || (path.length() == 1 && path.charAt(0) == '/') || path.equalsIgnoreCase("/RPC2"))) {
       return false;
     }
 
     if (request.getMethod() == HttpMethod.POST) {
-      ChannelBuffer result;
-      ChannelBufferInputStream in = new ChannelBufferInputStream(request.getContent());
+      ByteBuf result;
+      ByteBufInputStream in = new ByteBufInputStream(request.content());
       try {
         XmlRpcServerRequest xmlRpcServerRequest = new XmlRpcRequestProcessor().decodeRequest(in);
 
@@ -100,10 +99,10 @@
         }
 
         Object response = invokeHandler(getHandler(xmlRpcServerRequest.getMethodName(), handlers == null ? handlerMapping : handlers), xmlRpcServerRequest);
-        result = ChannelBuffers.copiedBuffer(new XmlRpcResponseProcessor().encodeResponse(response, CharsetToolkit.UTF8));
+        result = Unpooled.copiedBuffer(new XmlRpcResponseProcessor().encodeResponse(response, CharsetToolkit.UTF8));
       }
       catch (Throwable e) {
-        context.getChannel().close();
+        context.channel().close();
         LOG.error(e);
         return true;
       }
@@ -111,12 +110,10 @@
         in.close();
       }
 
-      HttpResponse response = Responses.create("text/xml");
-      response.setContent(result);
-      Responses.send(response, context.getChannel(), request);
+      Responses.send(Responses.response("text/xml", result), context.channel(), request);
       return true;
     }
-    else if (HttpMethod.POST.getName().equals(request.getHeader("Access-Control-Request-Method"))) {
+    else if (HttpMethod.POST.name().equals(request.headers().get("Access-Control-Request-Method"))) {
       LOG.assertTrue(request.getMethod() == HttpMethod.OPTIONS);
       Responses.sendOptionsResponse("POST, OPTIONS", request, context);
       return true;
diff --git a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
index 4f3954c7..e475b5b 100644
--- a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
@@ -78,7 +78,9 @@
 
   @Nullable
   private Object getDataFromProvider(@NotNull final DataProvider provider, @NotNull String dataId, @Nullable Set<String> alreadyComputedIds) {
-    if (alreadyComputedIds != null && alreadyComputedIds.contains(dataId)) return null;
+    if (alreadyComputedIds != null && alreadyComputedIds.contains(dataId)) {
+      return null;
+    }
     try {
       Object data = provider.getData(dataId);
       if (data != null) return validated(data, dataId, provider);
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/customization/ActionUrl.java b/platform/platform-impl/src/com/intellij/ide/ui/customization/ActionUrl.java
index 05f3e2d..aa9ea80 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/customization/ActionUrl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/customization/ActionUrl.java
@@ -276,4 +276,15 @@
   public void setGroupPath(final ArrayList<String> groupPath) {
     myGroupPath = groupPath;
   }
+
+  @Override
+  public String toString() {
+    return "ActionUrl{" +
+           "myGroupPath=" + myGroupPath +
+           ", myComponent=" + myComponent +
+           ", myActionType=" + myActionType +
+           ", myAbsolutePosition=" + myAbsolutePosition +
+           ", myInitialPosition=" + myInitialPosition +
+           '}';
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomActionsSchema.java b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomActionsSchema.java
index 04942ab..9359d31 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomActionsSchema.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomActionsSchema.java
@@ -21,6 +21,7 @@
 import com.intellij.openapi.actionSystem.ActionManager;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.components.ExportableComponent;
 import com.intellij.openapi.components.ServiceManager;
@@ -135,6 +136,10 @@
 
   public boolean isModified(CustomActionsSchema schema) {
     final ArrayList<ActionUrl> storedActions = schema.getActions();
+    if (ApplicationManager.getApplication().isUnitTestMode() && !storedActions.isEmpty()) {
+      System.err.println("stored: " + storedActions.toString());
+      System.err.println("actual: " + getActions().toString());
+    }
     if (storedActions.size() != getActions().size()) {
       return true;
     }
@@ -170,6 +175,9 @@
       url.readExternal((Element)groupElement);
       myActions.add(url);
     }
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      System.err.println("read custom actions: " + myActions.toString());
+    }
     readIcons(element);
   }
 
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index 5922749..bda380c 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -102,6 +102,8 @@
 
 SplitPane.highlight=3c3f41
 
+TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI
+
 Hyperlink.linkColor=589df6
 
 #List.background=45494A
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTreeUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTreeUI.java
new file mode 100644
index 0000000..b9190ea
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTreeUI.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ui.laf.darcula.ui;
+
+import com.intellij.util.ui.tree.WideSelectionTreeUI;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaTreeUI extends WideSelectionTreeUI {
+  @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+  public static ComponentUI createUI(JComponent c) {
+    return new DarculaTreeUI();
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
index 8d9768e..ffaee05 100644
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -105,6 +105,7 @@
     loadSystemLibraries(log);
 
     if (!Main.isHeadless()) {
+      AppUIUtil.patchSystem();
       AppUIUtil.updateWindowIcon(JOptionPane.getRootFrame());
       AppUIUtil.registerBundledFonts();
     }
@@ -275,7 +276,7 @@
                    DateFormatUtilRt.formatBuildDate(appInfo.getBuildDate()) + ")");
     log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ")");
     log.info("JRE: " + System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")");
-    log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.vendor", "-") + ")");
+    log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")");
 
     List<String> arguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
     if (arguments != null) {
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/OsInfoUsageCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/OsInfoUsageCollector.java
new file mode 100644
index 0000000..949cc36
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/OsInfoUsageCollector.java
@@ -0,0 +1,44 @@
+/*
+ * 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.internal.statistic;
+
+import com.intellij.internal.statistic.beans.GroupDescriptor;
+import com.intellij.internal.statistic.beans.UsageDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+
+/**
+ * @author peter
+ */
+public class OsInfoUsageCollector extends UsagesCollector {
+  @NotNull
+  @Override
+  public Set<UsageDescriptor> getUsages(@Nullable Project project) throws CollectUsagesException {
+    return ContainerUtil.newHashSet(new UsageDescriptor(SystemInfo.OS_NAME, 1),
+                                    new UsageDescriptor(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION, 1));
+  }
+
+  @NotNull
+  @Override
+  public GroupDescriptor getGroupId() {
+    return GroupDescriptor.create("user.os");
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java
index 272f80f..f4c792a 100644
--- a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java
+++ b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java
@@ -19,6 +19,7 @@
 import com.intellij.execution.impl.ConsoleViewUtil;
 import com.intellij.execution.impl.EditorHyperlinkSupport;
 import com.intellij.execution.ui.ConsoleViewContentType;
+import com.intellij.icons.AllIcons;
 import com.intellij.notification.impl.NotificationsManagerImpl;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.*;
@@ -88,7 +89,7 @@
 
     ((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true);
 
-    final ClearLog clearLog = new ClearLog();
+    final ClearLogAction clearLog = new ClearLogAction(this);
     clearLog.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.CONSOLE_CLEAR_ALL).getShortcutSet(), editor.getContentComponent());
 
     editor.addEditorMouseListener(new EditorPopupHandler() {
@@ -102,7 +103,7 @@
     return editor;
   }
 
-  private DefaultActionGroup createPopupActions(ActionManager actionManager, ClearLog action) {
+  private DefaultActionGroup createPopupActions(ActionManager actionManager, ClearLogAction action) {
     AnAction[] children = ((ActionGroup)actionManager.getAction(IdeActions.GROUP_CONSOLE_EDITOR_POPUP)).getChildren(null);
     DefaultActionGroup group = new DefaultActionGroup(children);
     group.addSeparator();
@@ -223,24 +224,27 @@
     document.insertString(document.getTextLength(), s);
   }
 
-  private class ClearLog extends DumbAwareAction {
-    public ClearLog() {
-      super("Clear All");
+  public static class ClearLogAction extends DumbAwareAction {
+    private EventLogConsole myConsole;
+
+    public ClearLogAction(EventLogConsole console) {
+      super("Clear All", "Clear the contents of the Event Log", AllIcons.Actions.GC);
+      myConsole = console;
     }
 
     @Override
     public void update(AnActionEvent e) {
-      final boolean enabled = e.getData(PlatformDataKeys.EDITOR) != null;
-      e.getPresentation().setEnabled(enabled);
-      e.getPresentation().setVisible(enabled);
+      Editor editor = e.getData(PlatformDataKeys.EDITOR);
+      e.getPresentation().setEnabled(editor != null && editor.getDocument().getTextLength() > 0);
     }
 
     public void actionPerformed(final AnActionEvent e) {
-      for (Notification notification : myProjectModel.getNotifications()) {
+      LogModel model = myConsole.myProjectModel;
+      for (Notification notification : model.getNotifications()) {
         notification.expire();
-        myProjectModel.removeNotification(notification);
+        model.removeNotification(notification);
       }
-      myProjectModel.setStatusMessage(null, 0);
+      model.setStatusMessage(null, 0);
       final Editor editor = e.getData(PlatformDataKeys.EDITOR);
       if (editor != null) {
         editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java
index 6db8dc7..b25c470 100644
--- a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java
+++ b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java
@@ -15,6 +15,8 @@
  */
 package com.intellij.notification;
 
+import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.ui.ConsoleView;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.actions.ContextHelpAction;
 import com.intellij.notification.impl.NotificationsConfigurable;
@@ -44,7 +46,8 @@
 public class EventLogToolWindowFactory implements ToolWindowFactory, DumbAware {
   @Override
   public void createToolWindowContent(final Project project, ToolWindow toolWindow) {
-    final Editor editor = EventLog.getProjectComponent(project).getConsole().getConsoleEditor();
+    EventLogConsole console = EventLog.getProjectComponent(project).getConsole();
+    final Editor editor = console.getConsoleEditor();
 
     SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true) {
       @Override
@@ -55,21 +58,22 @@
     panel.setContent(editor.getComponent());
     panel.addAncestorListener(new LogShownTracker(project));
 
-    ActionToolbar toolbar = createToolbar(project, editor);
-    toolbar.setTargetComponent(panel);
+    ActionToolbar toolbar = createToolbar(project, editor, console);
+    toolbar.setTargetComponent(editor.getContentComponent());
     panel.setToolbar(toolbar.getComponent());
 
     final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, "", false);
     toolWindow.getContentManager().addContent(content);
   }
 
-  private static ActionToolbar createToolbar(Project project, Editor editor) {
+  private static ActionToolbar createToolbar(Project project, Editor editor, EventLogConsole console) {
     DefaultActionGroup group = new DefaultActionGroup();
     group.add(new EditNotificationSettings(project));
     group.add(new DisplayBalloons());
     group.add(new ToggleSoftWraps(editor));
     group.add(new ScrollToTheEndToolbarAction(editor));
     group.add(new MarkAllAsRead(project));
+    group.add(new EventLogConsole.ClearLogAction(console));
     group.add(new ContextHelpAction(EventLog.HELP_ID));
 
     return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/TextDiffType.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/TextDiffType.java
index 29f4f97..6db2d74 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/TextDiffType.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/TextDiffType.java
@@ -120,7 +120,7 @@
   }
 
   @Nullable
-  public TextAttributes getTextAttributes(EditorColorsScheme scheme) {
+  public TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme) {
     return scheme.getAttributes(myAttributesKey);
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
index 2c47932..5ddbceed 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
@@ -19,14 +19,16 @@
 import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.project.DumbAwareAction;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author oleg
  */
-public class ScrollToTheEndToolbarAction extends AnAction {
+public class ScrollToTheEndToolbarAction extends DumbAwareAction {
   private final Editor myEditor;
 
   public ScrollToTheEndToolbarAction(@NotNull final Editor editor) {
@@ -39,6 +41,14 @@
   }
 
   @Override
+  public void update(AnActionEvent e) {
+    Document document = myEditor.getDocument();
+    int caretOffset = myEditor.getCaretModel().getOffset();
+    boolean isOnLastLine = document.getLineNumber(caretOffset) == document.getLineCount() - 1;
+    e.getPresentation().setEnabled(!isOnLastLine);
+  }
+
+  @Override
   public void actionPerformed(AnActionEvent e) {
     EditorUtil.scrollToTheEnd(myEditor);
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
index 795c65c..efc40e2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
@@ -117,6 +117,7 @@
       PrevNextActionsDescriptor descriptor = new PrevNextActionsDescriptor(IdeActions.ACTION_NEXT_EDITOR_TAB, IdeActions.ACTION_PREVIOUS_EDITOR_TAB);
       final TabbedPaneWrapper.AsJBTabs wrapper = new TabbedPaneWrapper.AsJBTabs(fileEditorManager.getProject(), SwingConstants.BOTTOM, descriptor, this);
       wrapper.getTabs().getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(1).setGhostsAlwaysVisible(true).setUiDecorator(new UiDecorator() {
+        @Override
         @NotNull
         public UiDecoration getDecoration() {
           return new UiDecoration(null, new Insets(0, 8, 0, 8));
@@ -126,14 +127,17 @@
 
       myTabbedPaneWrapper=wrapper;
       myComponent=new MyComponent(wrapper.getComponent()){
+        @Override
         public boolean requestFocusInWindow() {
           return wrapper.getComponent().requestFocusInWindow();
         }
 
+        @Override
         public void requestFocus() {
           wrapper.getComponent().requestFocus();
         }
 
+        @Override
         public boolean requestDefaultFocus() {
           return wrapper.getComponent().requestDefaultFocus();
         }
@@ -146,6 +150,7 @@
     else if(editors.length==1){
       myTabbedPaneWrapper=null;
       myComponent = new MyComponent(createEditorComponent(editors[0])){
+        @Override
         public void requestFocus() {
           JComponent component = editors[0].getPreferredFocusedComponent();
           if (component != null) {
@@ -153,6 +158,7 @@
           }
         }
 
+        @Override
         public boolean requestFocusInWindow() {
           JComponent component = editors[0].getPreferredFocusedComponent();
           if (component != null) {
@@ -162,6 +168,7 @@
           return false;
         }
 
+        @Override
         public boolean requestDefaultFocus() {
           JComponent component = editors[0].getPreferredFocusedComponent();
           if (component != null) {
@@ -383,6 +390,7 @@
    * Handles changes of selected myEditor
    */
   private final class MyChangeListener implements ChangeListener{
+    @Override
     public void stateChanged(ChangeEvent e) {
       FileEditor oldSelectedEditor = mySelectedEditor;
       LOG.assertTrue(oldSelectedEditor != null);
@@ -399,6 +407,7 @@
       add(realComponent, BorderLayout.CENTER);
     }
 
+    @Override
     public final Object getData(String dataId){
       if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
         return getSelectedEditor();
@@ -421,6 +430,7 @@
     }
   }
 
+  @Override
   public void dispose() {
     for (FileEditor editor : myEditors) {
       if (!Disposer.isDisposed(editor)) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
index a93a0bb..a608003 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
@@ -60,6 +60,7 @@
     uiSettings.addUISettingsListener(new MyUISettingsListener(), project);
   }
 
+  @Override
   public void projectOpened(){
 
     MessageBusConnection connection = myProject.getMessageBus().connect();
@@ -68,6 +69,7 @@
 
     StartupManager.getInstance(myProject).runWhenProjectIsInitialized(
       new DumbAwareRunnable() {
+        @Override
         public void run() {
           // myElement may be null if node that corresponds to this manager does not exist
           if (myElement != null) {
@@ -95,6 +97,7 @@
     );
   }
 
+  @Override
   @NotNull
   public String getComponentName(){
     return "editorHistoryManager";
@@ -305,6 +308,7 @@
     }
   }
 
+  @Override
   public void readExternal(final Element element) {
     // we have to delay xml processing because history entries require EditorStates to be created
     // which is done via corresponding EditorProviders, those are not accessible before their
@@ -312,6 +316,7 @@
     myElement = element.clone();
   }
 
+  @Override
   public void writeExternal(final Element element){
     // update history before saving
     final VirtualFile[] openFiles = FileEditorManager.getInstance(myProject).getOpenFiles();
@@ -331,10 +336,12 @@
    * Updates history
    */
   private final class MyEditorManagerListener extends FileEditorManagerAdapter{
+    @Override
     public void fileOpened(@NotNull final FileEditorManager source, @NotNull final VirtualFile file){
       fileOpenedImpl(file);
     }
 
+    @Override
     public void selectionChanged(@NotNull final FileEditorManagerEvent event){
       updateHistoryEntry(event.getOldFile(), event.getOldEditor(), event.getOldProvider(), false);
       updateHistoryEntry(event.getNewFile(), true);
@@ -352,6 +359,7 @@
    * Cuts/extends history length
    */
   private final class MyUISettingsListener implements UISettingsListener{
+    @Override
     public void uiSettingsChanged(final UISettings source) {
       trimToSize();
     }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
index 2db0bbd..51ebe7d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
@@ -86,11 +86,13 @@
     final ActionManager actionManager = ActionManager.getInstance();
     myTabs = new JBEditorTabs(project, actionManager, IdeFocusManager.getInstance(project), this);
     myTabs.setDataProvider(new MyDataProvider()).setPopupGroup(new Getter<ActionGroup>() {
+      @Override
       public ActionGroup get() {
         return (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_TAB_POPUP);
       }
     }, ActionPlaces.EDITOR_TAB_POPUP, false).setNavigationActionsEnabled(false).addTabMouseListener(new TabMouseListener()).getPresentation()
       .setTabDraggingEnabled(true).setUiDecorator(new UiDecorator() {
+      @Override
       @NotNull
       public UiDecoration getDecoration() {
         return new UiDecoration(null, new Insets(TabsUtil.TAB_VERTICAL_PADDING, 10, TabsUtil.TAB_VERTICAL_PADDING, 10));
@@ -98,6 +100,7 @@
     }).setTabLabelActionsMouseDeadzone(TimedDeadzone.NULL).setGhostsAlwaysVisible(true).setTabLabelActionsAutoHide(false)
       .setActiveTabFillIn(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground()).setPaintFocus(false).getJBTabs()
       .addListener(new TabsListener.Adapter() {
+        @Override
         public void selectionChanged(final TabInfo oldSelection, final TabInfo newSelection) {
           final FileEditorManager editorManager = FileEditorManager.getInstance(myProject);
           final FileEditor oldEditor = oldSelection != null ? editorManager.getSelectedEditor((VirtualFile)oldSelection.getObject()) : null;
@@ -142,16 +145,19 @@
     updateTabBorder();
 
     ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerAdapter() {
+      @Override
       public void stateChanged() {
         updateTabBorder();
       }
 
+      @Override
       public void toolWindowRegistered(@NotNull final String id) {
         updateTabBorder();
       }
     });
 
     UISettings.getInstance().addUISettingsListener(new UISettingsListener() {
+      @Override
       public void uiSettingsChanged(UISettings source) {
         updateTabBorder();
       }
@@ -354,6 +360,7 @@
       myTab = tab;
     }
 
+    @Override
     public void putInfo(@NotNull Map<String, String> info) {
       info.put("editorTab", myTab.getText());
     }
@@ -387,6 +394,7 @@
     return tab.getComponent();
   }
 
+  @Override
   public void dispose() {
 
   }
@@ -409,6 +417,7 @@
       e.getPresentation().setText("Close. Alt-click to close others.");
     }
 
+    @Override
     public void actionPerformed(final AnActionEvent e) {
       final FileEditorManagerEx mgr = FileEditorManagerEx.getInstanceEx(myProject);
       EditorWindow window;
@@ -434,6 +443,7 @@
   }
 
   private class MyDataProvider implements DataProvider {
+    @Override
     public Object getData(@NonNls final String dataId) {
       if (PlatformDataKeys.PROJECT.is(dataId)) {
         return myProject;
@@ -464,6 +474,7 @@
     }
   }
 
+  @Override
   public void close() {
     TabInfo selected = myTabs.getTargetInfo();
     if (selected == null) return;
@@ -533,6 +544,7 @@
   }
 
   private class MySwitchProvider implements SwitchProvider {
+    @Override
     public List<SwitchTarget> getTargets(final boolean onlyVisible, boolean originalProvider) {
       final ArrayList<SwitchTarget> result = new ArrayList<SwitchTarget>();
       TabInfo selected = myTabs.getSelectedInfo();
@@ -552,6 +564,7 @@
       return result;
     }
 
+    @Override
     public SwitchTarget getCurrentTarget() {
       TabInfo selected = myTabs.getSelectedInfo();
       final Ref<SwitchTarget> targetRef = new Ref<SwitchTarget>();
@@ -572,10 +585,12 @@
       return targetRef.get();
     }
 
+    @Override
     public JComponent getComponent() {
       return null;
     }
 
+    @Override
     public boolean isCycleRoot() {
       return false;
     }
@@ -589,7 +604,7 @@
     @Override
     public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
       final TabInfo previousSelection = info.getPreviousSelection();
-      final Image img = myTabs.getComponentImage(info);
+      final Image img = JBTabsImpl.getComponentImage(info);
       info.setHidden(true);
       if (previousSelection != null) {
         myTabs.select(previousSelection, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
index 752e23d..4207cab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
@@ -161,7 +161,7 @@
         boolean editorToTheDown = false;
 
         Splitter splitter = (Splitter)parent;
-        
+
         boolean vertical = splitter.getOrientation();
         if (vertical && splitter.getFirstComponent() == c) {
           editorToTheDown = true;
@@ -172,7 +172,7 @@
           if (splitter.getSecondComponent() == c) editorToTheLeft = true;
         }
 
-        
+
         //Frame frame = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, c);
         //if (frame instanceof IdeFrame) {
         //  Project project = ((IdeFrame)frame).getProject();
@@ -218,10 +218,10 @@
         int bottom = editorToTheDown ? 1 : 0;
         return new Insets(0, left, bottom, right);
       }
-      
+
       return new Insets(0, 0, 0, 0);
     }
-    
+
     @Nullable
     private static Splitter nextOuterSplitter(Component c) {
       Container parent = c.getParent();
@@ -290,6 +290,7 @@
   public void closeFile(final VirtualFile file, final boolean unsplit, final boolean transferFocus) {
     final FileEditorManagerImpl editorManager = getManager();
     editorManager.runChange(new FileEditorManagerChange() {
+      @Override
       public void run(EditorsSplitters splitters) {
         final List<EditorWithProviderComposite> editors = splitters.findEditorComposites(file);
         if (editors.isEmpty()) return;
@@ -308,6 +309,7 @@
               myRemovedTabs.push(Pair.create(file.getUrl(), componentIndex));
               final ActionCallback removeTab = myTabbedPane.removeTabAt(componentIndex, indexToSelect, transferFocus);
               final Runnable disposer = new Runnable() {
+                @Override
                 public void run() {
                   editorManager.disposeComposite(editor);
                 }
@@ -378,11 +380,11 @@
           return histFileIndex;
         }
       }
-    } else 
+    } else
     if (uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE && (fileIndex + 1 < myTabbedPane.getTabCount())) {
       return fileIndex + 1;
     }
-    
+
     // by default select previous neighbour
     if (fileIndex > 0) {
       return fileIndex - 1;
@@ -553,6 +555,7 @@
       return myWindow;
     }
 
+    @Override
     public Object getData(String dataId) {
       if (PlatformDataKeys.VIRTUAL_FILE.is(dataId)){
         final VirtualFile virtualFile = myEditor.getFile();
@@ -570,6 +573,7 @@
       super(window, editor);
     }
 
+    @Override
     public Object getData(String dataId) {
       // this is essential for ability to close opened file
       if (DATA_KEY.is(dataId)){
@@ -636,6 +640,7 @@
       final int index = findFileIndex(editor.getFile());
       if (index != -1) {
         UIUtil.invokeLaterIfNeeded(new Runnable() {
+          @Override
           public void run() {
             myTabbedPane.setSelectedIndex(index, focusEditor);
           }
@@ -663,12 +668,12 @@
         if (initialIndex == null) {
           int selectedIndex = myTabbedPane.getSelectedIndex();
           if (selectedIndex >= 0) {
-            indexToInsert = UISettings.getInstance().ACTIVATE_RIGHT_EDITOR_ON_CLOSE ? selectedIndex : selectedIndex + 1; 
+            indexToInsert = UISettings.getInstance().ACTIVATE_RIGHT_EDITOR_ON_CLOSE ? selectedIndex : selectedIndex + 1;
           }
         } else {
           indexToInsert = initialIndex;
         }
-        
+
         final VirtualFile file = editor.getFile();
         final Icon template = AllIcons.FileTypes.Text;
         myTabbedPane.insertTab(file, new EmptyIcon(template.getIconWidth(), template.getIconHeight()), new TComp(this, editor), null, indexToInsert);
@@ -709,7 +714,7 @@
         myPanel.setOpaque(false);
         myPanel.setBorder(new AdaptiveBorder());
         myPanel.setOpaque(false);
-        
+
         final Splitter splitter = new Splitter(orientation == JSplitPane.VERTICAL_SPLIT, 0.5f, 0.1f, 0.9f);
         final EditorWindow res = new EditorWindow(myOwner);
         if (myTabbedPane != null) {
@@ -772,7 +777,7 @@
 
   /**
    * Tries to setup caret and viewport for the given editor from the selected one.
-   * 
+   *
    * @param toSync    editor to setup caret and viewport for
    */
   private void syncCaretIfPossible(@Nullable FileEditor[] toSync) {
@@ -809,6 +814,7 @@
         scrollingModel.scrollVertically(scrollOffset);
 
         SwingUtilities.invokeLater(new Runnable() {
+          @Override
           public void run() {
             if (!editor.isDisposed()) {
               scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
index 6f10c4a..f3ccbef 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
@@ -47,6 +47,7 @@
     return myProviders;
   }
 
+  @Override
   public boolean isModified() {
     final FileEditor [] editors = getEditors ();
     for (FileEditor editor : editors) {
@@ -57,6 +58,7 @@
     return false;
   }
 
+  @Override
   @NotNull
   public Pair<FileEditor, FileEditorProvider> getSelectedEditorWithProvider() {
     LOG.assertTrue(myEditors.length > 0, myEditors.length);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
index db07ac7..381daf8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
@@ -479,6 +479,7 @@
     myFilesToUpdateIconsFor.add(file);
     myIconUpdaterAlarm.cancelAllRequests();
     myIconUpdaterAlarm.addRequest(new Runnable() {
+      @Override
       public void run() {
         if (myManager.getProject().isDisposed()) return;
         for (VirtualFile file : myFilesToUpdateIconsFor) {
@@ -650,6 +651,7 @@
   }
 
   private final class MyFocusTraversalPolicy extends IdeFocusTraversalPolicy {
+    @Override
     public final Component getDefaultComponentImpl(final Container focusCycleRoot) {
       if (myCurrentWindow != null) {
         final EditorWithProviderComposite selectedEditor = myCurrentWindow.getSelectedEditor();
@@ -708,6 +710,7 @@
     final EditorWithProviderComposite newEditor = window != null? window.getSelectedEditor() : null;
 
     Runnable fireRunnable = new Runnable() {
+      @Override
       public void run() {
         getManager().fireSelectionChanged(newEditor);
       }
@@ -824,6 +827,7 @@
   }
 
   private final class MyFocusWatcher extends FocusWatcher {
+    @Override
     protected void focusedComponentChanged(final Component component, final AWTEvent cause) {
       EditorWindow newWindow = null;
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index bdafe4d..f31f4b4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -159,6 +159,7 @@
 
   //-------------------------------------------------------------------------------
 
+  @Override
   public JComponent getComponent() {
     initUI();
     return myPanels;
@@ -279,6 +280,7 @@
     }
   }
 
+  @Override
   public JComponent getPreferredFocusedComponent() {
     assertReadAccess();
     final EditorWindow window = getSplitters().getCurrentWindow();
@@ -312,6 +314,7 @@
     return FileUtil.getLocationRelativeToUserHome(file.getPresentableUrl());
   }
 
+  @Override
   public void updateFilePresentation(@NotNull VirtualFile file) {
     if (!isFileOpen(file)) return;
 
@@ -357,10 +360,12 @@
     // Queue here is to prevent title flickering when tab is being closed and two events arriving: with component==null and component==next focused tab
     // only the last event makes sense to handle
     myQueue.queue(new Update("UpdateFileName " + (file == null ? "" : file.getPath())) {
+      @Override
       public boolean isExpired() {
         return myProject.isDisposed() || !myProject.isOpen() || (file == null ? super.isExpired() : !file.isValid());
       }
 
+      @Override
       public void run() {
         Set<EditorsSplitters> all = getAllSplitters();
         for (EditorsSplitters each : all) {
@@ -373,6 +378,7 @@
   //-------------------------------------------------------
 
 
+  @Override
   public VirtualFile getFile(@NotNull final FileEditor editor) {
     final EditorComposite editorComposite = getEditorComposite(editor);
     if (editorComposite != null) {
@@ -381,6 +387,7 @@
     return null;
   }
 
+  @Override
   public void unsplitWindow() {
     final EditorWindow currentWindow = getActiveSplitters(true).getResult().getCurrentWindow();
     if (currentWindow != null) {
@@ -388,6 +395,7 @@
     }
   }
 
+  @Override
   public void unsplitAllWindow() {
     final EditorWindow currentWindow = getActiveSplitters(true).getResult().getCurrentWindow();
     if (currentWindow != null) {
@@ -407,6 +415,7 @@
     return getWindowSplitCount() > 1;
   }
 
+  @Override
   @NotNull
   public EditorWindow[] getWindows() {
     ArrayList<EditorWindow> windows = new ArrayList<EditorWindow>();
@@ -419,6 +428,7 @@
     return windows.toArray(new EditorWindow[windows.size()]);
   }
 
+  @Override
   public EditorWindow getNextWindow(@NotNull final EditorWindow window) {
     final EditorWindow[] windows = getSplitters().getOrderedWindows();
     for (int i = 0; i != windows.length; ++i) {
@@ -430,6 +440,7 @@
     return null;
   }
 
+  @Override
   public EditorWindow getPrevWindow(@NotNull final EditorWindow window) {
     final EditorWindow[] windows = getSplitters().getOrderedWindows();
     for (int i = 0; i != windows.length; ++i) {
@@ -441,6 +452,7 @@
     return null;
   }
 
+  @Override
   public void createSplitter(final int orientation, @Nullable final EditorWindow window) {
     // window was available from action event, for example when invoked from the tab menu of an editor that is not the 'current'
     if (window != null) {
@@ -455,6 +467,7 @@
     }
   }
 
+  @Override
   public void changeSplitterOrientation() {
     final EditorWindow currentWindow = getSplitters().getCurrentWindow();
     if (currentWindow != null) {
@@ -463,6 +476,7 @@
   }
 
 
+  @Override
   public void flipTabs() {
     /*
     if (myTabs == null) {
@@ -480,6 +494,7 @@
     myPanels.revalidate();
   }
 
+  @Override
   public boolean tabsMode() {
     return false;
   }
@@ -492,20 +507,24 @@
   }
 
 
+  @Override
   public boolean isInSplitter() {
     final EditorWindow currentWindow = getSplitters().getCurrentWindow();
     return currentWindow != null && currentWindow.inSplitter();
   }
 
+  @Override
   public boolean hasOpenedFile() {
     final EditorWindow currentWindow = getSplitters().getCurrentWindow();
     return currentWindow != null && currentWindow.getSelectedEditor() != null;
   }
 
+  @Override
   public VirtualFile getCurrentFile() {
     return getActiveSplitters(true).getResult().getCurrentFile();
   }
 
+  @Override
   @NotNull
   public AsyncResult<EditorWindow> getActiveWindow() {
     return _getActiveWindow(false);
@@ -524,10 +543,12 @@
     return result;
   }
 
+  @Override
   public EditorWindow getCurrentWindow() {
     return _getActiveWindow(true).getResult();
   }
 
+  @Override
   public void setCurrentWindow(final EditorWindow window) {
     getActiveSplitters(true).getResult().setCurrentWindow(window, true);
   }
@@ -536,6 +557,7 @@
     assertDispatchThread();
 
     CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+      @Override
       public void run() {
         if (window.isFileOpen(file)) {
           window.closeFile(file, true, transferFocus);
@@ -552,12 +574,14 @@
     removeSelectionRecord(file, window);
   }
 
+  @Override
   public void closeFile(@NotNull final VirtualFile file, @NotNull final EditorWindow window) {
     closeFile(file, window, true);
   }
 
   //============================= EditorManager methods ================================
 
+  @Override
   public void closeFile(@NotNull final VirtualFile file) {
     closeFile(file, true, false);
   }
@@ -571,6 +595,7 @@
     }
 
     CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+      @Override
       public void run() {
         closeFileImpl(file, moveFocus, closeAllCopies);
       }
@@ -582,6 +607,7 @@
   private void closeFileImpl(@NotNull final VirtualFile file, final boolean moveFocus, boolean closeAllCopies) {
     assertDispatchThread();
     runChange(new FileEditorManagerChange() {
+      @Override
       public void run(EditorsSplitters splitters) {
         splitters.closeFile(file, moveFocus);
       }
@@ -590,6 +616,7 @@
 
   //-------------------------------------- Open File ----------------------------------------
 
+  @Override
   @NotNull
   public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull final VirtualFile file,
                                                                         final boolean focusEditor,
@@ -697,6 +724,7 @@
                                                                 final boolean focusEditor) {
     final Ref<Pair<FileEditor[], FileEditorProvider[]>> result = new Ref<Pair<FileEditor[], FileEditorProvider[]>>();
     CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+      @Override
       public void run() {
         result.set(openFileImpl3(window, file, focusEditor, null, true));
       }
@@ -711,7 +739,6 @@
    *                invalid file become selected. That's why we do not require that
    *                passed file is valid.
    * @param entry   map between FileEditorProvider and FileEditorState. If this parameter
-   * @param current
    */
   @NotNull
   Pair<FileEditor[], FileEditorProvider[]> openFileImpl3(@NotNull final EditorWindow window,
@@ -757,6 +784,7 @@
       providers = editorProviderManager.getProviders(myProject, file);
       if (DumbService.getInstance(myProject).isDumb()) {
         final List<FileEditorProvider> dumbAware = ContainerUtil.findAll(providers, new Condition<FileEditorProvider>() {
+          @Override
           public boolean value(FileEditorProvider fileEditorProvider) {
             return DumbService.isDumbAware(fileEditorProvider);
           }
@@ -873,6 +901,7 @@
     window.getOwner().afterFileOpen(file);
 
     UIUtil.invokeLaterIfNeeded(new Runnable() {
+      @Override
       public void run() {
         newSelectedComposite.getSelectedEditor().selectNotify();
       }
@@ -1008,6 +1037,7 @@
     return newComposite;
   }
 
+  @Override
   @NotNull
   public List<FileEditor> openEditor(@NotNull final OpenFileDescriptor descriptor, final boolean focusEditor) {
     assertDispatchThread();
@@ -1021,6 +1051,7 @@
 
     final List<FileEditor> result = new ArrayList<FileEditor>();
     CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+      @Override
       public void run() {
         VirtualFile file = descriptor.getFile();
         final FileEditor[] editors = openFile(file, focusEditor, !descriptor.isUseCurrentWindow());
@@ -1075,11 +1106,13 @@
     }
   }
 
+  @Override
   @NotNull
   public Project getProject() {
     return myProject;
   }
 
+  @Override
   @Nullable
   public Editor openTextEditor(@NotNull final OpenFileDescriptor descriptor, final boolean focusEditor) {
     final Collection<FileEditor> fileEditors = openEditor(descriptor, focusEditor);
@@ -1098,6 +1131,7 @@
     return editor;
   }
 
+  @Override
   public Editor getSelectedTextEditor() {
     assertReadAccess();
 
@@ -1113,10 +1147,12 @@
   }
 
 
+  @Override
   public boolean isFileOpen(@NotNull final VirtualFile file) {
     return !getEditorComposites(file).isEmpty();
   }
 
+  @Override
   @NotNull
   public VirtualFile[] getOpenFiles() {
     HashSet<VirtualFile> openFiles = new HashSet<VirtualFile>();
@@ -1127,6 +1163,7 @@
     return VfsUtilCore.toVirtualFileArray(openFiles);
   }
 
+  @Override
   @NotNull
   public VirtualFile[] getSelectedFiles() {
     HashSet<VirtualFile> selectedFiles = new HashSet<VirtualFile>();
@@ -1137,6 +1174,7 @@
     return VfsUtilCore.toVirtualFileArray(selectedFiles);
   }
 
+  @Override
   @NotNull
   public FileEditor[] getSelectedEditors() {
     HashSet<FileEditor> selectedEditors = new HashSet<FileEditor>();
@@ -1147,12 +1185,14 @@
     return selectedEditors.toArray(new FileEditor[selectedEditors.size()]);
   }
 
+  @Override
   @NotNull
   public EditorsSplitters getSplitters() {
     EditorsSplitters active = getActiveSplitters(true).getResult();
     return active == null ? getMainSplitters() : active;
   }
 
+  @Override
   @Nullable
   public FileEditor getSelectedEditor(@NotNull final VirtualFile file) {
     final Pair<FileEditor, FileEditorProvider> selectedEditorWithProvider = getSelectedEditorWithProvider(file);
@@ -1160,6 +1200,7 @@
   }
 
 
+  @Override
   @Nullable
   public Pair<FileEditor, FileEditorProvider> getSelectedEditorWithProvider(@NotNull VirtualFile file) {
     if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
@@ -1172,6 +1213,7 @@
     return composites.isEmpty() ? null : composites.get(0).getSelectedEditorWithProvider();
   }
 
+  @Override
   @NotNull
   public Pair<FileEditor[], FileEditorProvider[]> getEditorsWithProviders(@NotNull final VirtualFile file) {
     assertReadAccess();
@@ -1190,6 +1232,7 @@
     }
   }
 
+  @Override
   @NotNull
   public FileEditor[] getEditors(@NotNull VirtualFile file) {
     assertReadAccess();
@@ -1240,6 +1283,7 @@
     return result;
   }
 
+  @Override
   @NotNull
   public FileEditor[] getAllEditors() {
     assertReadAccess();
@@ -1255,14 +1299,17 @@
     return result.toArray(new FileEditor[result.size()]);
   }
 
+  @Override
   public void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent) {
     addTopComponent(editor, annotationComponent);
   }
 
+  @Override
   public void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent) {
     removeTopComponent(editor, annotationComponent);
   }
 
+  @Override
   public void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) {
     final EditorComposite composite = getEditorComposite(editor);
     if (composite != null) {
@@ -1270,6 +1317,7 @@
     }
   }
 
+  @Override
   public void removeTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) {
     final EditorComposite composite = getEditorComposite(editor);
     if (composite != null) {
@@ -1277,6 +1325,7 @@
     }
   }
 
+  @Override
   public void addBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) {
     final EditorComposite composite = getEditorComposite(editor);
     if (composite != null) {
@@ -1284,6 +1333,7 @@
     }
   }
 
+  @Override
   public void removeBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) {
     final EditorComposite composite = getEditorComposite(editor);
     if (composite != null) {
@@ -1293,20 +1343,24 @@
 
   private final MessageListenerList<FileEditorManagerListener> myListenerList;
 
+  @Override
   public void addFileEditorManagerListener(@NotNull final FileEditorManagerListener listener) {
     myListenerList.add(listener);
   }
 
+  @Override
   public void addFileEditorManagerListener(@NotNull final FileEditorManagerListener listener, @NotNull final Disposable parentDisposable) {
     myListenerList.add(listener, parentDisposable);
   }
 
+  @Override
   public void removeFileEditorManagerListener(@NotNull final FileEditorManagerListener listener) {
     myListenerList.remove(listener);
   }
 
 // ProjectComponent methods
 
+  @Override
   public void projectOpened() {
     //myFocusWatcher.install(myWindows.getComponent ());
     getMainSplitters().startListeningFocus();
@@ -1336,16 +1390,20 @@
     UISettings.getInstance().addUISettingsListener(myUISettingsListener, myProject);
 
     StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() {
+      @Override
       public void run() {
 
         setTabsMode(UISettings.getInstance().EDITOR_TAB_PLACEMENT != UISettings.TABS_NONE);
 
         ToolWindowManager.getInstance(myProject).invokeLater(new Runnable() {
+          @Override
           public void run() {
             CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+              @Override
               public void run() {
 
                 LaterInvocator.invokeLater(new Runnable() {
+                  @Override
                   public void run() {
                     long currentTime = System.nanoTime();
                     Long startTime = myProject.getUserData(ProjectImpl.CREATION_TIME);
@@ -1364,6 +1422,7 @@
     });
   }
 
+  @Override
   public void projectClosed() {
     //myFocusWatcher.deinstall(myWindows.getComponent ());
     getMainSplitters().dispose();
@@ -1375,23 +1434,28 @@
 
 // BaseCompomemnt methods
 
+  @Override
   @NotNull
   public String getComponentName() {
     return FILE_EDITOR_MANAGER;
   }
 
+  @Override
   public void initComponent() {
 
   }
 
+  @Override
   public void disposeComponent() { /* really do nothing */ }
 
 //JDOMExternalizable methods
 
+  @Override
   public void writeExternal(final Element element) {
     getMainSplitters().writeExternal(element);
   }
 
+  @Override
   public void readExternal(final Element element) {
     getMainSplitters().readExternal(element);
   }
@@ -1481,6 +1545,7 @@
     return new Trinity<VirtualFile, FileEditor, FileEditorProvider>(file, editor, provider);
   }
 
+  @Override
   public boolean isChanged(@NotNull final EditorComposite editor) {
     final FileStatusManager fileStatusManager = FileStatusManager.getInstance(myProject);
     if (fileStatusManager != null) {
@@ -1559,6 +1624,7 @@
    * Closes deleted files. Closes file which are in the deleted directories.
    */
   private final class MyVirtualFileListener extends VirtualFileAdapter {
+    @Override
     public void beforeFileDeletion(VirtualFileEvent e) {
       assertDispatchThread();
 
@@ -1573,6 +1639,7 @@
       }
     }
 
+    @Override
     public void propertyChanged(VirtualFilePropertyEvent e) {
       if (VirtualFile.PROP_NAME.equals(e.getPropertyName())) {
         assertDispatchThread();
@@ -1602,6 +1669,7 @@
       }
     }
 
+    @Override
     public void fileMoved(VirtualFileMoveEvent e) {
       final VirtualFile file = e.getFile();
       final VirtualFile[] openFiles = getOpenFiles();
@@ -1626,11 +1694,13 @@
     return true;
   }
 
+  @Override
   public boolean isInsideChange() {
     return getSplitters().isInsideChange();
   }
 
   private final class MyEditorPropertyChangeListener implements PropertyChangeListener {
+    @Override
     public void propertyChange(final PropertyChangeEvent e) {
       assertDispatchThread();
 
@@ -1662,6 +1732,7 @@
    * Gets events from VCS and updates color of myEditor tabs
    */
   private final class MyFileStatusListener implements FileStatusListener {
+    @Override
     public void fileStatusesChanged() { // update color of all open files
       assertDispatchThread();
       LOG.debug("FileEditorManagerImpl.MyFileStatusListener.fileStatusesChanged()");
@@ -1670,6 +1741,7 @@
         final VirtualFile file = openFiles[i];
         LOG.assertTrue(file != null);
         ApplicationManager.getApplication().invokeLater(new Runnable() {
+          @Override
           public void run() {
             if (LOG.isDebugEnabled()) {
               LOG.debug("updating file status in tab for " + file.getPath());
@@ -1680,6 +1752,7 @@
       }
     }
 
+    @Override
     public void fileStatusChanged(@NotNull final VirtualFile file) { // update color of the file (if necessary)
       assertDispatchThread();
       if (isFileOpen(file)) {
@@ -1710,6 +1783,7 @@
   }
 
   private class MyRootsListener extends ModuleRootAdapter {
+    @Override
     public void rootsChanged(ModuleRootEvent event) {
       EditorFileSwapper[] swappers = Extensions.getExtensions(EditorFileSwapper.EP_NAME);
 
@@ -1762,6 +1836,7 @@
    * and EDITOR_TAB_LIMIT, etc values.
    */
   private final class MyUISettingsListener implements UISettingsListener {
+    @Override
     public void uiSettingsChanged(final UISettings source) {
       assertDispatchThread();
       setTabsMode(source.EDITOR_TAB_PLACEMENT != UISettings.TABS_NONE && !UISettings.getInstance().PRESENTATION_MODE);
@@ -1790,6 +1865,7 @@
     }
   }
 
+  @Override
   public void closeAllFiles() {
     final VirtualFile[] openFiles = getSplitters().getOpenFiles();
     for (VirtualFile openFile : openFiles) {
@@ -1797,6 +1873,7 @@
     }
   }
 
+  @Override
   @NotNull
   public VirtualFile[] getSiblings(@NotNull VirtualFile file) {
     return getOpenFiles();
@@ -1804,6 +1881,7 @@
 
   protected void queueUpdateFile(final VirtualFile file) {
     myQueue.queue(new Update(file) {
+      @Override
       public void run() {
         if (isFileOpen(file)) {
           updateFileIcon(file);
@@ -1815,6 +1893,7 @@
     });
   }
 
+  @Override
   public EditorsSplitters getSplittersFor(Component c) {
     EditorsSplitters splitters = null;
     DockContainer dockContainer = myDockManager.getContainerFor(c);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
index c363256..9483073 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
@@ -57,10 +57,12 @@
   public FileEditorProviderManagerImpl(FileEditorProvider[] providers) {
     Extensions.getRootArea().getExtensionPoint(FileEditorProvider.EP_FILE_EDITOR_PROVIDER).addExtensionPointListener(
       new ExtensionPointListener<FileEditorProvider>() {
+        @Override
         public void extensionAdded(@NotNull final FileEditorProvider extension, @Nullable final PluginDescriptor pluginDescriptor) {
           registerProvider(extension);
         }
 
+        @Override
         public void extensionRemoved(@NotNull final FileEditorProvider extension, @Nullable final PluginDescriptor pluginDescriptor) {
           unregisterProvider(extension);
         }
@@ -74,6 +76,7 @@
   public FileEditorProviderManagerImpl() {
   }
 
+  @Override
   @NotNull
   public synchronized FileEditorProvider[] getProviders(@NotNull final Project project, @NotNull final VirtualFile file){
     // Collect all possible editors
@@ -113,6 +116,7 @@
     }
   }
 
+  @Override
   @Nullable
   public synchronized FileEditorProvider getProvider(@NotNull String editorTypeId){
     for(int i=myProviders.size()-1;i>=0;i--){
@@ -211,6 +215,7 @@
              : Double.MAX_VALUE;
     }
 
+    @Override
     public int compare(FileEditorProvider provider1, FileEditorProvider provider2) {
       final int i1 = provider1.getPolicy().ordinal();
       final int i2 = provider2.getPolicy().ordinal();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/MoveEditorToOppositeTabGroupAction.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/MoveEditorToOppositeTabGroupAction.java
index 557c65b..0fe8fef 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/MoveEditorToOppositeTabGroupAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/MoveEditorToOppositeTabGroupAction.java
@@ -27,6 +27,7 @@
  */
 public class MoveEditorToOppositeTabGroupAction extends AnAction implements DumbAware {
 
+  @Override
   public void actionPerformed(final AnActionEvent event) {
     final DataContext dataContext = event.getDataContext();
     final VirtualFile vFile = PlatformDataKeys.VIRTUAL_FILE.getData(dataContext);
@@ -46,6 +47,7 @@
     }
   }
 
+  @Override
   public void update(AnActionEvent e) {
     final Presentation presentation = e.getPresentation();
     final DataContext dataContext = e.getDataContext();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectNextEditorTabAction.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectNextEditorTabAction.java
index 15dfa39..63c44ab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectNextEditorTabAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectNextEditorTabAction.java
@@ -26,6 +26,7 @@
 // The only purpose of this action is to serve as placeholder for assigning keyboard shortcuts.
 // For actual tab switching code, see EditorComposite constructor.
 public class SelectNextEditorTabAction extends AnAction implements DumbAware {
+  @Override
   public void actionPerformed(final AnActionEvent e) {
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectPreviousEditorTabAction.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectPreviousEditorTabAction.java
index 3f17ddf..d601179 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectPreviousEditorTabAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/SelectPreviousEditorTabAction.java
@@ -26,6 +26,7 @@
 // The only purpose of this action is to serve as placeholder for assigning keyboard shortcuts.
 // For actual tab switching code, see EditorComposite constructor.
 public class SelectPreviousEditorTabAction extends AnAction implements DumbAware {
+  @Override
   public void actionPerformed(final AnActionEvent e) {
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
index 7958c1c..db45506e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
@@ -88,6 +88,7 @@
           @Override
           public void run() {
             CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+              @Override
               public void run() {
                 if (CharArrayUtil.containsOnlyWhiteSpaces(content.subSequence(start, end)) && doStrip) {
                   document.deleteString(start, end);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java
index 52e9d3a..e9e1968 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/WaverGraphicsDecorator.java
@@ -57,275 +57,342 @@
     }
   }
 
+  @Override
   public void draw(final Shape s) {
     myOriginal.draw(s);
   }
 
+  @Override
   public boolean drawImage(final Image img, final AffineTransform xform, final ImageObserver obs) {
     return myOriginal.drawImage(img, xform, obs);
   }
 
+  @Override
   public void drawImage(final BufferedImage img, final BufferedImageOp op, final int x, final int y) {
     myOriginal.drawImage(img, op, x, y);
   }
 
+  @Override
   public void drawRenderedImage(final RenderedImage img, final AffineTransform xform) {
     myOriginal.drawRenderedImage(img, xform);
   }
 
+  @Override
   public void drawRenderableImage(final RenderableImage img, final AffineTransform xform) {
     myOriginal.drawRenderableImage(img, xform);
   }
 
+  @Override
   public void drawString(final String str, final int x, final int y) {
     myOriginal.drawString(str, x, y);
     drawWave(str, x, y);
   }
 
+  @Override
   public void drawString(final String s, final float x, final float y) {
     myOriginal.drawString(s, x, y);
     drawWave(s, (int)x, (int)y);
   }
 
+  @Override
   public void drawString(final AttributedCharacterIterator iterator, final int x, final int y) {
     myOriginal.drawString(iterator, x, y);
     //TODO: drawWave
   }
 
+  @Override
   public void drawString(final AttributedCharacterIterator iterator, final float x, final float y) {
     myOriginal.drawString(iterator, x, y);
     //TODO: drawWave
   }
 
+  @Override
   public void drawGlyphVector(final GlyphVector g, final float x, final float y) {
     myOriginal.drawGlyphVector(g, x, y);
     //TODO: drawWave
   }
 
+  @Override
   public void fill(final Shape s) {
     myOriginal.fill(s);
   }
 
+  @Override
   public boolean hit(final Rectangle rect, final Shape s, final boolean onStroke) {
     return myOriginal.hit(rect, s, onStroke);
   }
 
+  @Override
   public GraphicsConfiguration getDeviceConfiguration() {
     return myOriginal.getDeviceConfiguration();
   }
 
+  @Override
   public void setComposite(final Composite comp) {
     myOriginal.setComposite(comp);
   }
 
+  @Override
   public void setPaint(final Paint paint) {
     myOriginal.setPaint(paint);
   }
 
+  @Override
   public void setStroke(final Stroke s) {
     myOriginal.setStroke(s);
   }
 
+  @Override
   public void setRenderingHint(final RenderingHints.Key hintKey, final Object hintValue) {
     myOriginal.setRenderingHint(hintKey, hintValue);
   }
 
+  @Override
   public Object getRenderingHint(final RenderingHints.Key hintKey) {
     return myOriginal.getRenderingHint(hintKey);
   }
 
+  @Override
   public void setRenderingHints(final Map<?, ?> hints) {
     myOriginal.setRenderingHints(hints);
   }
 
+  @Override
   public void addRenderingHints(final Map<?, ?> hints) {
     myOriginal.addRenderingHints(hints);
   }
 
+  @Override
   public RenderingHints getRenderingHints() {
     return myOriginal.getRenderingHints();
   }
 
+  @Override
   public void translate(final int x, final int y) {
     myOriginal.translate(x, y);
   }
 
+  @Override
   public void translate(final double tx, final double ty) {
     myOriginal.translate(tx, ty);
   }
 
+  @Override
   public void rotate(final double theta) {
     myOriginal.rotate(theta);
   }
 
+  @Override
   public void rotate(final double theta, final double x, final double y) {
     myOriginal.rotate(theta, x, y);
   }
 
+  @Override
   public void scale(final double sx, final double sy) {
     myOriginal.scale(sx, sy);
   }
 
+  @Override
   public void shear(final double shx, final double shy) {
     myOriginal.shear(shx, shy);
   }
 
+  @Override
   public void transform(final AffineTransform Tx) {
     myOriginal.transform(Tx);
   }
 
+  @Override
   public void setTransform(final AffineTransform Tx) {
     myOriginal.setTransform(Tx);
   }
 
+  @Override
   public AffineTransform getTransform() {
     return myOriginal.getTransform();
   }
 
+  @Override
   public Paint getPaint() {
     return myOriginal.getPaint();
   }
 
+  @Override
   public Composite getComposite() {
     return myOriginal.getComposite();
   }
 
+  @Override
   public void setBackground(final Color color) {
     myOriginal.setBackground(color);
   }
 
+  @Override
   public Color getBackground() {
     return myOriginal.getBackground();
   }
 
+  @Override
   public Stroke getStroke() {
     return myOriginal.getStroke();
   }
 
+  @Override
   public void clip(final Shape s) {
     myOriginal.clip(s);
   }
 
+  @Override
   public FontRenderContext getFontRenderContext() {
     return myOriginal.getFontRenderContext();
   }
 
+  @Override
   public Graphics create() {
     return new WaverGraphicsDecorator((Graphics2D)myOriginal.create(), myWaveColor);
   }
 
+  @Override
   public Color getColor() {
     return myOriginal.getColor();
   }
 
+  @Override
   public void setColor(final Color c) {
     myOriginal.setColor(c);
   }
 
+  @Override
   public void setPaintMode() {
     myOriginal.setPaintMode();
   }
 
+  @Override
   public void setXORMode(final Color c1) {
     myOriginal.setXORMode(c1);
   }
 
+  @Override
   public Font getFont() {
     return myOriginal.getFont();
   }
 
+  @Override
   public void setFont(final Font font) {
     myOriginal.setFont(font);
   }
 
+  @Override
   public FontMetrics getFontMetrics(final Font f) {
     return myOriginal.getFontMetrics(f);
   }
 
+  @Override
   public Rectangle getClipBounds() {
     return myOriginal.getClipBounds();
   }
 
+  @Override
   public void clipRect(final int x, final int y, final int width, final int height) {
     myOriginal.clipRect(x, y, width, height);
   }
 
+  @Override
   public void setClip(final int x, final int y, final int width, final int height) {
     myOriginal.setClip(x, y, width, height);
   }
 
+  @Override
   public Shape getClip() {
     return myOriginal.getClip();
   }
 
+  @Override
   public void setClip(final Shape clip) {
     myOriginal.setClip(clip);
   }
 
+  @Override
   public void copyArea(final int x, final int y, final int width, final int height, final int dx, final int dy) {
     myOriginal.copyArea(x, y, width, height, dx, dy);
   }
 
+  @Override
   public void drawLine(final int x1, final int y1, final int x2, final int y2) {
     myOriginal.drawLine(x1, y1, x2, y2);
   }
 
+  @Override
   public void fillRect(final int x, final int y, final int width, final int height) {
     myOriginal.fillRect(x, y, width, height);
   }
 
+  @Override
   public void clearRect(final int x, final int y, final int width, final int height) {
     myOriginal.clearRect(x, y, width, height);
   }
 
+  @Override
   public void drawRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) {
     myOriginal.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
   }
 
+  @Override
   public void fillRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) {
     myOriginal.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
   }
 
+  @Override
   public void drawOval(final int x, final int y, final int width, final int height) {
     myOriginal.drawOval(x, y, width, height);
   }
 
+  @Override
   public void fillOval(final int x, final int y, final int width, final int height) {
     myOriginal.fillOval(x, y, width, height);
   }
 
+  @Override
   public void drawArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) {
     myOriginal.drawArc(x, y, width, height, startAngle, arcAngle);
   }
 
+  @Override
   public void fillArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) {
     myOriginal.fillArc(x, y, width, height, startAngle, arcAngle);
   }
 
+  @Override
   public void drawPolyline(final int[] xPoints, final int[] yPoints, final int nPoints) {
     myOriginal.drawPolyline(xPoints, yPoints, nPoints);
   }
 
+  @Override
   public void drawPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) {
     myOriginal.drawPolygon(xPoints, yPoints, nPoints);
   }
 
+  @Override
   public void fillPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) {
     myOriginal.fillPolygon(xPoints, yPoints, nPoints);
   }
 
+  @Override
   public boolean drawImage(final Image img, final int x, final int y, final ImageObserver observer) {
     return myOriginal.drawImage(img, x, y, observer);
   }
 
+  @Override
   public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final ImageObserver observer) {
     return myOriginal.drawImage(img, x, y, width, height, observer);
   }
 
+  @Override
   public boolean drawImage(final Image img, final int x, final int y, final Color bgcolor, final ImageObserver observer) {
     return myOriginal.drawImage(img, x, y, bgcolor, observer);
   }
 
+  @Override
   public boolean drawImage(final Image img,
                            final int x,
                            final int y,
@@ -336,6 +403,7 @@
     return myOriginal.drawImage(img, x, y, width, height, bgcolor, observer);
   }
 
+  @Override
   public boolean drawImage(final Image img,
                            final int dx1,
                            final int dy1,
@@ -349,6 +417,7 @@
     return myOriginal.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
   }
 
+  @Override
   public boolean drawImage(final Image img,
                            final int dx1,
                            final int dy1,
@@ -363,47 +432,58 @@
     return myOriginal.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
   }
 
+  @Override
   public void dispose() {
     //myOriginal.dispose();
   }
 
 
+  @Override
   public Rectangle getClipRect() {
     return myOriginal.getClipRect();
   }
 
+  @Override
   public boolean hitClip(final int x, final int y, final int width, final int height) {
     return myOriginal.hitClip(x, y, width, height);
   }
 
+  @Override
   public Rectangle getClipBounds(final Rectangle r) {
     return myOriginal.getClipBounds(r);
   }
 
+  @Override
   public void fill3DRect(final int x, final int y, final int width, final int height, final boolean raised) {
     myOriginal.fill3DRect(x, y, width, height, raised);
   }
 
+  @Override
   public void draw3DRect(final int x, final int y, final int width, final int height, final boolean raised) {
     myOriginal.draw3DRect(x, y, width, height, raised);
   }
 
+  @Override
   public Graphics create(final int x, final int y, final int width, final int height) {
     return new WaverGraphicsDecorator((Graphics2D)myOriginal.create(x, y, width, height), myWaveColor);
   }
 
+  @Override
   public void drawRect(final int x, final int y, final int width, final int height) {
     myOriginal.drawRect(x, y, width, height);
   }
 
+  @Override
   public void drawPolygon(final Polygon p) {
     myOriginal.drawPolygon(p);
   }
 
+  @Override
   public void fillPolygon(final Polygon p) {
     myOriginal.fillPolygon(p);
   }
 
+  @Override
   public FontMetrics getFontMetrics() {
     return myOriginal.getFontMetrics();
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
index ac57802..956998c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
@@ -47,11 +47,13 @@
     myPanel = new RemoteFilePanel(project, virtualFile);
   }
 
+  @Override
   @NotNull
   public JComponent getComponent() {
     return myPanel.getMainPanel();
   }
 
+  @Override
   public JComponent getPreferredFocusedComponent() {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -60,11 +62,13 @@
     return myPanel.getMainPanel();
   }
 
+  @Override
   @NotNull
   public String getName() {
     return "Http";
   }
 
+  @Override
   @NotNull
   public Editor getEditor() {
     final TextEditor fileEditor = myPanel.getFileEditor();
@@ -77,6 +81,7 @@
     return myMockTextEditor;
   }
 
+  @Override
   @NotNull
   public FileEditorState getState(@NotNull final FileEditorStateLevel level) {
     final TextEditor textEditor = myPanel.getFileEditor();
@@ -86,6 +91,7 @@
     return new TextEditorState();
   }
 
+  @Override
   public void setState(@NotNull final FileEditorState state) {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -93,30 +99,37 @@
     }
   }
 
+  @Override
   public boolean isModified() {
     return false;
   }
 
+  @Override
   public boolean isValid() {
     return true;
   }
 
+  @Override
   public void selectNotify() {
     myPanel.selectNotify();
   }
 
+  @Override
   public void deselectNotify() {
     myPanel.deselectNotify();
   }
 
+  @Override
   public void addPropertyChangeListener(@NotNull final PropertyChangeListener listener) {
     myPanel.addPropertyChangeListener(listener);
   }
 
+  @Override
   public void removePropertyChangeListener(@NotNull final PropertyChangeListener listener) {
     myPanel.removePropertyChangeListener(listener);
   }
 
+  @Override
   public BackgroundEditorHighlighter getBackgroundHighlighter() {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -125,6 +138,7 @@
     return null;
   }
 
+  @Override
   public boolean canNavigateTo(@NotNull Navigatable navigatable) {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -133,6 +147,7 @@
     return false;
   }
 
+  @Override
   public void navigateTo(@NotNull Navigatable navigatable) {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -140,6 +155,7 @@
     }
   }
 
+  @Override
   public <T> T getUserData(@NotNull Key<T> key) {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -148,6 +164,7 @@
     return myUserDataHolder.getUserData(key);
   }
 
+  @Override
   public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -158,6 +175,7 @@
     }
   }
 
+  @Override
   public FileEditorLocation getCurrentLocation() {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -166,6 +184,7 @@
     return null;
   }
 
+  @Override
   public StructureViewBuilder getStructureViewBuilder() {
     final TextEditor textEditor = myPanel.getFileEditor();
     if (textEditor != null) {
@@ -174,6 +193,7 @@
     return null;
   }
 
+  @Override
   public void dispose() {
     if (myMockTextEditor != null) {
       EditorFactory.getInstance().releaseEditor(myMockTextEditor);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
index 58a2f90..17354c7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
@@ -32,32 +32,39 @@
  * @author nik
  */
 public class HttpFileEditorProvider implements FileEditorProvider, DumbAware {
+  @Override
   public boolean accept(@NotNull final Project project, @NotNull final VirtualFile file) {
     return file instanceof HttpVirtualFile && !file.isDirectory();
   }
 
+  @Override
   @NotNull
   public FileEditor createEditor(@NotNull final Project project, @NotNull final VirtualFile file) {
-    return new HttpFileEditor(project, (HttpVirtualFile)file); 
+    return new HttpFileEditor(project, (HttpVirtualFile)file);
   }
 
+  @Override
   public void disposeEditor(@NotNull final FileEditor editor) {
     Disposer.dispose(editor);
   }
 
+  @Override
   @NotNull
   public FileEditorState readState(@NotNull final Element sourceElement, @NotNull final Project project, @NotNull final VirtualFile file) {
     return new TextEditorState();
   }
 
+  @Override
   public void writeState(@NotNull final FileEditorState state, @NotNull final Project project, @NotNull final Element targetElement) {
   }
 
+  @Override
   @NotNull
   public String getEditorTypeId() {
     return "httpFileEditor";
   }
 
+  @Override
   @NotNull
   public FileEditorPolicy getPolicy() {
     return FileEditorPolicy.HIDE_DEFAULT_EDITOR;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java
index 5211c89..972ac67 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java
@@ -45,10 +45,12 @@
   }
 
 
+  @Override
   public boolean canHandleDrop(final DataFlavor[] transferFlavors) {
     return transferFlavors != null && FileCopyPasteUtil.isFileListFlavorSupported(transferFlavors);
   }
 
+  @Override
   public void handleDrop(@NotNull final Transferable t, @Nullable final Project project, EditorWindow editorWindow) {
     if (project == null || !FileCopyPasteUtil.isFileListFlavorSupported(t)) {
       return;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/LargeFileEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/LargeFileEditorProvider.java
index afaf715..cf3411b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/LargeFileEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/LargeFileEditorProvider.java
@@ -36,6 +36,7 @@
  */
 public class LargeFileEditorProvider implements FileEditorProvider, DumbAware {
 
+  @Override
   public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
     if (file.isDirectory() || !file.isValid()) {
       return false;
@@ -43,28 +44,34 @@
     return SingleRootFileViewProvider.isTooLargeForContentLoading(file);
   }
 
+  @Override
   @NotNull
   public FileEditor createEditor(@NotNull Project project, @NotNull final VirtualFile file) {
     return new LargeFileEditor(file);
   }
 
+  @Override
   public void disposeEditor(@NotNull FileEditor editor) {
     Disposer.dispose(editor);
   }
 
+  @Override
   @NotNull
   public FileEditorState readState(@NotNull Element element, @NotNull Project project, @NotNull VirtualFile file) {
     return FileEditorState.INSTANCE;
   }
 
+  @Override
   public void writeState(@NotNull FileEditorState _state, @NotNull Project project, @NotNull Element element) {
   }
 
+  @Override
   @NotNull
   public String getEditorTypeId() {
     return "LargeFileEditor";
   }
 
+  @Override
   @NotNull
   public FileEditorPolicy getPolicy() {
     return FileEditorPolicy.NONE;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java
index d0ed91c..145aba5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java
@@ -16,7 +16,6 @@
 package com.intellij.openapi.fileTypes.impl;
 
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.newvfs.BulkFileListener;
@@ -35,11 +34,10 @@
  * @author peter
  */
 class IgnoredFileCache {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileTypes.impl.IgnoredFileCache");
   private final BitSet myCheckedIds = new BitSet();
   private final TIntHashSet myIgnoredIds = new TIntHashSet();
   private final IgnoredPatternSet myIgnoredPatterns;
-  private boolean myEnableCache = true;
+  private int myVfsEventNesting = 0;
 
   IgnoredFileCache(IgnoredPatternSet ignoredPatterns) {
     myIgnoredPatterns = ignoredPatterns;
@@ -48,17 +46,14 @@
       @Override
       public void before(@NotNull List<? extends VFileEvent> events) {
         // during VFS event processing the system may be in inconsistent state, don't cache it
-        if (!myEnableCache) {
-          LOG.error("VFS before event received without a matching after: " + events);
-        }
-        myEnableCache = false;
+        myVfsEventNesting++;
         clearCacheForChangedFiles(events);
       }
 
       @Override
       public void after(@NotNull List<? extends VFileEvent> events) {
         clearCacheForChangedFiles(events);
-        myEnableCache = true;
+        myVfsEventNesting--;
       }
 
       private void clearCacheForChangedFiles(List<? extends VFileEvent> events) {
@@ -98,7 +93,7 @@
   }
 
   boolean isFileIgnored(VirtualFile file) {
-    if (!myEnableCache || !(file instanceof NewVirtualFile)) {
+    if (myVfsEventNesting == 0 || !(file instanceof NewVirtualFile)) {
       return isFileIgnoredNoCache(file);
     }
 
@@ -113,7 +108,7 @@
       }
     }
 
-    boolean result = isFileIgnoredNoCache(file);;
+    boolean result = isFileIgnoredNoCache(file);
     synchronized (myCheckedIds) {
       myCheckedIds.set(id);
       if (result) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
index 50aee94..3fb8bcf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
@@ -166,6 +166,29 @@
     return myCurrentModalProgressCount.get() > 0;
   }
 
+  @Override
+  public void runProcess(@NotNull final Runnable process, final ProgressIndicator progress) {
+    executeProcessUnderProgress(new Runnable(){
+      @Override
+      public void run() {
+        try {
+          if (progress != null && !progress.isRunning()) {
+            progress.start();
+          }
+          process.run();
+          maybeSleep();
+        }
+        finally {
+          if (progress != null && progress.isRunning()) {
+            progress.stop();
+            if (progress instanceof ProgressIndicatorEx) {
+              ((ProgressIndicatorEx)progress).processFinish();
+            }
+          }
+        }
+      }
+    },progress);
+  }
 
   @Override
   public <T> T runProcess(@NotNull final Computable<T> process, ProgressIndicator progress) throws ProcessCanceledException {
@@ -413,36 +436,6 @@
     }
   }
 
-  @Override
-   public void runProcess(@NotNull final Runnable process, final ProgressIndicator progress) {
-     executeProcessUnderProgress(new Runnable(){
-       @Override
-       public void run() {
-         synchronized (process) {
-           process.notifyAll();
-         }
-         try {
-           if (progress != null && !progress.isRunning()) {
-             progress.start();
-           }
-           process.run();
-           maybeSleep();
-         }
-         finally {
-           if (progress != null && progress.isRunning()) {
-             progress.stop();
-             if (progress instanceof ProgressIndicatorEx) {
-               ((ProgressIndicatorEx)progress).processFinish();
-             }
-             synchronized (process) {
-               process.notifyAll();
-             }
-           }
-         }
-       }
-     },progress);
-   }
-
   private abstract static class TaskContainer implements Runnable {
     private final Task myTask;
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
index 6693ca3..b616efd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
@@ -26,7 +26,7 @@
 import com.intellij.openapi.progress.*;
 import com.intellij.openapi.progress.util.ProgressIndicatorBase;
 import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.ShutDownTracker;
 import com.intellij.openapi.wm.AppIconScheme;
 import com.intellij.openapi.wm.IdeFrame;
@@ -144,7 +144,7 @@
       }
       try {
         final int size = runner.queryNeededFiles(indicator);
-        if (application.isHeadlessEnvironment() || (size + runner.getNumberOfPendingUpdateJobs(indicator)) < 50) {
+        if (size + runner.getNumberOfPendingUpdateJobs(indicator) < 50) {
           // If not that many files found, process them on the spot, avoiding entering dumb mode
           // Consider number of pending tasks as well, because they may take noticeable time to process even if the number of files is small
           try {
@@ -176,37 +176,38 @@
           return;
         }
         // ok to test and set the flag like this, because the change is always done from dispatch thread
-        final boolean wasDumb = myDumb;
-        if (!wasDumb) {
-          // always change dumb status inside write action.
-          // This will ensure all active read actions are completed before the app goes dumb
-          final Ref<Boolean> startFailure = new Ref<Boolean>(Boolean.FALSE);
-          application.runWriteAction(new Runnable() {
-            public void run() {
-              myDumb = true;
-              try {
-                myPublisher.enteredDumbMode();
-              }
-              catch (Throwable e) {
-                LOG.error(e);
-              }
-              finally {
-                try {
-                  updateRunnable.run();
-                }
-                catch (Throwable e) {
-                  startFailure.set(Boolean.TRUE);
-                  LOG.error("Failed to start background index update task", e);
-                }
-              }
-            }
-          });
-          if (startFailure.get()) {
-            updateFinished();
-          }
+        if (myDumb) {
+          myUpdatesQueue.addLast(updateRunnable);
         }
         else {
-          myUpdatesQueue.addLast(updateRunnable);
+          // always change dumb status inside write action.
+          // This will ensure all active read actions are completed before the app goes dumb
+          boolean startSuccess =
+            application.runWriteAction(new Computable<Boolean>() {
+              @Override
+              public Boolean compute() {
+                myDumb = true;
+                try {
+                  myPublisher.enteredDumbMode();
+                }
+                catch (Throwable e) {
+                  LOG.error(e);
+                }
+                finally {
+                  try {
+                    updateRunnable.run();
+                  }
+                  catch (Throwable e) {
+                    LOG.error("Failed to start background index update task", e);
+                    return false;
+                  }
+                }
+                return true;
+              }
+            });
+          if (!startSuccess) {
+            updateFinished();
+          }
         }
       }
     });
@@ -254,7 +255,7 @@
     });
   }
 
-  private static final Ref<CacheUpdateRunner> NULL_ACTION = new Ref<CacheUpdateRunner>(null);
+  private static final CacheUpdateRunner NULL_ACTION = new CacheUpdateRunner(null,null);
 
   public void waitForSmartMode() {
     final Application application = ApplicationManager.getApplication();
@@ -389,14 +390,14 @@
           }
         }
 
-        @Nullable 
+        @Nullable
         private CacheUpdateRunner getNextUpdateRunner() {
-          final BlockingQueue<Ref<CacheUpdateRunner>> actionQueue = new LinkedBlockingQueue<Ref<CacheUpdateRunner>>();
+          final BlockingQueue<CacheUpdateRunner> actionQueue = new LinkedBlockingQueue<CacheUpdateRunner>();
           UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() {
             public void run() {
               IndexUpdateRunnable nextRunnable = getNextUpdateFromQueue();
               try {
-                actionQueue.offer(nextRunnable == null ? NULL_ACTION : new Ref<CacheUpdateRunner>(nextRunnable.myAction));
+                actionQueue.offer(nextRunnable == null ? NULL_ACTION : nextRunnable.myAction);
               }
               finally {
                 if (nextRunnable == null) {
@@ -409,9 +410,9 @@
           // try to obtain the next action or terminate if no actions left
           while (!myProject.isDisposed()) {
             try {
-              Ref<CacheUpdateRunner> ref = actionQueue.poll(500L, TimeUnit.MILLISECONDS);
+              CacheUpdateRunner ref = actionQueue.poll(500L, TimeUnit.MILLISECONDS);
               if (ref != null) {
-                return ref.get();
+                return ref == NULL_ACTION ? null : ref;
               }
             }
             catch (InterruptedException e) {
@@ -421,7 +422,7 @@
           return null;
         }
 
-        @Nullable 
+        @Nullable
         private IndexUpdateRunnable getNextUpdateFromQueue() {
           try {
             return myUpdatesQueue.isEmpty()? null : myUpdatesQueue.pullFirst();
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java b/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
index 70e4870..543efbf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.UIBundle;
 import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 
@@ -52,34 +53,42 @@
     return error(project, message, UIBundle.message("error.dialog.title"));
   }
 
+  @NotNull
   public static MessageInfo error(Project project, String message, String title) {
     return new MessageInfo(project, message, title);
   }
 
-  public static abstract class BaseDialogInfo<ThisClass extends BaseDialogInfo> {
-    private Project myProject;
+  public abstract static class BaseDialogInfo<ThisClass extends BaseDialogInfo> {
+    private final Project myProject;
     private String myMessage;
     private String myTitle;
     private Icon myIcon;
-    private String[] myOptions = new String[]{CommonBundle.getOkButtonText()};
+    private String[] myOptions = {CommonBundle.getOkButtonText()};
     private int myDefaultOption = 0;
 
     protected BaseDialogInfo(Project project) {
       myProject = project;
     }
 
-    public BaseDialogInfo(Project project, String message, String title, Icon icon) {
+    public BaseDialogInfo(Project project, @NotNull String message, String title, Icon icon) {
       this(project);
       myMessage = message;
       myTitle = title;
       myIcon = icon;
     }
 
-    public ThisClass setTitle(String title) { myTitle = title; return getThis(); }
+    @NotNull
+    public ThisClass setTitle(String title) {
+      myTitle = title;
+      return getThis();
+    }
 
-    public String getMessage() { return myMessage; }
+    public String getMessage() {
+      return myMessage;
+    }
 
-    public ThisClass appendMessage(String message) {
+    @NotNull
+    public ThisClass appendMessage(@NotNull String message) {
       myMessage += message;
       return getThis();
     }
@@ -89,11 +98,16 @@
       myDefaultOption = defaultOption;
     }
 
+    @NotNull
     protected abstract ThisClass getThis();
 
-    public ThisClass setIcon(Icon icon) { myIcon = icon; return getThis(); }
+    @NotNull
+    public ThisClass setIcon(Icon icon) {
+      myIcon = icon;
+      return getThis();
+    }
 
-    public void setMessage(String message) {
+    public void setMessage(@NotNull String message) {
       myMessage = message;
     }
 
@@ -129,11 +143,11 @@
 
     public void showLater() {
       ApplicationManager.getApplication().invokeLater(new Runnable() {
+          @Override
           public void run() {
-            if (ApplicationManager.getApplication().isDisposed()) return;
             showNow();
           }
-        });
+        }, ApplicationManager.getApplication().getDisposed());
     }
 
     public int askYesNo() {
@@ -146,6 +160,8 @@
       return showNow();
     }
 
+    @NotNull
+    @Override
     protected MessageInfo getThis() {
       return this;
     }
@@ -161,6 +177,8 @@
       setOptions(new String[]{CommonBundle.getOkButtonText()}, 0);
     }
 
+    @NotNull
+    @Override
     public ChoiceInfo getThis() {
       return this;
     }
@@ -171,6 +189,7 @@
       return getThis();
     }
 
+    @Override
     public UserInput askUser() {
       ChooseDialog dialog = new ChooseDialog(getProject(), getMessage(), getTitle(), getIcon(), myChoises, myDefaultChoice, getOptions(), getDefaultOption());
       dialog.setValidator(null);
@@ -209,12 +228,15 @@
       setOptions(new String[]{CommonBundle.getOkButtonText(), CommonBundle.getCancelButtonText()}, 0);
     }
 
+    @Override
     public UserInput askUser() {
       InputDialog dialog = new InputDialog(getProject(), getMessage(), getTitle(), getIcon(), myDefaultValue, null, getOptions(), getDefaultOption());
       dialog.show();
       return new UserInput(dialog.getTextField().getText(), dialog.getExitCode());
     }
 
+    @NotNull
+    @Override
     public InputInfo getThis() {
       return this;
     }
@@ -224,7 +246,7 @@
     }
   }
 
-  public static abstract class BaseInputInfo<ThisClass extends BaseInputInfo> extends BaseDialogInfo<ThisClass> {
+  public abstract static class BaseInputInfo<ThisClass extends BaseInputInfo> extends BaseDialogInfo<ThisClass> {
 
 
     public BaseInputInfo(Project project) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
index e09e48c..8663013 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
@@ -419,14 +419,7 @@
     final DumbService.DumbModeListener dumbModeListener = new DumbService.DumbModeListener() {
       @Override
       public void enteredDumbMode() {
-        for (final String id : getToolWindowIds()) {
-          if (!myDumbAwareIds.contains(id)) {
-            if (isToolWindowVisible(id)) {
-              hideToolWindow(id, true);
-            }
-            getStripeButton(id).setEnabled(false);
-          }
-        }
+        disableStripeButtons();
       }
 
       @Override
@@ -443,7 +436,7 @@
       public void run() {
         registerToolWindowsFromBeans();
         if (DumbService.getInstance(myProject).isDumb()) {
-          dumbModeListener.enteredDumbMode();
+          disableStripeButtons();
         }
       }
     });
@@ -459,6 +452,17 @@
     }, myProject);
   }
 
+  private void disableStripeButtons() {
+    for (final String id : getToolWindowIds()) {
+      if (!myDumbAwareIds.contains(id)) {
+        if (isToolWindowVisible(id)) {
+          hideToolWindow(id, true);
+        }
+        getStripeButton(id).setEnabled(false);
+      }
+    }
+  }
+
   private JComponent createEditorComponent(Project project) {
     return FrameEditorComponentProvider.EP.getExtensions()[0].createEditorComponent(project);
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
index caa0487..06b00ea 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
@@ -244,7 +244,7 @@
 
   @SuppressWarnings("SpellCheckingInspection")
   public static void patchDetectedWm(String wmName) {
-    if (X11 == null || Registry.is("idea.x11.skip.wm.patching")) return;
+    if (X11 == null || !Registry.is("ide.x11.override.wm")) return;
 
     try {
       if (wmName.startsWith("Mutter") || "Muffin".equals(wmName) || "GNOME Shell".equals(wmName)) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
index a1deb69..ad42294 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
@@ -95,7 +95,7 @@
   StatusPanel() {
     super(new BorderLayout());
 
-    setOpaque(isOpaque() && !SystemInfo.isMac);
+    setOpaque(false);
 
     myTextPanel.setBorder(new EmptyBorder(0, 5, 0, 0));
     new ClickListener() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
index 1ebb011..225bbf0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
@@ -19,15 +19,20 @@
 import com.intellij.ide.IdeEventQueue;
 import com.intellij.ide.ui.UISettings;
 import com.intellij.ide.ui.UISettingsListener;
+import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.openapi.Disposable;
+import com.intellij.openapi.ui.popup.Balloon;
 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.Disposer;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.wm.*;
 import com.intellij.openapi.wm.impl.IdeFrameImpl;
 import com.intellij.openapi.wm.impl.ToolWindowImpl;
+import com.intellij.ui.GotItMessage;
 import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.UIBundle;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.ui.components.JBLabel;
 import com.intellij.ui.components.JBList;
@@ -146,16 +151,18 @@
 
           final Dimension size = list.getPreferredSize();
           final JComponent c = ToolWindowsWidget.this;
-          final RelativePoint point = new RelativePoint(c, new Point(-4, -4 - size.height));
-
+          final Insets padding = UIUtil.getListViewportPadding();
+          final RelativePoint point = new RelativePoint(c, new Point(-4, -padding.top - padding.bottom -4 - size.height));
 
           if (popup != null && popup.isVisible()) {
             return;
           }
 
           list.setSelectedIndex(list.getItemsCount() - 1);
-          popup = JBPopupFactory.getInstance().createListPopupBuilder(list)
+          PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(list);
+          popup = builder
             .setAutoselectOnMouseMove(true)
+            .setRequestFocus(false)
             .setItemChoosenCallback(new Runnable() {
               @Override
               public void run() {
@@ -175,6 +182,26 @@
   }
 
   @Override
+  public void addNotify() {
+    super.addNotify();
+    final String key = "toolwindow.stripes.buttons.info.shown";
+    if (UISettings.getInstance().HIDE_TOOL_STRIPES && !PropertiesComponent.getInstance().isTrueValue(key)) {
+      final Alarm alarm = new Alarm();
+      alarm.addRequest(new Runnable() {
+        @Override
+        public void run() {
+          GotItMessage.createMessage(UIBundle.message("tool.window.quick.access.title"), UIBundle.message(
+            "tool.window.quick.access.message"))
+            .setDisposable(ToolWindowsWidget.this)
+            .show(new RelativePoint(ToolWindowsWidget.this, new Point(10, 0)), Balloon.Position.above);
+            PropertiesComponent.getInstance().setValue(key, String.valueOf(true));
+          Disposer.dispose(alarm);
+        }
+      }, 10000);
+    }
+  }
+
+  @Override
   public void propertyChange(PropertyChangeEvent evt) {
     updateIcon();
   }
@@ -262,5 +289,6 @@
     Disposer.dispose(this);
     KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener("focusOwner", this);
     myStatusBar = null;
+    popup = null;
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index e4f1171..8cc9b3d 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -159,6 +159,11 @@
     if (!myEnabled) hideHint();
   }
 
+  @Override
+  public boolean isEnabled() {
+    return myEnabled;
+  }
+
   @NotNull
   @Override
   public Collection<KeyType> getExpandedItems() {
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index a9eefcb..ce65d0e 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.ui;
 
+import com.intellij.Patches;
 import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -25,6 +26,7 @@
 import com.intellij.openapi.ui.popup.Balloon;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.ToolWindowManager;
 import com.intellij.util.PlatformUtils;
@@ -47,6 +49,21 @@
 public class AppUIUtil {
   private static final String VENDOR_PREFIX = "jetbrains-";
 
+  public static void patchSystem() {
+    if (Patches.SUN_BUG_ID_9000030 && Registry.is("ide.x11.suppress.xinerama")) {
+      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+      if (ge.getScreenDevices().length > 1) {
+        try {
+          @SuppressWarnings("SpellCheckingInspection") Field xinerState = ge.getClass().getDeclaredField("xinerState");
+          xinerState.setAccessible(true);
+          xinerState.set(null, Boolean.FALSE);
+          Logger.getInstance(AppUIUtil.class).info("Xinerama detection suppressed");
+        }
+        catch (Exception ignored) { }
+      }
+    }
+  }
+
   public static void updateWindowIcon(@NotNull Window window) {
     window.setIconImages(getAppIconImages());
   }
diff --git a/platform/platform-impl/src/com/intellij/ui/GotItMessage.java b/platform/platform-impl/src/com/intellij/ui/GotItMessage.java
new file mode 100644
index 0000000..6580d0c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/GotItMessage.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 com.intellij.ui;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.BalloonBuilder;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GotItMessage {
+  @NotNull private final String myTitle;
+  @NotNull private final String myMessage;
+  private Runnable myCallback;
+  private Disposable myDisposable;
+  private boolean myShowCallout = true;
+
+  private GotItMessage(@NotNull String title,
+                       @NotNull String message                       ) {
+    myTitle = title;
+    final String[] lines = message.split("\n");
+    if (lines.length > 1) {
+      myMessage = "<html><div align='center'>" + message.replace("\n", "<br>") + "</div></html>";
+    } else {
+      myMessage = message;
+    }
+  }
+
+  public static GotItMessage createMessage(@NotNull String title,
+                                           @NotNull String message) {
+    return new GotItMessage(title, message);
+  }
+
+  public GotItMessage setDisposable(Disposable disposable) {
+    myDisposable = disposable;
+    return this;
+  }
+
+  public GotItMessage setCallback(Runnable callback) {
+    myCallback = callback;
+    return this;
+  }
+
+  public GotItMessage setShowCallout(boolean showCallout) {
+    myShowCallout = showCallout;
+    return this;
+  }
+
+  public void show(RelativePoint point, Balloon.Position position) {
+    final GotItPanel panel = new GotItPanel();
+    panel.myTitle.setText(myTitle);
+    panel.myMessage.setText(myMessage);
+
+    panel.myButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+    final BalloonBuilder builder = JBPopupFactory.getInstance().createBalloonBuilder(panel.myRoot);
+    if (myDisposable != null) {
+      builder.setDisposable(myDisposable);
+    }
+
+    final Balloon balloon = builder
+      .setFillColor(UIUtil.getListBackground())
+      .setHideOnClickOutside(false)
+      .setHideOnAction(false)
+      .setHideOnFrameResize(false)
+      .setHideOnKeyOutside(false)
+      .setShowCallout(myShowCallout)
+      .createBalloon();
+    panel.myButton.addMouseListener(new MouseAdapter() {
+      @Override
+      public void mouseClicked(MouseEvent e) {
+        balloon.hide();
+        if (myCallback != null) {
+          myCallback.run();
+        }
+      }
+    });
+
+    balloon.show(point, position);
+  }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/GotItPanel.form b/platform/platform-impl/src/com/intellij/ui/GotItPanel.form
new file mode 100644
index 0000000..0fda696
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/GotItPanel.form
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ui.GotItPanel">
+  <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="4" left="5" bottom="4" right="5"/>
+    <constraints>
+      <xy x="20" y="20" width="442" height="177"/>
+    </constraints>
+    <properties>
+      <opaque value="false"/>
+    </properties>
+    <border type="none"/>
+    <children>
+      <component id="6805" class="javax.swing.JLabel" binding="myTitle">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <font size="20"/>
+          <text value="Title"/>
+        </properties>
+      </component>
+      <vspacer id="a3eac">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
+      <component id="1102e" class="javax.swing.JLabel" binding="myMessage">
+        <constraints>
+          <grid row="1" 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>
+          <font size="12"/>
+          <text value="Text text text text"/>
+        </properties>
+      </component>
+      <grid id="fd7bc" 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="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <opaque value="false"/>
+        </properties>
+        <border type="none"/>
+        <children>
+          <grid id="50d71" binding="myButton" custom-create="true" layout-manager="BorderLayout" hgap="0" vgap="0">
+            <constraints>
+              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <background color="-16750951"/>
+              <opaque value="false"/>
+            </properties>
+            <border type="empty">
+              <size top="2" left="10" bottom="2" right="8"/>
+            </border>
+            <children>
+              <component id="366a9" class="javax.swing.JLabel">
+                <constraints border-constraint="Center"/>
+                <properties>
+                  <font size="12" style="1"/>
+                  <foreground color="-1"/>
+                  <text resource-bundle="messages/UIBundle" key="got.it"/>
+                </properties>
+              </component>
+            </children>
+          </grid>
+          <hspacer id="a87ad">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+            </constraints>
+          </hspacer>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>
diff --git a/platform/platform-impl/src/com/intellij/ui/GotItPanel.java b/platform/platform-impl/src/com/intellij/ui/GotItPanel.java
new file mode 100644
index 0000000..20c43fa
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/GotItPanel.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.ui;
+
+import com.intellij.util.ui.GraphicsUtil;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+* @author Konstantin Bulenkov
+*/
+public class GotItPanel {
+  JPanel myButton;
+  JPanel myRoot;
+  JLabel myTitle;
+  JLabel myMessage;
+
+  private void createUIComponents() {
+    myButton = new JPanel(new BorderLayout()) {
+      {
+        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+      }
+      @Override
+      protected void paintComponent(Graphics g) {
+        super.paintComponent(g);
+        GraphicsUtil.setupAAPainting(g);
+        ((Graphics2D)g).setPaint(new GradientPaint(0, 0, new JBColor(new Color(77, 143, 253), new Color(52, 74, 100)), 0, getHeight(),
+                                                   new JBColor(new Color(71, 135, 237), new Color(38, 53, 73))));
+        g.fillRoundRect(0,0,getWidth()-1, getHeight()-1, 5,5);
+        g.setColor(new JBColor(new Color(48, 121, 237), new Color(87, 93, 101)));
+        g.drawRoundRect(0,0,getWidth()-1, getHeight()-1, 5,5);
+      }
+    };
+  }
+}
diff --git a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
index 006f88b..b783956 100644
--- a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
+++ b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
@@ -14,7 +14,7 @@
 import com.intellij.openapi.startup.StartupActivity;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.ShutDownTracker;
-import org.jboss.netty.channel.ChannelException;
+import io.netty.channel.ChannelException;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -108,7 +108,8 @@
         }
 
         try {
-          server = new BuiltInServer(workerCount);
+          server = new BuiltInServer();
+          detectedPortNumber = server.start(workerCount, defaultPort, PORTS_COUNT, true);
         }
         catch (ChannelException e) {
           LOG.info(e);
@@ -121,6 +122,13 @@
           return;
         }
 
+        if (detectedPortNumber == -1) {
+          LOG.info("built-in server cannot be started, cannot bind to port");
+          return;
+        }
+
+        LOG.info("built-in server started, port " + detectedPortNumber);
+
         Disposer.register(ApplicationManager.getApplication(), server);
         ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
           @Override
@@ -131,14 +139,6 @@
             }
           }
         });
-
-        detectedPortNumber = server.start(defaultPort, PORTS_COUNT, true);
-        if (detectedPortNumber == -1) {
-          LOG.info("built-in server cannot be started, cannot bind to port");
-        }
-        else {
-          LOG.info("built-in server started, port " + detectedPortNumber);
-        }
       }
     });
   }
diff --git a/platform/platform-impl/src/org/jetbrains/ide/PooledThreadExecutor.java b/platform/platform-impl/src/org/jetbrains/ide/PooledThreadExecutor.java
index 1c24110..952393d 100644
--- a/platform/platform-impl/src/org/jetbrains/ide/PooledThreadExecutor.java
+++ b/platform/platform-impl/src/org/jetbrains/ide/PooledThreadExecutor.java
@@ -5,7 +5,12 @@
 
 import java.util.concurrent.Executor;
 
-public class PooledThreadExecutor implements Executor {
+public final class PooledThreadExecutor implements Executor {
+  public static final PooledThreadExecutor INSTANCE = new PooledThreadExecutor();
+
+  private PooledThreadExecutor() {
+  }
+
   @Override
   public void execute(@NotNull Runnable command) {
     ApplicationManager.getApplication().executeOnPooledThread(command);
diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
index 6f61306..85d70892 100644
--- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
+++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
@@ -20,12 +20,12 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.util.net.NetUtils;
-import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.channel.group.DefaultChannelGroup;
-import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
-import org.jboss.netty.handler.codec.http.*;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.QueryStringDecoder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.ide.CustomPortServerManager;
@@ -35,73 +35,62 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.Map;
-import java.util.concurrent.Executor;
 
 public class BuiltInServer implements Disposable {
-  private final ChannelGroup openChannels = new DefaultChannelGroup();
+  private final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
 
   static final Logger LOG = Logger.getInstance(BuiltInServer.class);
 
-  private final NioServerSocketChannelFactory channelFactory;
-
-  public BuiltInServer() {
-    this(1);
-  }
-
-  public BuiltInServer(int workerCount) {
-    Executor pooledThreadExecutor = new PooledThreadExecutor();
-    channelFactory = new NioServerSocketChannelFactory(pooledThreadExecutor, pooledThreadExecutor, workerCount);
-  }
-
   public boolean isRunning() {
-    return !openChannels.isEmpty();
+    return !channelRegistrar.isEmpty();
   }
 
   public void start(int port) {
-    start(port, 1, false);
+    start(1, port, 1, false);
   }
 
-  public int start(int firstPort, int portsCount, boolean tryAnyPort) {
+  public int start(int workerCount, int firstPort, int portsCount, boolean tryAnyPort) {
     if (isRunning()) {
       throw new IllegalStateException("server already started");
     }
 
-    ServerBootstrap bootstrap = createServerBootstrap(channelFactory, openChannels, null);
+    NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(workerCount, PooledThreadExecutor.INSTANCE);
+    ServerBootstrap bootstrap = createServerBootstrap(eventLoopGroup, channelRegistrar, null);
     int port = bind(firstPort, portsCount, tryAnyPort, bootstrap);
-    bindCustomPorts(firstPort, port);
+    bindCustomPorts(firstPort, port, eventLoopGroup);
     return port;
   }
 
-  static ServerBootstrap createServerBootstrap(NioServerSocketChannelFactory channelFactory, ChannelGroup openChannels, @Nullable Map<String, Object> xmlRpcHandlers) {
-    ServerBootstrap bootstrap = new ServerBootstrap(channelFactory);
-    bootstrap.setOption("child.tcpNoDelay", true);
-    bootstrap.setOption("child.keepAlive", true);
+  static ServerBootstrap createServerBootstrap(EventLoopGroup eventLoopGroup, final ChannelRegistrar channelRegistrar, @Nullable Map<String, Object> xmlRpcHandlers) {
+    ServerBootstrap bootstrap = NettyUtil.nioServerBootstrap(eventLoopGroup);
     if (xmlRpcHandlers == null) {
-      final ChannelHandler handler = new PortUnificationServerHandler(openChannels);
-      bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
+      final PortUnificationServerHandler portUnificationServerHandler = new PortUnificationServerHandler();
+      bootstrap.childHandler(new ChannelInitializer() {
         @Override
-        public ChannelPipeline getPipeline() throws Exception {
-          return Channels.pipeline(handler);
+        protected void initChannel(Channel channel) throws Exception {
+          channel.pipeline().addLast(channelRegistrar, portUnificationServerHandler);
         }
       });
     }
     else {
       final XmlRpcDelegatingHttpRequestHandler handler = new XmlRpcDelegatingHttpRequestHandler(xmlRpcHandlers);
-      bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
+      bootstrap.childHandler(new ChannelInitializer() {
         @Override
-        public ChannelPipeline getPipeline() throws Exception {
-          return Channels.pipeline(new HttpRequestDecoder(), new HttpChunkAggregator(1048576), new HttpResponseEncoder(), handler);
+        protected void initChannel(Channel channel) throws Exception {
+          channel.pipeline().addLast(channelRegistrar);
+          NettyUtil.initHttpHandlers(channel.pipeline());
+          channel.pipeline().addLast(handler);
         }
       });
     }
     return bootstrap;
   }
 
-  private void bindCustomPorts(int firstPort, int port) {
+  private void bindCustomPorts(int firstPort, int port, NioEventLoopGroup eventLoopGroup) {
     for (CustomPortServerManager customPortServerManager : CustomPortServerManager.EP_NAME.getExtensions()) {
       try {
         int customPortServerManagerPort = customPortServerManager.getPort();
-        SubServer subServer = new SubServer(customPortServerManager, channelFactory);
+        SubServer subServer = new SubServer(customPortServerManager, eventLoopGroup);
         Disposer.register(this, subServer);
         if (customPortServerManagerPort != firstPort && customPortServerManagerPort != port) {
           subServer.bind(customPortServerManagerPort);
@@ -117,55 +106,40 @@
     InetAddress loopbackAddress = NetUtils.getLoopbackAddress();
     for (int i = 0; i < portsCount; i++) {
       int port = firstPort + i;
-      try {
-        openChannels.add(bootstrap.bind(new InetSocketAddress(loopbackAddress, port)));
+      ChannelFuture future = bootstrap.bind(loopbackAddress, port).awaitUninterruptibly();
+      if (future.isSuccess()) {
+        channelRegistrar.add(future.channel());
         return port;
       }
-      catch (ChannelException e) {
-        if (!openChannels.isEmpty()) {
-          openChannels.close();
-          openChannels.clear();
-        }
-
-        if (portsCount == 1) {
-          throw e;
-        }
-        else if (!tryAnyPort && i == (portsCount - 1)) {
-          LOG.error(e);
-        }
+      else if (!tryAnyPort && i == (portsCount - 1)) {
+        LOG.error(future.cause());
+        return -1;
       }
     }
 
-    if (tryAnyPort) {
-      LOG.info("We cannot bind to our default range, so, try to bind to any free port");
-      try {
-        Channel channel = bootstrap.bind(new InetSocketAddress(loopbackAddress, 0));
-        openChannels.add(channel);
-        return ((InetSocketAddress)channel.getLocalAddress()).getPort();
-      }
-      catch (ChannelException e) {
-        LOG.error(e);
-      }
+    LOG.info("We cannot bind to our default range, so, try to bind to any free port");
+    ChannelFuture future = bootstrap.bind(loopbackAddress, 0).awaitUninterruptibly();
+    if (future.isSuccess()) {
+      channelRegistrar.add(future.channel());
+      return ((InetSocketAddress)future.channel().localAddress()).getPort();
     }
-
-    return -1;
+    else {
+      LOG.error(future.cause());
+      return -1;
+    }
   }
 
   @Override
   public void dispose() {
-    try {
-      openChannels.close().awaitUninterruptibly();
-    }
-    finally {
-      channelFactory.releaseExternalResources();
-    }
+    channelRegistrar.close();
     LOG.info("web server stopped");
   }
 
-  public static void replaceDefaultHandler(@NotNull ChannelHandlerContext context, @NotNull SimpleChannelUpstreamHandler messageChannelHandler) {
-    context.getPipeline().replace(DelegatingHttpRequestHandler.class, "replacedDefaultHandler", messageChannelHandler);
+  public static void replaceDefaultHandler(@NotNull ChannelHandlerContext context, @NotNull SimpleChannelInboundHandler messageChannelHandler) {
+    context.pipeline().replace(DelegatingHttpRequestHandler.class, "replacedDefaultHandler", messageChannelHandler);
   }
 
+  @ChannelHandler.Sharable
   private static final class XmlRpcDelegatingHttpRequestHandler extends DelegatingHttpRequestHandlerBase {
     private final Map<String, Object> handlers;
 
@@ -174,9 +148,9 @@
     }
 
     @Override
-    protected boolean process(ChannelHandlerContext context, HttpRequest request, QueryStringDecoder urlDecoder) throws IOException {
+    protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException {
       return (request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS) &&
-             XmlRpcServer.SERVICE.getInstance().process(urlDecoder.getPath(), request, context, handlers);
+             XmlRpcServer.SERVICE.getInstance().process(urlDecoder.path(), request, context, handlers);
     }
   }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
index 2ac00c1..93def2e 100644
--- a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
@@ -1,24 +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 org.jetbrains.io;
 
 import com.intellij.openapi.diagnostic.Logger;
-import org.jboss.netty.channel.ChannelEvent;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelUpstreamHandler;
-import org.jboss.netty.channel.ExceptionEvent;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
 
 import java.net.ConnectException;
 
-public final class ChannelExceptionHandler implements ChannelUpstreamHandler {
+@ChannelHandler.Sharable
+public final class ChannelExceptionHandler extends ChannelInboundHandlerAdapter {
   private static final Logger LOG = Logger.getInstance(ChannelExceptionHandler.class);
 
   @Override
-  public void handleUpstream(ChannelHandlerContext context, ChannelEvent event) throws Exception {
-    if (!(event instanceof ExceptionEvent)) {
-      context.sendUpstream(event);
-      return;
-    }
-
-    Throwable cause = ((ExceptionEvent)event).getCause();
+  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
     // don't report about errors while connecting
     // WEB-7727
     if (!(cause instanceof ConnectException) && !"Connection reset".equals(cause.getMessage())) {
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
new file mode 100644
index 0000000..96bb850d
--- /dev/null
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
@@ -0,0 +1,54 @@
+package org.jetbrains.io;
+
+import io.netty.channel.*;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.ImmediateEventExecutor;
+import org.jetbrains.annotations.NotNull;
+
+@ChannelHandler.Sharable
+public final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
+  private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
+
+  public boolean isEmpty() {
+    return openChannels.isEmpty();
+  }
+
+  public void add(@NotNull Channel serverChannel) {
+    assert serverChannel instanceof ServerChannel;
+    openChannels.add(serverChannel);
+  }
+
+  @Override
+  public void channelActive(ChannelHandlerContext context) throws Exception {
+    // we don't need to remove channel on close - ChannelGroup do it
+    openChannels.add(context.channel());
+
+    super.channelActive(context);
+  }
+
+  public void close() {
+    close(true);
+  }
+
+  public void close(boolean shutdownEventLoopGroup) {
+    EventLoopGroup eventLoopGroup = null;
+    if (shutdownEventLoopGroup) {
+      for (Channel channel : openChannels) {
+        if (channel instanceof ServerChannel) {
+          eventLoopGroup = channel.eventLoop().parent();
+          break;
+        }
+      }
+    }
+
+    try {
+      openChannels.close().awaitUninterruptibly();
+    }
+    finally {
+      if (eventLoopGroup != null) {
+        eventLoopGroup.shutdownGracefully();
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/Decoder.java b/platform/platform-impl/src/org/jetbrains/io/Decoder.java
index 45464e5..30052bd 100644
--- a/platform/platform-impl/src/org/jetbrains/io/Decoder.java
+++ b/platform/platform-impl/src/org/jetbrains/io/Decoder.java
@@ -15,24 +15,28 @@
  */
 package org.jetbrains.io;
 
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
 import org.jetbrains.annotations.Nullable;
 
-public abstract class Decoder extends SimpleChannelUpstreamHandler {
-  protected ChannelBuffer cumulation;
+public abstract class Decoder<I> extends SimpleChannelInboundHandler<I> {
+  protected ByteBuf cumulation;
+
+  protected Decoder() {
+    super(false);
+  }
 
   @Nullable
-  protected final ChannelBuffer getBufferIfSufficient(ChannelBuffer input, int requiredLength, ChannelHandlerContext context) {
-    if (!input.readable()) {
+  protected final ByteBuf getBufferIfSufficient(ByteBuf input, int requiredLength, ChannelHandlerContext context) {
+    if (!input.isReadable()) {
       return null;
     }
 
     if (cumulation == null) {
       if (input.readableBytes() < requiredLength) {
-        cumulation = context.getChannel().getConfig().getBufferFactory().getBuffer(requiredLength);
+        cumulation = context.channel().config().getAllocator().buffer(requiredLength);
         cumulation.writeBytes(input);
         return null;
       }
@@ -46,7 +50,7 @@
         return null;
       }
       else {
-        ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(cumulation, input);
+        ByteBuf buffer = Unpooled.wrappedBuffer(cumulation, input);
         input.skipBytes(input.readableBytes());
         cumulation = null;
         return buffer;
diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
index e2464d3..e7809ac 100644
--- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
@@ -18,13 +18,17 @@
 import com.intellij.openapi.application.ex.ApplicationInfoEx;
 import com.intellij.openapi.util.IconLoader;
 import com.intellij.util.ui.UIUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.handler.codec.http.QueryStringDecoder;
+import io.netty.util.Attribute;
+import io.netty.util.AttributeKey;
 import org.apache.sanselan.ImageFormat;
 import org.apache.sanselan.ImageWriteException;
 import org.apache.sanselan.Sanselan;
-import org.jboss.netty.channel.ChannelHandler;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.http.HttpRequest;
-import org.jboss.netty.handler.codec.http.QueryStringDecoder;
 import org.jetbrains.ide.BuiltInServerManager;
 import org.jetbrains.ide.HttpRequestHandler;
 
@@ -34,23 +38,24 @@
 
 @ChannelHandler.Sharable
 final class DelegatingHttpRequestHandler extends DelegatingHttpRequestHandlerBase {
+  private static final AttributeKey<HttpRequestHandler> PREV_HANDLER = new AttributeKey<HttpRequestHandler>("DelegatingHttpRequestHandler.handler");
+
   @Override
-  protected boolean process(ChannelHandlerContext context, HttpRequest request, QueryStringDecoder urlDecoder) throws IOException, ImageWriteException {
-    HttpRequestHandler connectedHandler = (HttpRequestHandler)context.getAttachment();
+  protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException, ImageWriteException {
+    Attribute<HttpRequestHandler> prevHandlerAttribute = context.attr(PREV_HANDLER);
+    HttpRequestHandler connectedHandler = prevHandlerAttribute.get();
     if (connectedHandler != null) {
       if (connectedHandler.isSupported(request) && connectedHandler.process(urlDecoder, request, context)) {
         return true;
       }
       // prev cached connectedHandler is not suitable for this request, so, let's find it again
-      context.setAttachment(null);
+      prevHandlerAttribute.set(null);
     }
 
     for (HttpRequestHandler handler : BuiltInServerManager.EP_NAME.getExtensions()) {
       try {
         if (handler.isSupported(request) && handler.process(urlDecoder, request, context)) {
-          if (context.getAttachment() == null) {
-            context.setAttachment(handler);
-          }
+          prevHandlerAttribute.set(handler);
           return true;
         }
       }
@@ -59,17 +64,26 @@
       }
     }
 
-    if (urlDecoder.getPath().equals("/favicon.ico")) {
+    if (urlDecoder.path().equals("/favicon.ico")) {
       Icon icon = IconLoader.findIcon(ApplicationInfoEx.getInstanceEx().getSmallIconUrl());
       if (icon != null) {
         BufferedImage image = UIUtil.createImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
         icon.paintIcon(null, image.getGraphics(), 0, 0);
         byte[] icoBytes = Sanselan.writeImageToBytes(image, ImageFormat.IMAGE_FORMAT_ICO, null);
-        Responses.send(icoBytes, FileResponses.createResponse(urlDecoder.getPath()), request, context);
+        HttpResponse response = Responses.response(FileResponses.getContentType(urlDecoder.path()), Unpooled.wrappedBuffer(icoBytes));
+        Responses.addNoCache(response);
+        Responses.send(response, context.channel(), request);
         return true;
       }
     }
 
     return false;
   }
+
+  @Override
+  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
+    super.exceptionCaught(context, cause);
+
+    context.attr(PREV_HANDLER).remove();
+  }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
index 7fd497b..2a8f6ea 100644
--- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
+++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
@@ -15,43 +15,33 @@
  */
 package org.jetbrains.io;
 
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ExceptionEvent;
-import org.jboss.netty.channel.MessageEvent;
-import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
-import org.jboss.netty.handler.codec.http.HttpRequest;
-import org.jboss.netty.handler.codec.http.QueryStringDecoder;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.QueryStringDecoder;
 
-import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
-
-abstract class DelegatingHttpRequestHandlerBase extends SimpleChannelUpstreamHandler {
+abstract class DelegatingHttpRequestHandlerBase extends SimpleChannelInboundHandler<FullHttpRequest> {
   @Override
-  public final void messageReceived(ChannelHandlerContext context, MessageEvent event) throws Exception {
-    if (!(event.getMessage() instanceof HttpRequest)) {
-      context.sendUpstream(event);
-      return;
+  protected void channelRead0(ChannelHandlerContext context, FullHttpRequest message) throws Exception {
+    if (BuiltInServer.LOG.isDebugEnabled()) {
+      BuiltInServer.LOG.debug("IN HTTP:\n" + message);
     }
 
-    HttpRequest request = (HttpRequest)event.getMessage();
-    //if (BuiltInServer.LOG.isDebugEnabled()) {
-    //BuiltInServer.LOG.debug(request.toString());
-    //}
-
-    if (!process(context, request, new QueryStringDecoder(request.getUri()))) {
-      Responses.sendStatus(request, context.getChannel(), NOT_FOUND);
+    if (!process(context, message, new QueryStringDecoder(message.getUri()))) {
+      Responses.sendStatus(HttpResponseStatus.NOT_FOUND, context.channel(), message);
     }
   }
 
-  protected abstract boolean process(ChannelHandlerContext context, HttpRequest request, QueryStringDecoder urlDecoder) throws Exception;
+  protected abstract boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws Exception;
 
   @Override
-  public final void exceptionCaught(ChannelHandlerContext context, ExceptionEvent event) throws Exception {
+  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
     try {
-      NettyUtil.log(event.getCause(), BuiltInServer.LOG);
+      NettyUtil.log(cause, BuiltInServer.LOG);
     }
     finally {
-      context.setAttachment(null);
-      event.getChannel().close();
+      context.channel().close();
     }
   }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/FileResponses.java b/platform/platform-impl/src/org/jetbrains/io/FileResponses.java
index ce70e37..14897fd 100644
--- a/platform/platform-impl/src/org/jetbrains/io/FileResponses.java
+++ b/platform/platform-impl/src/org/jetbrains/io/FileResponses.java
@@ -15,47 +15,39 @@
  */
 package org.jetbrains.io;
 
-import org.jboss.netty.channel.*;
-import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
-import org.jboss.netty.handler.codec.http.HttpMethod;
-import org.jboss.netty.handler.codec.http.HttpRequest;
-import org.jboss.netty.handler.codec.http.HttpResponse;
-import org.jboss.netty.handler.ssl.SslHandler;
-import org.jboss.netty.handler.stream.ChunkedFile;
+import com.intellij.openapi.util.text.StringUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.DefaultFileRegion;
+import io.netty.handler.codec.http.*;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.stream.ChunkedFile;
 
 import javax.activation.MimetypesFileTypeMap;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.text.ParseException;
 import java.util.Date;
 
-import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
-import static org.jboss.netty.handler.codec.http.HttpHeaders.setContentLength;
-import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NOT_MODIFIED;
-import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
 import static org.jetbrains.io.Responses.*;
 
 public class FileResponses {
   private static final MimetypesFileTypeMap FILE_MIMETYPE_MAP = new MimetypesFileTypeMap();
 
-  public static HttpResponse createResponse(String path) {
-    HttpResponse response = create(FILE_MIMETYPE_MAP.getContentType(path));
-    response.setHeader(CACHE_CONTROL, "no-cache, no-store, must-revalidate, max-age=0");
-    response.setHeader(PRAGMA, "no-cache");
-    return response;
+  public static String getContentType(String path) {
+    return FILE_MIMETYPE_MAP.getContentType(path);
   }
 
   private static boolean checkCache(HttpRequest request, Channel channel, long lastModified) {
-    String ifModifiedSince = request.getHeader(IF_MODIFIED_SINCE);
-    if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
+    String ifModifiedSince = request.headers().get(HttpHeaders.Names.IF_MODIFIED_SINCE);
+    if (!StringUtil.isEmpty(ifModifiedSince)) {
       try {
         if (Responses.DATE_FORMAT.get().parse(ifModifiedSince).getTime() >= lastModified) {
-          HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NOT_MODIFIED);
-          addAllowAnyOrigin(response);
-          addDate(response);
-          addServer(response);
-          send(response, channel, request);
+          send(response(HttpResponseStatus.NOT_MODIFIED), channel, request);
           return true;
         }
       }
@@ -72,42 +64,41 @@
       return;
     }
 
+    HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
+    response.headers().add(CONTENT_TYPE, getContentType(file.getPath()));
+    addCommonHeaders(response);
+    response.headers().set(HttpHeaders.Names.CACHE_CONTROL, "private, must-revalidate");
+    response.headers().set(HttpHeaders.Names.LAST_MODIFIED, Responses.DATE_FORMAT.get().format(new Date(file.lastModified())));
+
+    boolean keepAlive = addKeepAliveIfNeed(response, request);
+
     boolean fileWillBeClosed = false;
-    RandomAccessFile raf = new RandomAccessFile(file, "r");
+    RandomAccessFile raf;
+    try {
+      raf = new RandomAccessFile(file, "r");
+    }
+    catch (FileNotFoundException ignored) {
+      send(response(HttpResponseStatus.NOT_FOUND), channel, request);
+      return;
+    }
+
     try {
       long fileLength = raf.length();
-      HttpResponse response = createResponse(file.getPath());
-      addCommonHeaders(response);
-      response.setHeader(LAST_MODIFIED, Responses.DATE_FORMAT.get().format(new Date(file.lastModified())));
-      boolean keepAlive = addKeepAliveIfNeed(response, request);
       if (request.getMethod() != HttpMethod.HEAD) {
-        setContentLength(response, fileLength);
+        HttpHeaders.setContentLength(response, fileLength);
       }
 
-      ChannelFuture future = channel.write(response);
-
+      channel.write(response);
       if (request.getMethod() != HttpMethod.HEAD) {
-        if (channel.getPipeline().get(SslHandler.class) == null) {
-          // No encryption - use zero-copy.
-          final FileRegion region = new DefaultFileRegion(raf.getChannel(), 0, fileLength);
-          future = channel.write(region);
-          future.addListener(new ChannelFutureListener() {
-            @Override
-            public void operationComplete(ChannelFuture future) {
-              region.releaseExternalResources();
-            }
-          });
+        if (channel.pipeline().get(SslHandler.class) == null) {
+          // no encryption - use zero-copy
+          channel.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength));
         }
         else {
-          // Cannot use zero-copy with HTTPS.
-          future = channel.write(new ChunkedFile(raf, 0, fileLength, 8192));
+          // cannot use zero-copy with HTTPS
+          channel.write(new ChunkedFile(raf));
         }
       }
-
-      if (!keepAlive) {
-        future.addListener(ChannelFutureListener.CLOSE);
-      }
-
       fileWillBeClosed = true;
     }
     finally {
@@ -115,5 +106,10 @@
         raf.close();
       }
     }
+
+    ChannelFuture future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
+    if (!keepAlive) {
+      future.addListener(ChannelFutureListener.CLOSE);
+    }
   }
-}
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
index 293a22b..86ae505 100644
--- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
+++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java
@@ -17,12 +17,17 @@
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.ActionCallback;
-import org.jboss.netty.bootstrap.ClientBootstrap;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelException;
-import org.jboss.netty.channel.ChannelFactory;
-import org.jboss.netty.channel.ChannelFuture;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.*;
+import io.netty.channel.oio.OioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.channel.socket.oio.OioSocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.ide.PooledThreadExecutor;
 
 import java.io.IOException;
 import java.net.SocketAddress;
@@ -40,18 +45,18 @@
     }
   }
 
-  public static Channel connectClient(ClientBootstrap bootstrap, SocketAddress remoteAddress, ActionCallback asyncResult) {
+  public static Channel connectClient(Bootstrap bootstrap, SocketAddress remoteAddress, ActionCallback asyncResult) {
     return connect(bootstrap, remoteAddress, asyncResult, DEFAULT_CONNECT_ATTEMPT_COUNT);
   }
 
   @Nullable
-  public static Channel connect(ClientBootstrap bootstrap, SocketAddress remoteAddress, ActionCallback asyncResult, int maxAttemptCount) {
+  public static Channel connect(Bootstrap bootstrap, SocketAddress remoteAddress, ActionCallback asyncResult, int maxAttemptCount) {
     int attemptCount = 0;
     while (true) {
       try {
         ChannelFuture future = bootstrap.connect(remoteAddress).await();
         if (future.isSuccess()) {
-          return future.getChannel();
+          return future.channel();
         }
         else if (asyncResult.isRejected()) {
           return null;
@@ -84,13 +89,29 @@
 
   // applicable only in case of ClientBootstrap&OioClientSocketChannelFactory
   public static void closeAndReleaseFactory(Channel channel) {
-    ChannelFactory channelFactory = channel.getFactory();
+    EventLoop channelFactory = channel.eventLoop();
     try {
       channel.close().awaitUninterruptibly();
     }
     finally {
       // in our case it does nothing, we don't use ExecutorService, but we are aware of future changes
-      channelFactory.releaseExternalResources();
+      channelFactory.shutdownGracefully();
     }
   }
+
+  public static ServerBootstrap nioServerBootstrap(EventLoopGroup eventLoopGroup) {
+    ServerBootstrap bootstrap = new ServerBootstrap().group(eventLoopGroup).channel(NioServerSocketChannel.class);
+    bootstrap.childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_KEEPALIVE, true);
+    return bootstrap;
+  }
+
+  public static Bootstrap oioClientBootstrap() {
+    Bootstrap bootstrap = new Bootstrap().group(new OioEventLoopGroup(1, PooledThreadExecutor.INSTANCE)).channel(OioSocketChannel.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());
+  }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
index 1662ab0..1169763 100644
--- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
@@ -16,30 +16,24 @@
 package org.jetbrains.io;
 
 import com.intellij.openapi.util.AtomicNotNullLazyValue;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.*;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.handler.codec.compression.ZlibDecoder;
-import org.jboss.netty.handler.codec.compression.ZlibEncoder;
-import org.jboss.netty.handler.codec.compression.ZlibWrapper;
-import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
-import org.jboss.netty.handler.codec.http.HttpContentCompressor;
-import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
-import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
-import org.jboss.netty.handler.ssl.SslHandler;
-import org.jboss.netty.handler.stream.ChunkedWriteHandler;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.*;
+import io.netty.handler.codec.compression.JZlibEncoder;
+import io.netty.handler.codec.compression.JdkZlibDecoder;
+import io.netty.handler.codec.compression.ZlibWrapper;
+import io.netty.handler.codec.http.HttpMessage;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.stream.ChunkedWriteHandler;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
-import java.net.SocketAddress;
 import java.security.KeyStore;
 import java.security.Security;
 
 @ChannelHandler.Sharable
-final class PortUnificationServerHandler extends Decoder {
+final class PortUnificationServerHandler extends Decoder<ByteBuf> {
   private static final AtomicNotNullLazyValue<SSLContext> SSL_SERVER_CONTEXT = new AtomicNotNullLazyValue<SSLContext>() {
     @NotNull
     @Override
@@ -69,73 +63,67 @@
   private final boolean detectSsl;
   private final boolean detectGzip;
 
-  private final ChannelGroup openChannels;
   private final DelegatingHttpRequestHandler delegatingHttpRequestHandler;
 
-  public PortUnificationServerHandler(ChannelGroup openChannels) {
-    this(new DelegatingHttpRequestHandler(), openChannels, true, true);
+  public PortUnificationServerHandler() {
+    this(new DelegatingHttpRequestHandler(), true, true);
   }
 
-  private PortUnificationServerHandler(DelegatingHttpRequestHandler delegatingHttpRequestHandler, @Nullable ChannelGroup openChannels, boolean detectSsl, boolean detectGzip) {
+  private PortUnificationServerHandler(DelegatingHttpRequestHandler delegatingHttpRequestHandler, boolean detectSsl, boolean detectGzip) {
     this.delegatingHttpRequestHandler = delegatingHttpRequestHandler;
-    this.openChannels = openChannels;
     this.detectSsl = detectSsl;
     this.detectGzip = detectGzip;
   }
 
   @Override
-  public void channelOpen(ChannelHandlerContext context, ChannelStateEvent e) {
-    if (openChannels != null) {
-      openChannels.add(e.getChannel());
+  protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+    ByteBuf buffer = getBufferIfSufficient(message, 5, context);
+    if (buffer == null) {
+      message.release();
+    }
+    else {
+      decode(context, buffer);
     }
   }
 
-  @Override
-  public void messageReceived(ChannelHandlerContext context, MessageEvent e) throws Exception {
-    Object m = e.getMessage();
-    if (!(m instanceof ChannelBuffer)) {
-      context.sendUpstream(e);
-      return;
-    }
-
-    ChannelBuffer buffer = getBufferIfSufficient((ChannelBuffer)m, 5, context);
-    if (buffer != null) {
-      decode(context, buffer, e.getRemoteAddress());
-    }
-  }
-
-  private void decode(ChannelHandlerContext context, ChannelBuffer buffer, SocketAddress remoteAddress) throws Exception {
-    ChannelPipeline pipeline = context.getPipeline();
+  private 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("ssl", new SslHandler(engine));
-      pipeline.addLast("streamer", new ChunkedWriteHandler());
-      pipeline.addLast("unificationWOSsl", new PortUnificationServerHandler(delegatingHttpRequestHandler, null, false, detectGzip));
+      pipeline.addLast(new SslHandler(engine), new ChunkedWriteHandler());
+      pipeline.addLast(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("gzipDeflater", new ZlibEncoder(ZlibWrapper.GZIP));
-        pipeline.addLast("gzipInflater", new ZlibDecoder(ZlibWrapper.GZIP));
-        pipeline.addLast("unificationWOGzip", new PortUnificationServerHandler(delegatingHttpRequestHandler, null, detectSsl, false));
+        pipeline.addLast(new JZlibEncoder(ZlibWrapper.GZIP), new JdkZlibDecoder(ZlibWrapper.GZIP));
+        pipeline.addLast(new PortUnificationServerHandler(delegatingHttpRequestHandler, detectSsl, false));
       }
       else {
-        pipeline.addLast("decoder", new HttpRequestDecoder());
-        pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
-        pipeline.addLast("encoder", new HttpResponseEncoder());
-        pipeline.addLast("deflater", new HttpContentCompressor());
-        pipeline.addLast("handler", delegatingHttpRequestHandler);
+        NettyUtil.initHttpHandlers(pipeline);
+        pipeline.addLast(delegatingHttpRequestHandler);
+        if (BuiltInServer.LOG.isDebugEnabled()) {
+          pipeline.addLast(new ChannelOutboundHandlerAdapter() {
+            @Override
+            public void write(ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception {
+              if (message instanceof HttpMessage) {
+                BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
+              }
+              super.write(context, message, promise);
+            }
+          });
+        }
       }
     }
     // must be after new channels handlers addition (netty bug?)
     pipeline.remove(this);
-    Channels.fireMessageReceived(context, buffer, remoteAddress);
+    context.fireChannelRead(buffer);
   }
 
   @Override
-  public void exceptionCaught(ChannelHandlerContext context, ExceptionEvent event) throws Exception {
-    NettyUtil.log(event.getCause(), BuiltInServer.LOG);
+  public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
+    NettyUtil.log(cause, BuiltInServer.LOG);
   }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/Responses.java b/platform/platform-impl/src/org/jetbrains/io/Responses.java
index 55f603a..fbe7d86 100644
--- a/platform/platform-impl/src/org/jetbrains/io/Responses.java
+++ b/platform/platform-impl/src/org/jetbrains/io/Responses.java
@@ -19,14 +19,14 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ex.ApplicationInfoEx;
 import com.intellij.openapi.util.text.StringUtil;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelFuture;
-import org.jboss.netty.channel.ChannelFutureListener;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.http.*;
-import org.jboss.netty.util.CharsetUtil;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.*;
+import io.netty.util.CharsetUtil;
 import org.jetbrains.annotations.Nullable;
 
 import java.nio.charset.Charset;
@@ -37,11 +37,7 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
-import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
-import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
-import static org.jboss.netty.handler.codec.http.HttpHeaders.setContentLength;
-import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
-import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+import static io.netty.handler.codec.http.HttpHeaders.Names.*;
 
 public final class Responses {
   static final ThreadLocal<DateFormat> DATE_FORMAT = new ThreadLocal<DateFormat>() {
@@ -56,16 +52,36 @@
 
   private static String SERVER_HEADER_VALUE;
 
+  public static FullHttpResponse response(HttpResponseStatus status) {
+    return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.EMPTY_BUFFER);
+  }
+
+  public static HttpResponse response(@Nullable String contentType, @Nullable ByteBuf content) {
+    HttpResponse response =
+      new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content == null ? Unpooled.EMPTY_BUFFER : content);
+    if (contentType != null) {
+      response.headers().add(CONTENT_TYPE, contentType);
+    }
+    return response;
+  }
+
   public static void addAllowAnyOrigin(HttpResponse response) {
-    response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
+    response.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
   }
 
   public static void addDate(HttpResponse response) {
-    addDate(response, Calendar.getInstance().getTime());
+    if (!response.headers().contains(DATE)) {
+      addDate(response, Calendar.getInstance().getTime());
+    }
   }
 
   public static void addDate(HttpResponse response, Date date) {
-    response.setHeader(DATE, DATE_FORMAT.get().format(date));
+    response.headers().set(DATE, DATE_FORMAT.get().format(date));
+  }
+
+  public static void addNoCache(HttpResponse response) {
+    response.headers().add(CACHE_CONTROL, "no-cache, no-store, must-revalidate, max-age=0");
+    response.headers().add(PRAGMA, "no-cache");
   }
 
   @Nullable
@@ -81,32 +97,23 @@
 
   public static void addServer(HttpResponse response) {
     if (getServerHeaderValue() != null) {
-      response.setHeader(SERVER, getServerHeaderValue());
+      response.headers().add(SERVER, getServerHeaderValue());
     }
   }
 
-  public static void send(String contentType, CharSequence content, HttpRequest request, ChannelHandlerContext context) {
-    HttpResponse response = create(contentType);
-    response.setContent(ChannelBuffers.copiedBuffer(content, CharsetUtil.UTF_8));
-    send(response, request, context);
-  }
-
-  public static void send(HttpResponse response, @Nullable HttpRequest request, ChannelHandlerContext context) {
-    send(response, context.getChannel(), request);
-  }
-
   public static void send(HttpResponse response, Channel channel, @Nullable HttpRequest request) {
-    ChannelBuffer content = response.getContent();
-    setContentLength(response, content == ChannelBuffers.EMPTY_BUFFER ? 0 : content.readableBytes());
+    if (response.getStatus() != HttpResponseStatus.NOT_MODIFIED && !HttpHeaders.isContentLengthSet(response)) {
+      HttpHeaders.setContentLength(response,
+                                   response instanceof FullHttpResponse ? ((FullHttpResponse)response).content().readableBytes() : 0);
+    }
 
-    boolean keepAlive = request != null && addKeepAliveIfNeed(response, request);
     addCommonHeaders(response);
-    send(response, channel, !keepAlive);
+    send(response, channel, request != null && !addKeepAliveIfNeed(response, request));
   }
 
   public static boolean addKeepAliveIfNeed(HttpResponse response, HttpRequest request) {
-    if (isKeepAlive(request)) {
-      response.setHeader(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
+    if (HttpHeaders.isKeepAlive(request)) {
+      HttpHeaders.setKeepAlive(response, true);
       return true;
     }
     return false;
@@ -118,84 +125,63 @@
     addAllowAnyOrigin(response);
   }
 
-  public static HttpResponse create(String contentType) {
-    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
-    response.setHeader(CONTENT_TYPE, contentType);
-    return response;
+  public static void send(CharSequence content, Channel channel, @Nullable HttpRequest request) {
+    send(content, CharsetUtil.US_ASCII, channel, request);
   }
 
-  public static void send(CharSequence content, HttpRequest request, ChannelHandlerContext context) {
-    send(content, CharsetUtil.US_ASCII, request, context);
-  }
-
-  public static void send(CharSequence content, Charset charset, HttpRequest request, ChannelHandlerContext context) {
-    DefaultHttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
-    response.setContent(ChannelBuffers.copiedBuffer(content, charset));
-    send(response, request, context);
-  }
-
-  public static void send(byte[] bytes, HttpResponse response, HttpRequest request, ChannelHandlerContext context) {
-    response.setContent(ChannelBuffers.wrappedBuffer(bytes));
-    send(response, request, context);
-  }
-
-  public static void send(HttpResponse response, ChannelHandlerContext context) {
-    send(response, context.getChannel(), true);
-  }
-
-  public static void send(HttpResponseStatus status, ChannelHandlerContext context) {
-    send(new DefaultHttpResponse(HTTP_1_1, status), context);
+  public static void send(CharSequence content, Charset charset, Channel channel, @Nullable HttpRequest request) {
+    send(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(content, charset)), channel, request);
   }
 
   private static void send(HttpResponse response, Channel channel, boolean close) {
-    if (!channel.isOpen()) {
+    if (!channel.isActive()) {
       return;
     }
 
     ChannelFuture future = channel.write(response);
+    if (!(response instanceof FullHttpResponse)) {
+      channel.write(LastHttpContent.EMPTY_LAST_CONTENT);
+    }
+    channel.flush();
     if (close) {
       future.addListener(ChannelFutureListener.CLOSE);
     }
   }
 
-  public static void sendStatus(HttpRequest request, Channel channel, HttpResponseStatus responseStatus, @Nullable String description) {
-    sendStatus(new DefaultHttpResponse(HTTP_1_1, responseStatus), request, channel, description);
-  }
-
-  public static void sendStatus(HttpRequest request, Channel channel, HttpResponseStatus responseStatus) {
-    sendStatus(request, channel, responseStatus, null);
-  }
-
-  public static void sendStatus(HttpResponse response, HttpRequest request, Channel channel) {
-    sendStatus(response, request, channel, null);
-  }
-
   public static void sendStatus(HttpResponseStatus responseStatus, Channel channel) {
-    sendStatus(new DefaultHttpResponse(HTTP_1_1, responseStatus), null, channel, null);
+    sendStatus(responseStatus, channel, null);
   }
 
-  private static void sendStatus(HttpResponse response, @Nullable HttpRequest request, Channel channel, @Nullable String description) {
-    response.setHeader(CONTENT_TYPE, "text/html");
-    if (request == null || request.getMethod() != HttpMethod.HEAD) {
-      String message = response.getStatus().toString();
+  public static void sendStatus(HttpResponseStatus responseStatus, Channel channel, @Nullable HttpRequest request) {
+    sendStatus(responseStatus, channel, null, request);
+  }
 
-      StringBuilder builder = new StringBuilder();
-      builder.append("<!doctype html><title>").append(message).append("</title>").append("<h1 style=\"text-align: center\">").append(message).append("</h1>");
-      if (description != null) {
-        builder.append("<p>").append(description).append("</p>");
-      }
-      builder.append("<hr/><p style=\"text-align: center\">").append(StringUtil.notNullize(getServerHeaderValue(), "")).append("</p>");
+  public static void sendStatus(HttpResponseStatus responseStatus, Channel channel, @Nullable String description, @Nullable HttpRequest request) {
+    send(createStatusResponse(responseStatus, request, description), channel, request);
+  }
 
-      response.setContent(ChannelBuffers.copiedBuffer(builder, CharsetUtil.UTF_8));
+  private static HttpResponse createStatusResponse(HttpResponseStatus responseStatus, @Nullable HttpRequest request, @Nullable String description) {
+    if (request != null && request.getMethod() == HttpMethod.HEAD) {
+      return response(responseStatus);
     }
-    send(response, channel, request);
+
+    StringBuilder builder = new StringBuilder();
+    String message = responseStatus.toString();
+    builder.append("<!doctype html><title>").append(message).append("</title>").append("<h1 style=\"text-align: center\">").append(message).append("</h1>");
+    if (description != null) {
+      builder.append("<p>").append(description).append("</p>");
+    }
+    builder.append("<hr/><p style=\"text-align: center\">").append(StringUtil.notNullize(getServerHeaderValue(), "")).append("</p>");
+
+    DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseStatus, Unpooled.copiedBuffer(builder, CharsetUtil.UTF_8));
+    response.headers().set(CONTENT_TYPE, "text/html");
+    return response;
   }
 
   public static void sendOptionsResponse(String allowHeaders, HttpRequest request, ChannelHandlerContext context) {
-    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
-    response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
-    response.setHeader(ACCESS_CONTROL_ALLOW_METHODS, allowHeaders);
-    response.setHeader(ALLOW, allowHeaders);
-    send(response, request, context);
+    HttpResponse response = response(HttpResponseStatus.OK);
+    response.headers().set(ACCESS_CONTROL_ALLOW_METHODS, allowHeaders);
+    response.headers().set(ALLOW, allowHeaders);
+    send(response, context.channel(), request);
   }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/org/jetbrains/io/SubServer.java b/platform/platform-impl/src/org/jetbrains/io/SubServer.java
index 12512be..ee070e7 100644
--- a/platform/platform-impl/src/org/jetbrains/io/SubServer.java
+++ b/platform/platform-impl/src/org/jetbrains/io/SubServer.java
@@ -17,24 +17,23 @@
 
 import com.intellij.openapi.Disposable;
 import com.intellij.util.net.NetUtils;
-import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.channel.group.DefaultChannelGroup;
-import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.EventLoopGroup;
 import org.jetbrains.ide.BuiltInServerManager;
 import org.jetbrains.ide.CustomPortServerManager;
 
 import java.net.InetSocketAddress;
 
 final class SubServer implements CustomPortServerManager.CustomPortService, Disposable {
-  private final ChannelGroup openChannels = new DefaultChannelGroup();
+  private final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
+
   private final CustomPortServerManager user;
   private final ServerBootstrap bootstrap;
 
-  public SubServer(CustomPortServerManager user, NioServerSocketChannelFactory channelFactory) {
+  public SubServer(CustomPortServerManager user, EventLoopGroup eventLoopGroup) {
     this.user = user;
     user.setManager(this);
-    bootstrap = BuiltInServer.createServerBootstrap(channelFactory, openChannels, user.createXmlRpcHandlers());
+    bootstrap = BuiltInServer.createServerBootstrap(eventLoopGroup, channelRegistrar, user.createXmlRpcHandlers());
   }
 
   public boolean bind(int port) {
@@ -43,7 +42,8 @@
     }
 
     try {
-      openChannels.add(bootstrap.bind(user.isAvailableExternally() ? new InetSocketAddress(port) : new InetSocketAddress(NetUtils.getLoopbackAddress(), port)));
+      bootstrap.localAddress(user.isAvailableExternally() ? new InetSocketAddress(port) : new InetSocketAddress(NetUtils.getLoopbackAddress(), port));
+      channelRegistrar.add(bootstrap.bind().syncUninterruptibly().channel());
       return true;
     }
     catch (Exception e) {
@@ -55,12 +55,11 @@
 
   @Override
   public boolean isBound() {
-    return !openChannels.isEmpty();
+    return !channelRegistrar.isEmpty();
   }
 
   private void stop() {
-    openChannels.close().awaitUninterruptibly();
-    openChannels.clear();
+    channelRegistrar.close(false);
   }
 
   @Override
diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
index 1ef645f..7f9d09d 100644
--- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties
+++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
@@ -644,7 +644,7 @@
 replace.this.code.fragment.and.change.signature=\nMethod signature will be changed to \n{0}
 process.duplicates.title=Process Duplicate {0} of {1}
 process.methods.duplicates.title=Process Method {2} Duplicate ({0} of {1})
-0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method={0} has detected {1} code fragments in this file that can be replaced with a call to extracted method. Would you like to review and replace them?
+0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method={0} has detected {1} code {1,choice,1#fragment|2#fragments} in this file that can be replaced with a call to extracted method. Would you like to review and replace {1,choice,1#it|2#them}?
 replace.button=Replace
 method.duplicates.method.label=Method {0}
 usages.detected.title=Usages Detected
diff --git a/platform/platform-resources-en/src/messages/UIBundle.properties b/platform/platform-resources-en/src/messages/UIBundle.properties
index 04a5c32..b1dc189 100644
--- a/platform/platform-resources-en/src/messages/UIBundle.properties
+++ b/platform/platform-resources-en/src/messages/UIBundle.properties
@@ -158,3 +158,8 @@
 
 message.nothingToShow=Nothing to show
 message.noMatchesFound=No matches found
+
+tool.window.quick.access.title=Tool Windows Quick Access
+tool.window.quick.access.message=Hover over the icon below to access tool windows\nTo restore the old layout simply click the icon
+
+got.it=Got it!
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties
index 8769198..0676fe2 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/platform-resources-en/src/misc/registry.properties
@@ -64,7 +64,8 @@
 # suppress inspection "UnusedProperty"
 idea.fix.mac.env.description=On Mac, use shell environment for external processes (effective on restart).
 
-idea.x11.skip.wm.patching=false
+ide.x11.override.wm=true
+ide.x11.suppress.xinerama=true
 
 ide.appIcon.progress=true
 ide.appIcon.badge=true
@@ -230,7 +231,7 @@
 ide.goto.middle.matching=true
 # suppress inspection "UnusedProperty"
 ide.goto.middle.matching.description=Suggest items in goto actions that contain the entered string somewhere in the middle.
-ide.goto.rebuild.delay=300
+ide.goto.rebuild.delay=0
 
 ide.enable.toolwindow.stack=false
 
@@ -310,4 +311,7 @@
 windows.jumplist=false
 windows.jumplist.description=Enables JumpLists on Windows
 
-external.system.in.process=false
\ No newline at end of file
+# suppress inspection "UnusedProperty"
+GRADLE.system.in.process=true
+# suppress inspection "UnusedProperty"
+GRADLE.system.in.process.description=Whether IDEA should use 'in-process' mode for interaction with gradle api
\ No newline at end of file
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index a7227be..8c05bb9 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -257,6 +257,7 @@
     <statistics.usagesCollector implementation="com.intellij.internal.statistic.UsageTrigger$MyCollector"/>
     <!--<statistics.usagesCollector implementation="com.intellij.internal.statistic.ideSettings.IdeSettingsUsagesCollector"/>-->
     <statistics.usagesCollector implementation="com.intellij.internal.statistic.ideSettings.LaFUsagesCollector"/>
+    <statistics.usagesCollector implementation="com.intellij.internal.statistic.OsInfoUsageCollector"/>
 
     <applicationConfigurable instance="com.intellij.internal.statistic.configurable.StatisticsConfigurable" id="usage.statistics"
                              displayName="Usage Statistics"/>
diff --git a/platform/remote-servers/api/remote-servers-api.iml b/platform/remote-servers/api/remote-servers-api.iml
index deb49db..c9b160c 100644
--- a/platform/remote-servers/api/remote-servers-api.iml
+++ b/platform/remote-servers/api/remote-servers-api.iml
@@ -8,8 +8,8 @@
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="core-api" />
-    <orderEntry type="module" module-name="platform-api" />
     <orderEntry type="module" module-name="compiler-openapi" />
+    <orderEntry type="module" module-name="lang-api" />
   </component>
 </module>
 
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
index 3f4bebc..f599d7c 100644
--- a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
@@ -7,7 +7,9 @@
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
 import com.intellij.remoteServer.runtime.ServerConnector;
 import com.intellij.remoteServer.runtime.ServerTaskExecutor;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnector;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 
@@ -43,4 +45,12 @@
 
   @NotNull
   public abstract ServerConnector<?> createConnector(@NotNull C configuration, @NotNull ServerTaskExecutor asyncTasksExecutor);
+
+  /**
+   * @return a non-null instance of {@link DebugConnector} if the server supports deployment in debug mode
+   */
+  @Nullable
+  public DebugConnector<?,?> createDebugConnector() {
+    return null;
+  }
 }
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java
index b77df4f..e126f34 100644
--- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java
@@ -21,4 +21,6 @@
 
   @NotNull
   LoggingHandler getLoggingHandler();
+
+  boolean isDebugMode();
 }
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionData.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionData.java
new file mode 100644
index 0000000..73c1820
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionData.java
@@ -0,0 +1,7 @@
+package com.intellij.remoteServer.runtime.deployment.debug;
+
+/**
+ * @author nik
+ */
+public interface DebugConnectionData {
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionDataNotAvailableException.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionDataNotAvailableException.java
new file mode 100644
index 0000000..840eaf5
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnectionDataNotAvailableException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.remoteServer.runtime.deployment.debug;
+
+/**
+ * @author nik
+ */
+public class DebugConnectionDataNotAvailableException extends Exception {
+  public DebugConnectionDataNotAvailableException(String message) {
+    super(message);
+  }
+
+  public DebugConnectionDataNotAvailableException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnector.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnector.java
new file mode 100644
index 0000000..d707452
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebugConnector.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.intellij.remoteServer.runtime.deployment.debug;
+
+import com.intellij.remoteServer.runtime.deployment.DeploymentRuntime;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Implement this class if a server supports deployment in debug mode. When an user starts a deployment run configuration using 'Debug' button
+ * the following happens:
+ * <ul>
+ *  <li>deployment process is started as usual by calling {@link com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance#deploy deploy}
+ *  method; you can check whether deployment is started in debug mode or not by using {@link com.intellij.remoteServer.runtime.deployment.DeploymentTask#isDebugMode() task.isDebugMode()} method</li>
+ *  <li>when deployment is finished successfully {@link #getConnectionData} method
+ *  is called to retrieve information necessary for debugger from the deployed instance</li>
+ *  <li>{@link DebuggerLauncher} is used to start debugging</li>
+ * </ul>
+ *
+ * @author nik
+ * @see com.intellij.remoteServer.ServerType#createDebugConnector()
+ * @see com.intellij.remoteServer.runtime.deployment.DeploymentTask#isDebugMode()
+ */
+public abstract class DebugConnector<D extends DebugConnectionData, R extends DeploymentRuntime> {
+  /**
+   * @see com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher#getInstance()
+   */
+  @NotNull
+  public abstract DebuggerLauncher<D> getLauncher();
+
+  @NotNull
+  public abstract D getConnectionData(@NotNull R runtime) throws DebugConnectionDataNotAvailableException;
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebuggerLauncher.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebuggerLauncher.java
new file mode 100644
index 0000000..6901fe8
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/DebuggerLauncher.java
@@ -0,0 +1,13 @@
+package com.intellij.remoteServer.runtime.deployment.debug;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface DebuggerLauncher<D extends DebugConnectionData> {
+  void startDebugSession(@NotNull D info, @NotNull ExecutionEnvironment executionEnvironment, RemoteServer<?> server) throws ExecutionException;
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java
new file mode 100644
index 0000000..e5d63a8
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java
@@ -0,0 +1,25 @@
+package com.intellij.remoteServer.runtime.deployment.debug;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class JavaDebugConnectionData implements DebugConnectionData {
+  private final String myHost;
+  private final int myPort;
+
+  public JavaDebugConnectionData(@NotNull String host, int port) {
+    myHost = host;
+    myPort = port;
+  }
+
+  @NotNull
+  public String getHost() {
+    return myHost;
+  }
+
+  public int getPort() {
+    return myPort;
+  }
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebuggerLauncher.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebuggerLauncher.java
new file mode 100644
index 0000000..ad459ae
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebuggerLauncher.java
@@ -0,0 +1,12 @@
+package com.intellij.remoteServer.runtime.deployment.debug;
+
+import com.intellij.openapi.components.ServiceManager;
+
+/**
+ * @author nik
+ */
+public abstract class JavaDebuggerLauncher implements DebuggerLauncher<JavaDebugConnectionData> {
+  public static JavaDebuggerLauncher getInstance() {
+    return ServiceManager.getService(JavaDebuggerLauncher.class);
+  }
+}
diff --git a/platform/remote-servers/impl/remote-servers-impl.iml b/platform/remote-servers/impl/remote-servers-impl.iml
index 51c6c6f8..737907a 100644
--- a/platform/remote-servers/impl/remote-servers-impl.iml
+++ b/platform/remote-servers/impl/remote-servers-impl.iml
@@ -13,6 +13,8 @@
     <orderEntry type="module" module-name="lang-api" />
     <orderEntry type="module" module-name="compiler-openapi" />
     <orderEntry type="module" module-name="lang-impl" />
+    <orderEntry type="module" module-name="compiler-impl" />
+    <orderEntry type="module" module-name="xdebugger-api" />
   </component>
 </module>
 
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerConfigurationType.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerConfigurationType.java
index c7e406e..527c33a 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerConfigurationType.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerConfigurationType.java
@@ -19,9 +19,12 @@
 import com.intellij.execution.configurations.ConfigurationTypeBase;
 import com.intellij.execution.configurations.RunConfiguration;
 import com.intellij.openapi.project.Project;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.run.BuildArtifactsBeforeRunTaskProvider;
 import com.intellij.remoteServer.ServerType;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import com.intellij.util.containers.ContainerUtil;
@@ -33,7 +36,7 @@
  * @author nik
  */
 public class DeployToServerConfigurationType extends ConfigurationTypeBase {
-  private ServerType<?> myServerType;
+  private final ServerType<?> myServerType;
 
   public DeployToServerConfigurationType(ServerType<?> serverType) {
     super(serverType.getId() + "-deploy", serverType.getPresentableName() + " Deployment",
@@ -62,6 +65,12 @@
         DeploymentSource source = ContainerUtil.getFirstItem(sources);
         if (source != null) {
           deployConfiguration.setDeploymentSource(source);
+          if (source instanceof ArtifactDeploymentSource) {
+            Artifact artifact = ((ArtifactDeploymentSource)source).getArtifact();
+            if (artifact != null) {
+              BuildArtifactsBeforeRunTaskProvider.setBuildArtifactBeforeRun(configuration.getProject(), configuration, artifact);
+            }
+          }
         }
       }
     }
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerRunConfiguration.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerRunConfiguration.java
index 235a274..1850988 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerRunConfiguration.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerRunConfiguration.java
@@ -67,6 +67,11 @@
     myDeploymentConfigurator = deploymentConfigurator;
   }
 
+  @NotNull
+  public ServerType<S> getServerType() {
+    return myServerType;
+  }
+
   public String getServerName() {
     return myServerName;
   }
@@ -79,7 +84,7 @@
   @NotNull
   @Override
   public SettingsEditor<DeployToServerRunConfiguration> getConfigurationEditor() {
-    return new DeployToServerSettingsEditor(myServerType, myDeploymentConfigurator);
+    return new DeployToServerSettingsEditor(myServerType, myDeploymentConfigurator, getProject());
   }
 
   @Nullable
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
index a4190f6..ee18ac1 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
@@ -18,13 +18,17 @@
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.SettingsEditor;
 import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.ComboBox;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.run.BuildArtifactsBeforeRunTaskProvider;
 import com.intellij.remoteServer.ServerType;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.configuration.RemoteServersManager;
 import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
@@ -46,6 +50,7 @@
 public class DeployToServerSettingsEditor<S extends ServerConfiguration, D extends DeploymentConfiguration> extends SettingsEditor<DeployToServerRunConfiguration<S, D>> {
   private final ServerType<S> myServerType;
   private final DeploymentConfigurator<D> myDeploymentConfigurator;
+  private final Project myProject;
   private final ComboboxWithBrowseButton myServerComboBox;
   private final ComboBox mySourceComboBox;
   private final SortedComboBoxModel<String> myServerListModel;
@@ -54,9 +59,10 @@
   private SettingsEditor<D> myDeploymentSettingsEditor;
   private DeploymentSource myLastSelection;
 
-  public DeployToServerSettingsEditor(final ServerType<S> type, DeploymentConfigurator<D> deploymentConfigurator) {
+  public DeployToServerSettingsEditor(final ServerType<S> type, DeploymentConfigurator<D> deploymentConfigurator, Project project) {
     myServerType = type;
     myDeploymentConfigurator = deploymentConfigurator;
+    myProject = project;
 
     myServerListModel = new SortedComboBoxModel<String>(String.CASE_INSENSITIVE_ORDER);
     myServerComboBox = new ComboboxWithBrowseButton(new ComboBox(myServerListModel));
@@ -102,7 +108,7 @@
     mySourceComboBox.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
-        updateDeploymentSettings(null);
+        onDeploymentSourceChanged(null);
       }
     });
   }
@@ -116,7 +122,7 @@
     myServerComboBox.getComboBox().setSelectedItem(newSelection != null ? newSelection.getName() : oldSelection);
   }
 
-  private void updateDeploymentSettings(@Nullable D configuration) {
+  private void onDeploymentSourceChanged(@Nullable D configuration) {
     DeploymentSource selected = mySourceListModel.getSelectedItem();
     if (Comparing.equal(selected, myLastSelection)) {
       if (configuration != null && myDeploymentSettingsEditor != null) {
@@ -125,6 +131,8 @@
       return;
     }
 
+    updateBeforeRunOptions(myLastSelection, false);
+    updateBeforeRunOptions(selected, true);
     myDeploymentSettingsComponent.removeAll();
     myDeploymentSettingsEditor = myDeploymentConfigurator.createEditor(selected);
     if (myDeploymentSettingsEditor != null) {
@@ -137,6 +145,15 @@
     myLastSelection = selected;
   }
 
+  private void updateBeforeRunOptions(@Nullable DeploymentSource source, boolean selected) {
+    if (source instanceof ArtifactDeploymentSource) {
+      Artifact artifact = ((ArtifactDeploymentSource)source).getArtifact();
+      if (artifact != null) {
+        BuildArtifactsBeforeRunTaskProvider.setBuildArtifactBeforeRunOption(myServerComboBox, myProject, artifact, selected);
+      }
+    }
+  }
+
   @Override
   protected void resetEditorFrom(DeployToServerRunConfiguration<S,D> configuration) {
     String serverName = configuration.getServerName();
@@ -145,7 +162,7 @@
     }
     myServerComboBox.getComboBox().setSelectedItem(serverName);
     mySourceComboBox.setSelectedItem(configuration.getDeploymentSource());
-    updateDeploymentSettings(configuration.getDeploymentConfiguration());
+    onDeploymentSourceChanged(configuration.getDeploymentConfiguration());
   }
 
   @Override
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerRunner.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerRunner.java
index e3561b3..d86168b 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerRunner.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerRunner.java
@@ -1,6 +1,7 @@
 package com.intellij.remoteServer.impl.runtime;
 
 import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.executors.DefaultDebugExecutor;
 import com.intellij.execution.executors.DefaultRunExecutor;
 import com.intellij.execution.runners.DefaultProgramRunner;
 import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
@@ -18,6 +19,15 @@
 
   @Override
   public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
-    return executorId.equals(DefaultRunExecutor.EXECUTOR_ID) && profile instanceof DeployToServerRunConfiguration;
+    if (!(profile instanceof DeployToServerRunConfiguration)) {
+      return false;
+    }
+    if (executorId.equals(DefaultRunExecutor.EXECUTOR_ID)) {
+      return true;
+    }
+    if (executorId.equals(DefaultDebugExecutor.EXECUTOR_ID)) {
+      return ((DeployToServerRunConfiguration<?, ?>)profile).getServerType().createDebugConnector() != null;
+    }
+    return false;
   }
 }
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java
index 59cf6ad..a8fab93 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java
@@ -19,6 +19,7 @@
 import com.intellij.execution.ExecutionResult;
 import com.intellij.execution.Executor;
 import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.executors.DefaultDebugExecutor;
 import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.execution.runners.ProgramRunner;
 import com.intellij.openapi.project.Project;
@@ -30,6 +31,7 @@
 import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
 import com.intellij.remoteServer.runtime.ServerConnection;
 import com.intellij.remoteServer.runtime.ServerConnectionManager;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnector;
 import com.intellij.remoteServer.runtime.log.LoggingHandler;
 import com.intellij.remoteServer.runtime.ui.RemoteServersView;
 import com.intellij.util.ParameterizedRunnable;
@@ -62,7 +64,14 @@
     RemoteServersView.getInstance(project).showServerConnection(connection);
 
     LoggingHandler loggingHandler = new LoggingHandlerImpl(project);
-    connection.deploy(new DeploymentTaskImpl(mySource, myConfiguration, project, loggingHandler), new ParameterizedRunnable<String>() {
+    DebugConnector<?,?> debugConnector;
+    if (DefaultDebugExecutor.getDebugExecutorInstance().equals(executor)) {
+      debugConnector = myServer.getType().createDebugConnector();
+    }
+    else {
+      debugConnector = null;
+    }
+    connection.deploy(new DeploymentTaskImpl(mySource, myConfiguration, project, loggingHandler, debugConnector, myEnvironment), new ParameterizedRunnable<String>() {
       @Override
       public void run(String s) {
         RemoteServersView.getInstance(project).showDeployment(connection, s);
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java
index ea83602..c239b35 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java
@@ -1,10 +1,14 @@
 package com.intellij.remoteServer.impl.runtime;
 
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.ui.ComponentContainer;
 import com.intellij.remoteServer.configuration.RemoteServer;
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import com.intellij.remoteServer.impl.runtime.deployment.DeploymentImpl;
+import com.intellij.remoteServer.impl.runtime.deployment.DeploymentTaskImpl;
 import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
 import com.intellij.remoteServer.runtime.ConnectionStatus;
 import com.intellij.remoteServer.runtime.Deployment;
@@ -14,6 +18,9 @@
 import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
 import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
 import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnectionData;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnectionDataNotAvailableException;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnector;
 import com.intellij.util.ParameterizedRunnable;
 import com.intellij.util.containers.ConcurrentHashMap;
 import org.jetbrains.annotations.NotNull;
@@ -25,6 +32,7 @@
  * @author nik
  */
 public class ServerConnectionImpl<D extends DeploymentConfiguration> implements ServerConnection<D> {
+  private static final Logger LOG = Logger.getInstance(ServerConnectionImpl.class);
   private final RemoteServer<?> myServer;
   private final ServerConnector<D> myConnector;
   private final ServerConnectionEventDispatcher myEventDispatcher;
@@ -101,9 +109,11 @@
         DeploymentSource source = task.getSource();
         String deploymentName = instance.getDeploymentName(source);
         myLocalDeployments.put(deploymentName, new DeploymentImpl(deploymentName, DeploymentStatus.DEPLOYING, null, null));
-        myLoggingHandlers.put(deploymentName, (LoggingHandlerImpl)task.getLoggingHandler());
+        LoggingHandlerImpl handler = (LoggingHandlerImpl)task.getLoggingHandler();
+        handler.printlnSystemMessage("Deploying '" + deploymentName + "'...");
+        myLoggingHandlers.put(deploymentName, handler);
         onDeploymentStarted.run(deploymentName);
-        instance.deploy(task, new DeploymentOperationCallbackImpl(deploymentName));
+        instance.deploy(task, new DeploymentOperationCallbackImpl(deploymentName, (DeploymentTaskImpl<D>)task, handler));
       }
     });
   }
@@ -159,15 +169,20 @@
     final String deploymentName = deployment.getName();
     myLocalDeployments.put(deploymentName, new DeploymentImpl(deploymentName, DeploymentStatus.UNDEPLOYING, null, null));
     myEventDispatcher.queueDeploymentsChanged(this);
+    final LoggingHandlerImpl loggingHandler = myLoggingHandlers.get(deploymentName);
+    loggingHandler.printlnSystemMessage("Undeploying '" + deploymentName + "'...");
     runtime.undeploy(new DeploymentRuntime.UndeploymentTaskCallback() {
       @Override
       public void succeeded() {
+        loggingHandler.printlnSystemMessage("'" + deploymentName + "' has been undeployed successfully.");
         myLocalDeployments.remove(deploymentName);
+        myLoggingHandlers.remove(deploymentName);
         myEventDispatcher.queueDeploymentsChanged(ServerConnectionImpl.this);
       }
 
       @Override
       public void errorOccurred(@NotNull String errorMessage) {
+        loggingHandler.printlnSystemMessage("Failed to undeploy '" + deploymentName + "': " + errorMessage);
         myLocalDeployments.put(deploymentName, new DeploymentImpl(deploymentName, DeploymentStatus.DEPLOYED, errorMessage, runtime));
         myEventDispatcher.queueDeploymentsChanged(ServerConnectionImpl.this);
       }
@@ -228,19 +243,51 @@
 
   private class DeploymentOperationCallbackImpl implements ServerRuntimeInstance.DeploymentOperationCallback {
     private final String myDeploymentName;
+    private final DeploymentTaskImpl<D> myDeploymentTask;
+    private final LoggingHandlerImpl myLoggingHandler;
 
-    public DeploymentOperationCallbackImpl(String deploymentName) {
+    public DeploymentOperationCallbackImpl(String deploymentName, DeploymentTaskImpl<D> deploymentTask, LoggingHandlerImpl handler) {
       myDeploymentName = deploymentName;
+      myDeploymentTask = deploymentTask;
+      myLoggingHandler = handler;
     }
 
     @Override
     public void succeeded(@NotNull DeploymentRuntime deployment) {
+      myLoggingHandler.printlnSystemMessage("'" + myDeploymentName + "' has been deployed successfully.");
       myLocalDeployments.put(myDeploymentName, new DeploymentImpl(myDeploymentName, DeploymentStatus.DEPLOYED, null, deployment));
       myEventDispatcher.queueDeploymentsChanged(ServerConnectionImpl.this);
+      DebugConnector<?,?> debugConnector = myDeploymentTask.getDebugConnector();
+      if (debugConnector != null) {
+        launchDebugger(debugConnector, deployment);
+      }
+    }
+
+    private <D extends DebugConnectionData, R extends DeploymentRuntime> void launchDebugger(@NotNull final DebugConnector<D, R> debugConnector,
+                                                                                             @NotNull DeploymentRuntime runtime) {
+      try {
+        final D debugInfo = debugConnector.getConnectionData((R)runtime);
+        ApplicationManager.getApplication().invokeLater(new Runnable() {
+          public void run() {
+            try {
+              debugConnector.getLauncher().startDebugSession(debugInfo, myDeploymentTask.getExecutionEnvironment(), myServer);
+            }
+            catch (ExecutionException e) {
+              myLoggingHandler.print("Cannot start debugger: " + e.getMessage() + "\n");
+              LOG.info(e);
+            }
+          }
+        });
+      }
+      catch (DebugConnectionDataNotAvailableException e) {
+        myLoggingHandler.print("Cannot retrieve debug connection: " + e.getMessage() + "\n");
+        LOG.info(e);
+      }
     }
 
     @Override
     public void errorOccurred(@NotNull String errorMessage) {
+      myLoggingHandler.printlnSystemMessage("Failed to deploy '" + myDeploymentName + "': " + errorMessage);
       myLocalDeployments.put(myDeploymentName, new DeploymentImpl(myDeploymentName, DeploymentStatus.NOT_DEPLOYED, errorMessage, null));
       myEventDispatcher.queueDeploymentsChanged(ServerConnectionImpl.this);
     }
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java
index 4372296..d9c717f 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java
@@ -13,11 +13,10 @@
  */
 public class ServerTaskExecutorImpl implements ServerTaskExecutor {
   private static final Logger LOG = Logger.getInstance(ServerTaskExecutorImpl.class);
-  private static final PooledThreadExecutor POOLED_THREAD_EXECUTOR = new PooledThreadExecutor();
   private final SequentialTaskExecutor myTaskExecutor;
 
   public ServerTaskExecutorImpl() {
-    myTaskExecutor = new SequentialTaskExecutor(POOLED_THREAD_EXECUTOR);
+    myTaskExecutor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
   }
 
   @Override
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java
index b8efa2e..3f34d7e 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java
@@ -1,11 +1,14 @@
 package com.intellij.remoteServer.impl.runtime.deployment;
 
+import com.intellij.execution.runners.ExecutionEnvironment;
 import com.intellij.openapi.project.Project;
 import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.runtime.deployment.debug.DebugConnector;
 import com.intellij.remoteServer.runtime.log.LoggingHandler;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * @author nik
@@ -15,12 +18,17 @@
   private final D myConfiguration;
   private final Project myProject;
   private final LoggingHandler myLoggingHandler;
+  private final DebugConnector<?,?> myDebugConnector;
+  private final ExecutionEnvironment myExecutionEnvironment;
 
-  public DeploymentTaskImpl(DeploymentSource source, D configuration, Project project, LoggingHandler loggingHandler) {
+  public DeploymentTaskImpl(DeploymentSource source, D configuration, Project project, LoggingHandler loggingHandler,
+                            DebugConnector<?, ?> connector, ExecutionEnvironment environment) {
     mySource = source;
     myConfiguration = configuration;
     myProject = project;
     myLoggingHandler = loggingHandler;
+    myDebugConnector = connector;
+    myExecutionEnvironment = environment;
   }
 
   @NotNull
@@ -43,4 +51,19 @@
   public Project getProject() {
     return myProject;
   }
+
+  @Override
+  public boolean isDebugMode() {
+    return myDebugConnector != null;
+  }
+
+  @Nullable
+  public DebugConnector<?, ?> getDebugConnector() {
+    return myDebugConnector;
+  }
+
+  @NotNull
+  public ExecutionEnvironment getExecutionEnvironment() {
+    return myExecutionEnvironment;
+  }
 }
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
index 503cd3c..bd5e010 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
@@ -27,6 +27,10 @@
     myConsole.print(s, ConsoleViewContentType.NORMAL_OUTPUT);
   }
 
+  public void printlnSystemMessage(@NotNull String s) {
+    myConsole.print(s + "\n", ConsoleViewContentType.SYSTEM_OUTPUT);
+  }
+
   @Override
   public void attachToProcess(@NotNull ProcessHandler handler) {
     myConsole.attachToProcess(handler);
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
index 8bf0af5..29b0c25 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
@@ -147,18 +147,18 @@
     }
     URL resource = PlatformTestCase.class.getClassLoader().getResource("idea/ApplicationInfo.xml");
     if (resource == null) {
-      resource = PlatformTestCase.class.getClassLoader().getResource("idea/IdeaApplicationInfo.xml");
+      resource = PlatformTestCase.class.getClassLoader().getResource("META-INF/UltimateLangXmlPlugin.xml");
       if (resource == null) {
-        resource = PlatformTestCase.class.getClassLoader().getResource("META-INF/UltimateLangXmlPlugin.xml");
+        resource = PlatformTestCase.class.getClassLoader().getResource("idea/IdeaApplicationInfo.xml");
         if (resource == null) {
           setPlatformPrefix("PlatformLangXml");
         }
         else {
-          setPlatformPrefix("UltimateLangXml");
+          setPlatformPrefix("Idea");
         }
       }
       else {
-        setPlatformPrefix("Idea");
+        setPlatformPrefix("UltimateLangXml");
       }
     }
   }
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index 9cfade6..404eff3 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -530,7 +530,7 @@
 
   public static <T> T assertOneElement(T[] ts) {
     Assert.assertNotNull(ts);
-    Assert.assertEquals(1, ts.length);
+    Assert.assertEquals(Arrays.asList(ts).toString(), 1, ts.length);
     return ts[0];
   }
 
diff --git a/platform/testFramework/testFramework.iml b/platform/testFramework/testFramework.iml
index 7985252..91e0821 100644
--- a/platform/testFramework/testFramework.iml
+++ b/platform/testFramework/testFramework.iml
@@ -26,6 +26,7 @@
     <orderEntry type="module" module-name="relaxng" exported="" scope="RUNTIME" />
     <orderEntry type="module" module-name="images" exported="" scope="RUNTIME" />
     <orderEntry type="module" module-name="RegExpSupport" exported="" scope="RUNTIME" />
+    <orderEntry type="module" module-name="remote-servers-impl" scope="RUNTIME" />
   </component>
 </module>
 
diff --git a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
index 443f07e..571b19c 100644
--- a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
+++ b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.util.containers;
 
+import com.intellij.openapi.util.Pair;
 import com.intellij.util.ArrayUtilRt;
 import com.intellij.util.Function;
 import org.jetbrains.annotations.NotNull;
@@ -60,6 +61,15 @@
     return map;
   }
 
+  public static <K, V> Map<K,V> newHashMap(Pair<K, V> first, Pair<K, V>[] entries) {
+    Map<K, V> map = newHashMap();
+    map.put(first.getFirst(), first.getSecond());
+    for (Pair<K, V> entry : entries) {
+      map.put(entry.getFirst(), entry.getSecond());
+    }
+    return map;
+  }
+
   @NotNull
   public static <K extends Comparable, V> TreeMap<K, V> newTreeMap() {
     return new TreeMap<K, V>();
diff --git a/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java b/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java
index bc0f868..607d0d4 100644
--- a/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java
+++ b/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java
@@ -72,6 +72,10 @@
     return Math.min(super.available(), myReadLimit - myBytesRead);
   }
 
+  protected int remainingLimit() {
+    return myReadLimit - myBytesRead;
+  }
+
   public synchronized void mark(final int readLimit) {
     throw new UnsupportedOperationException();
   }
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index 4e1754b..0d601b9 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.java
@@ -331,6 +331,7 @@
     public static final Icon JavaScript = IconLoader.getIcon("/fileTypes/javaScript.png"); // 16x16
     public static final Icon Jsp = IconLoader.getIcon("/fileTypes/jsp.png"); // 16x16
     public static final Icon Jspx = IconLoader.getIcon("/fileTypes/jspx.png"); // 16x16
+    public static final Icon Manifest = IconLoader.getIcon("/fileTypes/manifest.png"); // 16x16
     public static final Icon Properties = IconLoader.getIcon("/fileTypes/properties.png"); // 16x16
     public static final Icon Text = IconLoader.getIcon("/fileTypes/text.png"); // 16x16
     public static final Icon TypeScript = IconLoader.getIcon("/fileTypes/typeScript.png"); // 16x16
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java b/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
index c802ffa..57f60f7 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/DefaultLogger.java
@@ -46,7 +46,7 @@
   public void error(String message, @Nullable Throwable t, @NotNull String... details) {
     System.err.println("ERROR: " + message);
     if (t != null) t.printStackTrace();
-    if (details != null && details.length > 0) {
+    if (details.length > 0) {
       System.out.println("details: ");
       for (String detail : details) {
         System.out.println(detail);
diff --git a/platform/util/src/com/intellij/openapi/util/Key.java b/platform/util/src/com/intellij/openapi/util/Key.java
index f2b25db..2c3be89 100644
--- a/platform/util/src/com/intellij/openapi/util/Key.java
+++ b/platform/util/src/com/intellij/openapi/util/Key.java
@@ -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.
@@ -16,6 +16,7 @@
 package com.intellij.openapi.util;
 
 import com.intellij.util.containers.ConcurrentWeakValueIntObjectHashMap;
+import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -33,7 +34,7 @@
 public class Key<T> {
   private static final AtomicInteger ourKeysCounter = new AtomicInteger();
   private final int myIndex = ourKeysCounter.getAndIncrement();
-  private final String myName; // for debug purposes only
+  private final String myName;
   private static final ConcurrentWeakValueIntObjectHashMap<Key> allKeys = new ConcurrentWeakValueIntObjectHashMap<Key>();
 
   public Key(@NotNull @NonNls String name) {
@@ -102,4 +103,15 @@
     //noinspection unchecked
     return (Key<T>)allKeys.get(index);
   }
+
+  @Nullable
+  public static <T> Key<T> findKeyByName(String name) {
+    for (StripedLockIntObjectConcurrentHashMap.IntEntry<Key> key : allKeys.entries()) {
+      if (name.equals(key.getValue().myName)) {
+        //noinspection unchecked
+        return key.getValue();
+      }
+    }
+    return null;
+  }
 }
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index cd9192e..a44aec2 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -28,10 +28,7 @@
 import com.intellij.util.text.StringFactory;
 import gnu.trove.TObjectHashingStrategy;
 import org.intellij.lang.annotations.RegExp;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.annotations.*;
 
 import java.io.*;
 import java.lang.reflect.Method;
@@ -633,23 +630,23 @@
    * Please note that this method is symlink-unfriendly (i.e. result of "/path/to/link/../next" most probably will differ from
    * what {@link java.io.File#getCanonicalPath()} will return) - so use with care.
    */
-  @Nullable
+  @Contract("null -> null")
   public static String toCanonicalPath(@Nullable String path) {
     return toCanonicalPath(path, File.separatorChar);
   }
 
-  @Nullable
-  public static String toCanonicalPath(@Nullable String path, final char separatorChar) {
+  @Contract("null, _ -> null")
+  public static String toCanonicalPath(@Nullable String path, char separatorChar) {
     return toCanonicalPath(path, separatorChar, true);
   }
 
-  @Nullable
+  @Contract("null -> null")
   public static String toCanonicalUriPath(@Nullable String path) {
     return toCanonicalPath(path, '/', false);
   }
 
-  @Nullable
-  private static String toCanonicalPath(@Nullable String path, final char separatorChar, boolean removeLastSlash) {
+  @Contract("null, _, _ -> null")
+  private static String toCanonicalPath(@Nullable String path, char separatorChar, boolean removeLastSlash) {
     if (path == null || path.isEmpty()) {
       return path;
     }
@@ -682,7 +679,7 @@
           ++dots;
         }
         else {
-          result.append(c);
+          result.append('.');
         }
         separator = false;
       }
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java
index b5cd8b4..19affac 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java
@@ -21,6 +21,8 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.util.*;
 import java.util.concurrent.ConcurrentMap;
@@ -61,7 +63,7 @@
 
   /**
    * The default number of concurrency control segments.
-   **/
+   */
   static final int DEFAULT_SEGMENTS = Math.min(2, Runtime.getRuntime().availableProcessors()); // CHANGED FROM 16
 
   /**
@@ -76,40 +78,41 @@
    * unbounded retries if tables undergo continuous modification
    * which would make it impossible to obtain an accurate result.
    */
-  static final int RETRIES_BEFORE_LOCK = 2;
+  private static final int RETRIES_BEFORE_LOCK = 2;
 
     /* ---------------- Fields -------------- */
 
   /**
    * Mask value for indexing into segments. The upper bits of a
    * key's hash code are used to choose the segment.
-   **/
-  final int segmentMask;
+   */
+  private final int segmentMask;
 
   /**
    * Shift value for indexing within segments.
-   **/
-  final int segmentShift;
+   */
+  private final int segmentShift;
 
   /**
    * The segments, each of which is a specialized hash table
    */
-  final Segment[] segments;
+  private final Segment[] segments;
 
-  transient Set<K> keySet;
-  transient Set<Entry<K,V>> entrySet;
-  transient Collection<V> values;
+  private transient Set<K> keySet;
+  private transient Set<Entry<K, V>> entrySet;
+  private transient Collection<V> values;
   private final TObjectHashingStrategy<K> myHashingStrategy;
 
   /* ---------------- Small Utilities -------------- */
 
   /**
    * Returns the segment that should be used for key with given hash
+   *
    * @param hash the hash code for the key
    * @return the segment
    */
-  final Segment<K,V> segmentFor(int hash) {
-    return segments[(hash >>> segmentShift) & segmentMask];
+  private Segment<K, V> segmentFor(int hash) {
+    return segments[hash >>> segmentShift & segmentMask];
   }
 
   /* ---------------- Inner Classes -------------- */
@@ -117,7 +120,7 @@
   /**
    * ConcurrentHashMap list entry. Note that this is never exported
    * out as a user-visible Map.Entry.
-   *
+   * <p/>
    * Because the value field is volatile, not final, it is legal wrt
    * the Java Memory Model for an unsynchronized reader to see null
    * instead of initial value when read via a data race.  Although a
@@ -126,13 +129,13 @@
    * backup in case a null (pre-initialized) value is ever seen in
    * an unsynchronized access method.
    */
-  static final class HashEntry<K,V> {
-    final K key;
-    final int hash;
-    volatile V value;
-    final HashEntry<K,V> next;
+  private static final class HashEntry<K, V> {
+    private final K key;
+    private final int hash;
+    private volatile V value;
+    private final HashEntry<K, V> next;
 
-    HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
+    private HashEntry(K key, int hash, HashEntry<K, V> next, V value) {
       this.key = key;
       this.hash = hash;
       this.next = next;
@@ -144,8 +147,8 @@
    * Segments are specialized versions of hash tables.  This
    * subclasses from ReentrantLock opportunistically, just to
    * simplify some locking and avoid separate construction.
-   **/
-  static final class Segment<K,V> extends ReentrantLock implements Serializable {
+   */
+  private static final class Segment<K, V> extends ReentrantLock implements Serializable {
         /*
          * Segments maintain a table of entry lists that are ALWAYS
          * kept in a consistent state, so can be read without locking.
@@ -187,8 +190,8 @@
 
     /**
      * The number of elements in this segment's region.
-     **/
-    transient volatile int count;
+     */
+    private transient volatile int count;
 
     /**
      * Number of updates that alter the size of the table. This is
@@ -198,31 +201,32 @@
      * we might have an inconsistent view of state so (usually)
      * must retry.
      */
-    transient int modCount;
+    private transient int modCount;
 
     /**
      * The table is rehashed when its size exceeds this threshold.
      * (The value of this field is always (int)(capacity *
      * loadFactor).)
      */
-    transient int threshold;
+    private transient int threshold;
 
     /**
      * The per-segment table. Declared as a raw type, casted
      * to HashEntry<K,V> on each use.
      */
-    transient volatile HashEntry[] table;
+    private transient volatile HashEntry[] table;
 
     /**
      * The load factor for the hash table.  Even though this value
      * is same for all segments, it is replicated to avoid needing
      * links to outer object.
+     *
      * @serial
      */
-    final float loadFactor;
+    private final float loadFactor;
     private final TObjectHashingStrategy<K> myHashingStrategy;
 
-    Segment(int initialCapacity, float lf, TObjectHashingStrategy<K> hashingStrategy) {
+    private Segment(int initialCapacity, float lf, TObjectHashingStrategy<K> hashingStrategy) {
       loadFactor = lf;
       myHashingStrategy = hashingStrategy;
       setTable(new HashEntry[initialCapacity]);
@@ -231,8 +235,8 @@
     /**
      * Set table to new HashEntry array.
      * Call only while holding lock or in constructor.
-     **/
-    void setTable(HashEntry[] newTable) {
+     */
+    private void setTable(HashEntry[] newTable) {
       threshold = (int)(newTable.length * loadFactor);
       table = newTable;
     }
@@ -240,9 +244,9 @@
     /**
      * Return properly casted first entry of bin for given hash
      */
-    HashEntry<K,V> getFirst(int hash) {
+    private HashEntry<K, V> getFirst(int hash) {
       HashEntry[] tab = table;
-      return (HashEntry<K,V>) tab[hash & (tab.length - 1)];
+      return (HashEntry<K, V>)tab[hash & tab.length - 1];
     }
 
     /**
@@ -252,25 +256,27 @@
      * its table assignment, which is legal under memory model
      * but is not known to ever occur.
      */
-    V readValueUnderLock(HashEntry<K,V> e) {
+    private V readValueUnderLock(HashEntry<K, V> e) {
       lock();
       try {
         return e.value;
-      } finally {
+      }
+      finally {
         unlock();
       }
     }
 
         /* Specialized implementations of map methods */
 
-    V get(K key, int hash) {
+    private V get(K key, int hash) {
       if (count != 0) { // read-volatile
-        HashEntry<K,V> e = getFirst(hash);
+        HashEntry<K, V> e = getFirst(hash);
         while (e != null) {
-          if (e.hash == hash && myHashingStrategy.equals(key,e.key)) {
+          if (e.hash == hash && myHashingStrategy.equals(key, e.key)) {
             V v = e.value;
-            if (v != null)
+            if (v != null) {
               return v;
+            }
             return readValueUnderLock(e); // recheck
           }
           e = e.next;
@@ -279,43 +285,47 @@
       return null;
     }
 
-    boolean containsKey(K key, int hash) {
+    private boolean containsKey(K key, int hash) {
       if (count != 0) { // read-volatile
-        HashEntry<K,V> e = getFirst(hash);
+        HashEntry<K, V> e = getFirst(hash);
         while (e != null) {
-          if (e.hash == hash && myHashingStrategy.equals(key,e.key))
+          if (e.hash == hash && myHashingStrategy.equals(key, e.key)) {
             return true;
+          }
           e = e.next;
         }
       }
       return false;
     }
 
-    boolean containsValue(Object value) {
+    private boolean containsValue(Object value) {
       if (count != 0) { // read-volatile
         HashEntry[] tab = table;
-        int len = tab.length;
-        for (int i = 0 ; i < len; i++) {
-          for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i];
-               e != null ;
+        for (HashEntry tabEntry : tab) {
+          for (HashEntry<K, V> e = (HashEntry<K, V>)tabEntry;
+               e != null;
                e = e.next) {
             V v = e.value;
             if (v == null) // recheck
+            {
               v = readValueUnderLock(e);
-            if (value.equals(v))
+            }
+            if (value.equals(v)) {
               return true;
+            }
           }
         }
       }
       return false;
     }
 
-    boolean replace(K key, int hash, V oldValue, V newValue) {
+    private boolean replace(K key, int hash, V oldValue, V newValue) {
       lock();
       try {
-        HashEntry<K,V> e = getFirst(hash);
-        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key,e.key)))
+        HashEntry<K, V> e = getFirst(hash);
+        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key, e.key))) {
           e = e.next;
+        }
 
         boolean replaced = false;
         if (e != null && oldValue.equals(e.value)) {
@@ -323,17 +333,19 @@
           e.value = newValue;
         }
         return replaced;
-      } finally {
+      }
+      finally {
         unlock();
       }
     }
 
-    V replace(K key, int hash, V newValue) {
+    private V replace(K key, int hash, V newValue) {
       lock();
       try {
-        HashEntry<K,V> e = getFirst(hash);
-        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key,e.key)))
+        HashEntry<K, V> e = getFirst(hash);
+        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key, e.key))) {
           e = e.next;
+        }
 
         V oldValue = null;
         if (e != null) {
@@ -341,48 +353,54 @@
           e.value = newValue;
         }
         return oldValue;
-      } finally {
+      }
+      finally {
         unlock();
       }
     }
 
-
-    V put(K key, int hash, V value, boolean onlyIfAbsent) {
+    private V put(K key, int hash, V value, boolean onlyIfAbsent) {
       lock();
       try {
         int c = count;
         if (c++ > threshold) // ensure capacity
+        {
           rehash();
+        }
         HashEntry[] tab = table;
-        int index = hash & (tab.length - 1);
-        HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
-        HashEntry<K,V> e = first;
-        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key,e.key)))
+        int index = hash & tab.length - 1;
+        HashEntry<K, V> first = (HashEntry<K, V>)tab[index];
+        HashEntry<K, V> e = first;
+        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key, e.key))) {
           e = e.next;
+        }
 
         V oldValue;
         if (e != null) {
           oldValue = e.value;
-          if (!onlyIfAbsent)
+          if (!onlyIfAbsent) {
             e.value = value;
+          }
         }
         else {
           oldValue = null;
           ++modCount;
-          tab[index] = new HashEntry<K,V>(key, hash, first, value);
+          tab[index] = new HashEntry<K, V>(key, hash, first, value);
           count = c; // write-volatile
         }
         return oldValue;
-      } finally {
+      }
+      finally {
         unlock();
       }
     }
 
-    void rehash() {
+    private void rehash() {
       HashEntry[] oldTable = table;
       int oldCapacity = oldTable.length;
-      if (oldCapacity >= MAXIMUM_CAPACITY)
+      if (oldCapacity >= MAXIMUM_CAPACITY) {
         return;
+      }
 
             /*
              * Reclassify nodes in each list to new Map.  Because we are
@@ -401,24 +419,25 @@
       HashEntry[] newTable = new HashEntry[oldCapacity << 1];
       threshold = (int)(newTable.length * loadFactor);
       int sizeMask = newTable.length - 1;
-      for (int i = 0; i < oldCapacity ; i++) {
+      for (int i = 0; i < oldCapacity; i++) {
         // We need to guarantee that any existing reads of old Map can
         //  proceed. So we cannot yet null out each bin.
-        HashEntry<K,V> e = (HashEntry<K,V>)oldTable[i];
+        HashEntry<K, V> e = (HashEntry<K, V>)oldTable[i];
 
         if (e != null) {
-          HashEntry<K,V> next = e.next;
+          HashEntry<K, V> next = e.next;
           int idx = e.hash & sizeMask;
 
           //  Single node on list
-          if (next == null)
+          if (next == null) {
             newTable[idx] = e;
+          }
 
           else {
             // Reuse trailing consecutive sequence at same slot
-            HashEntry<K,V> lastRun = e;
+            HashEntry<K, V> lastRun = e;
             int lastIdx = idx;
-            for (HashEntry<K,V> last = next;
+            for (HashEntry<K, V> last = next;
                  last != null;
                  last = last.next) {
               int k = last.hash & sizeMask;
@@ -430,11 +449,11 @@
             newTable[lastIdx] = lastRun;
 
             // Clone all remaining nodes
-            for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
+            for (HashEntry<K, V> p = e; p != lastRun; p = p.next) {
               int k = p.hash & sizeMask;
-              HashEntry<K,V> n = (HashEntry<K,V>)newTable[k];
-              newTable[k] = new HashEntry<K,V>(p.key, p.hash,
-                                               n, p.value);
+              HashEntry<K, V> n = (HashEntry<K, V>)newTable[k];
+              newTable[k] = new HashEntry<K, V>(p.key, p.hash,
+                                                n, p.value);
             }
           }
         }
@@ -445,16 +464,17 @@
     /**
      * Remove; match on key only if value null, else match both.
      */
-    V remove(K key, int hash, Object value) {
+    private V remove(K key, int hash, V value) {
       lock();
       try {
         int c = count - 1;
         HashEntry[] tab = table;
-        int index = hash & (tab.length - 1);
-        HashEntry<K,V> first = (HashEntry<K,V>)tab[index];
-        HashEntry<K,V> e = first;
-        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key,e.key)))
+        int index = hash & tab.length - 1;
+        HashEntry<K, V> first = (HashEntry<K, V>)tab[index];
+        HashEntry<K, V> e = first;
+        while (e != null && (e.hash != hash || !myHashingStrategy.equals(key, e.key))) {
           e = e.next;
+        }
 
         V oldValue = null;
         if (e != null) {
@@ -465,94 +485,101 @@
             // in list, but all preceding ones need to be
             // cloned.
             ++modCount;
-            HashEntry<K,V> newFirst = e.next;
-            for (HashEntry<K,V> p = first; p != e; p = p.next)
-              newFirst = new HashEntry<K,V>(p.key, p.hash,
-                                            newFirst, p.value);
+            HashEntry<K, V> newFirst = e.next;
+            for (HashEntry<K, V> p = first; p != e; p = p.next) {
+              newFirst = new HashEntry<K, V>(p.key, p.hash, newFirst, p.value);
+            }
             tab[index] = newFirst;
             count = c; // write-volatile
           }
         }
         return oldValue;
-      } finally {
+      }
+      finally {
         unlock();
       }
     }
 
-    void clear() {
+    private void clear() {
       if (count != 0) {
         lock();
         try {
           HashEntry[] tab = table;
-          for (int i = 0; i < tab.length ; i++)
+          for (int i = 0; i < tab.length; i++) {
             tab[i] = null;
+          }
           ++modCount;
           count = 0; // write-volatile
-        } finally {
+        }
+        finally {
           unlock();
         }
       }
     }
   }
 
-
-
     /* ---------------- Public operations -------------- */
 
   public ConcurrentHashMap(TObjectHashingStrategy<K> hashingStrategy) {
-    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS,hashingStrategy);
+    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS, hashingStrategy);
   }
 
   /**
    * Creates a new, empty map with the specified initial
    * capacity, load factor, and concurrency level.
    *
-   * @param initialCapacity the initial capacity. The implementation
-   * performs internal sizing to accommodate this many elements.
-   * @param loadFactor  the load factor threshold, used to control resizing.
-   * Resizing may be performed when the average number of elements per
-   * bin exceeds this threshold.
+   * @param initialCapacity  the initial capacity. The implementation
+   *                         performs internal sizing to accommodate this many elements.
+   * @param loadFactor       the load factor threshold, used to control resizing.
+   *                         Resizing may be performed when the average number of elements per
+   *                         bin exceeds this threshold.
    * @param concurrencyLevel the estimated number of concurrently
-   * updating threads. The implementation performs internal sizing
-   * to try to accommodate this many threads.
+   *                         updating threads. The implementation performs internal sizing
+   *                         to try to accommodate this many threads.
    * @throws IllegalArgumentException if the initial capacity is
-   * negative or the load factor or concurrencyLevel are
-   * nonpositive.
+   *                                  negative or the load factor or concurrencyLevel are
+   *                                  nonpositive.
    */
   public ConcurrentHashMap(int initialCapacity,
                            float loadFactor, int concurrencyLevel) {
-    this(initialCapacity,loadFactor, concurrencyLevel,null);
+    this(initialCapacity, loadFactor, concurrencyLevel, null);
   }
-  public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, TObjectHashingStrategy<K> hashingStrategy) {
-    if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
-      throw new IllegalArgumentException();
 
-    if (concurrencyLevel > MAX_SEGMENTS)
+  public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, TObjectHashingStrategy<K> hashingStrategy) {
+    if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
+      throw new IllegalArgumentException();
+    }
+
+    if (concurrencyLevel > MAX_SEGMENTS) {
       concurrencyLevel = MAX_SEGMENTS;
+    }
 
     // Find power-of-two sizes best matching arguments
-    int sshift = 0;
     int ssize = 1;
     while (ssize < concurrencyLevel) {
-      ++sshift;
       ssize <<= 1;
     }
-    segmentShift = 12; // the middle of the hash is much more random that its HSB. Especially when we use TObjectHashingStrategy.CANONICAl as a hash provider
+    segmentShift =
+      12; // the middle of the hash is much more random that its HSB. Especially when we use TObjectHashingStrategy.CANONICAl as a hash provider
     segmentMask = ssize - 1;
     segments = new Segment[ssize];
 
-    if (initialCapacity > MAXIMUM_CAPACITY)
+    if (initialCapacity > MAXIMUM_CAPACITY) {
       initialCapacity = MAXIMUM_CAPACITY;
+    }
     int c = initialCapacity / ssize;
-    if (c * ssize < initialCapacity)
+    if (c * ssize < initialCapacity) {
       ++c;
+    }
     int cap = 1;
-    while (cap < c)
+    while (cap < c) {
       cap <<= 1;
+    }
 
     hashingStrategy = hashingStrategy == null ? this : hashingStrategy;
-    for (int i = 0; i < segments.length; ++i)
-      segments[i] = new Segment<K,V>(cap, loadFactor,hashingStrategy);
+    for (int i = 0; i < segments.length; ++i) {
+      segments[i] = new Segment<K, V>(cap, loadFactor, hashingStrategy);
+    }
     myHashingStrategy = hashingStrategy;
   }
 
@@ -561,9 +588,9 @@
    * capacity, and with default load factor and concurrencyLevel.
    *
    * @param initialCapacity the initial capacity. The implementation
-   * performs internal sizing to accommodate this many elements.
+   *                        performs internal sizing to accommodate this many elements.
    * @throws IllegalArgumentException if the initial capacity of
-   * elements is negative.
+   *                                  elements is negative.
    */
   public ConcurrentHashMap(int initialCapacity) {
     this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
@@ -582,10 +609,11 @@
    * map is created with a capacity of twice the number of mappings in
    * the given map or 11 (whichever is greater), and a default load factor
    * and concurrencyLevel.
+   *
    * @param t the map
    */
   public ConcurrentHashMap(Map<? extends K, ? extends V> t) {
-    this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1,
+    this(Math.max((int)(t.size() / DEFAULT_LOAD_FACTOR) + 1,
                   11),
          DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
     putAll(t);
@@ -607,10 +635,12 @@
     int[] mc = new int[segments.length];
     int mcsum = 0;
     for (int i = 0; i < segments.length; ++i) {
-      if (segments[i].count != 0)
+      if (segments[i].count != 0) {
         return false;
-      else
+      }
+      else {
         mcsum += mc[i] = segments[i].modCount;
+      }
     }
     // If mcsum happens to be zero, then we know we got a snapshot
     // before any modifications at all were made.  This is
@@ -618,8 +648,9 @@
     if (mcsum != 0) {
       for (int i = 0; i < segments.length; ++i) {
         if (segments[i].count != 0 ||
-            mc[i] != segments[i].modCount)
+            mc[i] != segments[i].modCount) {
           return false;
+        }
       }
     }
     return true;
@@ -651,8 +682,9 @@
           }
         }
       }
-      if (check == sum)
+      if (check == sum) {
         break;
+      }
     }
     if (check != sum) { // Resort to locking all segments
       sum = 0;
@@ -667,12 +699,12 @@
   /**
    * Returns the value to which the specified key is mapped in this table.
    *
-   * @param   key   a key in the table.
-   * @return  the value to which the key is mapped in this table;
-   *          <tt>null</tt> if the key is not mapped to any value in
-   *          this table.
-   * @throws  NullPointerException  if the key is
-   *               <tt>null</tt>.
+   * @param key a key in the table.
+   * @return the value to which the key is mapped in this table;
+   * <tt>null</tt> if the key is not mapped to any value in
+   * this table.
+   * @throws NullPointerException if the key is
+   *                              <tt>null</tt>.
    */
   @Override
   public V get(Object key) {
@@ -683,12 +715,12 @@
   /**
    * Tests if the specified object is a key in this table.
    *
-   * @param   key   possible key.
-   * @return  <tt>true</tt> if and only if the specified object
-   *          is a key in this table, as determined by the
-   *          <tt>equals</tt> method; <tt>false</tt> otherwise.
-   * @throws  NullPointerException  if the key is
-   *               <tt>null</tt>.
+   * @param key possible key.
+   * @return <tt>true</tt> if and only if the specified object
+   * is a key in this table, as determined by the
+   * <tt>equals</tt> method; <tt>false</tt> otherwise.
+   * @throws NullPointerException if the key is
+   *                              <tt>null</tt>.
    */
   @Override
   public boolean containsKey(Object key) {
@@ -705,11 +737,10 @@
    * @param value value whose presence in this map is to be tested.
    * @return <tt>true</tt> if this map maps one or more keys to the
    * specified value.
-   * @throws  NullPointerException  if the value is <tt>null</tt>.
+   * @throws NullPointerException if the value is <tt>null</tt>.
    */
   @Override
   public boolean containsValue(@NotNull Object value) {
-
     // See explanation of modCount use above
 
     final Segment[] segments = this.segments;
@@ -722,8 +753,9 @@
       for (int i = 0; i < segments.length; ++i) {
         int c = segments[i].count;
         mcsum += mc[i] = segments[i].modCount;
-        if (segments[i].containsValue(value))
+        if (segments[i].containsValue(value)) {
           return true;
+        }
       }
       boolean cleanSweep = true;
       if (mcsum != 0) {
@@ -735,23 +767,27 @@
           }
         }
       }
-      if (cleanSweep)
+      if (cleanSweep) {
         return false;
+      }
     }
     // Resort to locking all segments
-    for (int i = 0; i < segments.length; ++i)
-      segments[i].lock();
+    for (Segment segment : segments) {
+      segment.lock();
+    }
     boolean found = false;
     try {
-      for (int i = 0; i < segments.length; ++i) {
-        if (segments[i].containsValue(value)) {
+      for (Segment segment : segments) {
+        if (segment.containsValue(value)) {
           found = true;
           break;
         }
       }
-    } finally {
-      for (int i = 0; i < segments.length; ++i)
-        segments[i].unlock();
+    }
+    finally {
+      for (Segment segment : segments) {
+        segment.unlock();
+      }
     }
     return found;
   }
@@ -763,13 +799,13 @@
    * full compatibility with class {@link java.util.Hashtable},
    * which supported this method prior to introduction of the
    * Java Collections framework.
-
-   * @param      value   a value to search for.
-   * @return     <tt>true</tt> if and only if some key maps to the
-   *             <tt>value</tt> argument in this table as
-   *             determined by the <tt>equals</tt> method;
-   *             <tt>false</tt> otherwise.
-   * @throws  NullPointerException  if the value is <tt>null</tt>.
+   *
+   * @param value a value to search for.
+   * @return <tt>true</tt> if and only if some key maps to the
+   * <tt>value</tt> argument in this table as
+   * determined by the <tt>equals</tt> method;
+   * <tt>false</tt> otherwise.
+   * @throws NullPointerException if the value is <tt>null</tt>.
    */
   public boolean contains(Object value) {
     return containsValue(value);
@@ -779,16 +815,16 @@
    * Maps the specified <tt>key</tt> to the specified
    * <tt>value</tt> in this table. Neither the key nor the
    * value can be <tt>null</tt>.
-   *
+   * <p/>
    * <p> The value can be retrieved by calling the <tt>get</tt> method
    * with a key that is equal to the original key.
    *
-   * @param      key     the table key.
-   * @param      value   the value.
-   * @return     the previous value of the specified key in this table,
-   *             or <tt>null</tt> if it did not have one.
-   * @throws  NullPointerException  if the key or value is
-   *               <tt>null</tt>.
+   * @param key   the table key.
+   * @param value the value.
+   * @return the previous value of the specified key in this table,
+   * or <tt>null</tt> if it did not have one.
+   * @throws NullPointerException if the key or value is
+   *                              <tt>null</tt>.
    */
   @Override
   public V put(K key, @NotNull V value) {
@@ -807,12 +843,13 @@
    *      return map.get(key);
    * </pre>
    * Except that the action is performed atomically.
-   * @param key key with which the specified value is to be associated.
+   *
+   * @param key   key with which the specified value is to be associated.
    * @param value value to be associated with the specified key.
    * @return previous value associated with specified key, or <tt>null</tt>
-   *         if there was no mapping for key.
+   * if there was no mapping for key.
    * @throws NullPointerException if the specified key or value is
-   *            <tt>null</tt>.
+   *                              <tt>null</tt>.
    */
   @Override
   public V putIfAbsent(@NotNull K key, @NotNull V value) {
@@ -823,15 +860,17 @@
 
   /**
    * Copies all of the mappings from the specified map to this one.
-   *
+   * <p/>
    * These mappings replace any mappings that this map had for any of the
    * keys currently in the specified Map.
    *
    * @param t Mappings to be stored in this map.
    */
   @Override
-  public void putAll(Map<? extends K, ? extends V> t) {
-    for (Iterator<? extends Entry<? extends K, ? extends V>> it = (Iterator<? extends Entry<? extends K, ? extends V>>) t.entrySet().iterator(); it.hasNext(); ) {
+  public void putAll(@NotNull Map<? extends K, ? extends V> t) {
+    for (
+      Iterator<? extends Entry<? extends K, ? extends V>> it = (Iterator<? extends Entry<? extends K, ? extends V>>)t.entrySet().iterator();
+      it.hasNext(); ) {
       Entry<? extends K, ? extends V> e = it.next();
       put(e.getKey(), e.getValue());
     }
@@ -841,11 +880,11 @@
    * Removes the key (and its corresponding value) from this
    * table. This method does nothing if the key is not in the table.
    *
-   * @param   key   the key that needs to be removed.
-   * @return  the value to which the key had been mapped in this table,
-   *          or <tt>null</tt> if the key did not have a mapping.
-   * @throws  NullPointerException  if the key is
-   *               <tt>null</tt>.
+   * @param key the key that needs to be removed.
+   * @return the value to which the key had been mapped in this table,
+   * or <tt>null</tt> if the key did not have a mapping.
+   * @throws NullPointerException if the key is
+   *                              <tt>null</tt>.
    */
   @Override
   public V remove(Object key) {
@@ -863,19 +902,20 @@
    * } else return false;
    * </pre>
    * except that the action is performed atomically.
-   * @param key key with which the specified value is associated.
+   *
+   * @param key   key with which the specified value is associated.
    * @param value value associated with the specified key.
    * @return true if the value was removed
    * @throws NullPointerException if the specified key is
-   *            <tt>null</tt>.
+   *                              <tt>null</tt>.
    */
   @Override
   public boolean remove(@NotNull Object key, Object value) {
     int hash = myHashingStrategy.computeHashCode((K)key);
-    return remove((K)key, hash, value);
+    return remove((K)key, hash, (V)value);
   }
 
-  public boolean remove(@NotNull K key, int hash, Object value) {
+  public boolean remove(@NotNull K key, int hash, V value) {
     return segmentFor(hash).remove(key, hash, value) != null;
   }
 
@@ -889,12 +929,13 @@
    * } else return false;
    * </pre>
    * except that the action is performed atomically.
-   * @param key key with which the specified value is associated.
+   *
+   * @param key      key with which the specified value is associated.
    * @param oldValue value expected to be associated with the specified key.
    * @param newValue value to be associated with the specified key.
    * @return true if the value was replaced
    * @throws NullPointerException if the specified key or values are
-   * <tt>null</tt>.
+   *                              <tt>null</tt>.
    */
   @Override
   public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) {
@@ -911,12 +952,13 @@
    * } else return null;
    * </pre>
    * except that the action is performed atomically.
-   * @param key key with which the specified value is associated.
+   *
+   * @param key   key with which the specified value is associated.
    * @param value value to be associated with the specified key.
    * @return previous value associated with specified key, or <tt>null</tt>
-   *         if there was no mapping for key.
+   * if there was no mapping for key.
    * @throws NullPointerException if the specified key or value is
-   *            <tt>null</tt>.
+   *                              <tt>null</tt>.
    */
   @Override
   public V replace(@NotNull K key, @NotNull V value) {
@@ -949,10 +991,11 @@
    *
    * @return a set view of the keys contained in this map.
    */
+  @NotNull
   @Override
   public Set<K> keySet() {
     Set<K> ks = keySet;
-    return (ks != null) ? ks : (keySet = new KeySet());
+    return ks != null ? ks : (keySet = new KeySet());
   }
 
 
@@ -972,10 +1015,11 @@
    *
    * @return a collection view of the values contained in this map.
    */
+  @NotNull
   @Override
   public Collection<V> values() {
     Collection<V> vs = values;
-    return (vs != null) ? vs : (values = new Values());
+    return vs == null ? (values = new Values()) : vs;
   }
 
 
@@ -996,18 +1040,19 @@
    *
    * @return a collection view of the mappings contained in this map.
    */
+  @NotNull
   @Override
-  public Set<Entry<K,V>> entrySet() {
-    Set<Entry<K,V>> es = entrySet;
-    return (es != null) ? es : (entrySet = (Set<Entry<K,V>>) (Set) new EntrySet());
+  public Set<Entry<K, V>> entrySet() {
+    Set<Entry<K, V>> es = entrySet;
+    return es != null ? es : (entrySet = (Set<Entry<K, V>>)(Set)new EntrySet());
   }
 
 
   /**
    * Returns an enumeration of the keys in this table.
    *
-   * @return  an enumeration of the keys in this table.
-   * @see     #keySet
+   * @return an enumeration of the keys in this table.
+   * @see #keySet
    */
   public Enumeration<K> keys() {
     return new KeyIterator();
@@ -1016,8 +1061,8 @@
   /**
    * Returns an enumeration of the values in this table.
    *
-   * @return  an enumeration of the values in this table.
-   * @see     #values
+   * @return an enumeration of the values in this table.
+   * @see #values
    */
   public Enumeration<V> elements() {
     return new ValueIterator();
@@ -1025,36 +1070,40 @@
 
     /* ---------------- Iterator Support -------------- */
 
-  abstract class HashIterator {
-    int nextSegmentIndex;
-    int nextTableIndex;
-    HashEntry[] currentTable;
-    HashEntry<K, V> nextEntry;
+  private abstract class HashIterator {
+    private int nextSegmentIndex;
+    private int nextTableIndex;
+    private HashEntry[] currentTable;
+    private HashEntry<K, V> nextEntry;
     HashEntry<K, V> lastReturned;
 
-    HashIterator() {
+    private HashIterator() {
       nextSegmentIndex = segments.length - 1;
       nextTableIndex = -1;
       advance();
     }
 
-    public boolean hasMoreElements() { return hasNext(); }
+    public boolean hasMoreElements() {
+      return hasNext();
+    }
 
-    final void advance() {
-      if (nextEntry != null && (nextEntry = nextEntry.next) != null)
+    private void advance() {
+      if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
         return;
+      }
 
       while (nextTableIndex >= 0) {
-        if ( (nextEntry = (HashEntry<K,V>)currentTable[nextTableIndex--]) != null)
+        if ((nextEntry = (HashEntry<K, V>)currentTable[nextTableIndex--]) != null) {
           return;
+        }
       }
 
       while (nextSegmentIndex >= 0) {
-        Segment seg = (Segment)segments[nextSegmentIndex--];
+        Segment seg = segments[nextSegmentIndex--];
         if (seg.count != 0) {
           currentTable = seg.table;
           for (int j = currentTable.length - 1; j >= 0; --j) {
-            if ( (nextEntry = (HashEntry<K,V>)currentTable[j]) != null) {
+            if ((nextEntry = (HashEntry<K, V>)currentTable[j]) != null) {
               nextTableIndex = j - 1;
               return;
             }
@@ -1063,38 +1112,51 @@
       }
     }
 
-    public boolean hasNext() { return nextEntry != null; }
+    public boolean hasNext() {
+      return nextEntry != null;
+    }
 
-    HashEntry<K,V> nextEntry() {
-      if (nextEntry == null)
+    HashEntry<K, V> nextEntry() {
+      if (nextEntry == null) {
         throw new NoSuchElementException();
+      }
       lastReturned = nextEntry;
       advance();
       return lastReturned;
     }
 
     public void remove() {
-      if (lastReturned == null)
+      if (lastReturned == null) {
         throw new IllegalStateException();
+      }
       ConcurrentHashMap.this.remove(lastReturned.key);
       lastReturned = null;
     }
   }
 
-  final class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
+  private final class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
     @Override
-    public K next() { return super.nextEntry().key; }
+    public K next() {
+      return super.nextEntry().key;
+    }
+
     @Override
-    public K nextElement() { return super.nextEntry().key; }
+    public K nextElement() {
+      return super.nextEntry().key;
+    }
   }
 
-  final class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
+  private final class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
     @Override
-    public V next() { return super.nextEntry().value; }
-    @Override
-    public V nextElement() { return super.nextEntry().value; }
-  }
+    public V next() {
+      return super.nextEntry().value;
+    }
 
+    @Override
+    public V nextElement() {
+      return super.nextEntry().value;
+    }
+  }
 
 
   /**
@@ -1103,202 +1165,242 @@
    * cannot return internal HashEntry objects. Instead, the iterator
    * itself acts as a forwarding pseudo-entry.
    */
-  final class EntryIterator extends HashIterator implements Entry<K,V>, Iterator<Entry<K,V>> {
+  private final class EntryIterator extends HashIterator implements Entry<K, V>, Iterator<Entry<K, V>> {
     @Override
-    public Entry<K,V> next() {
+    public Entry<K, V> next() {
       nextEntry();
       return this;
     }
 
     @Override
     public K getKey() {
-      if (lastReturned == null)
+      if (lastReturned == null) {
         throw new IllegalStateException("Entry was removed");
+      }
       return lastReturned.key;
     }
 
     @Override
     public V getValue() {
-      if (lastReturned == null)
+      if (lastReturned == null) {
         throw new IllegalStateException("Entry was removed");
+      }
       return get(lastReturned.key);
     }
 
     @Override
     public V setValue(V value) {
-      if (lastReturned == null)
+      if (lastReturned == null) {
         throw new IllegalStateException("Entry was removed");
+      }
       return put(lastReturned.key, value);
     }
 
     public boolean equals(Object o) {
       // If not acting as entry, just use default.
-      if (lastReturned == null)
+      if (lastReturned == null) {
         return super.equals(o);
-      if (!(o instanceof Entry))
+      }
+      if (!(o instanceof Entry)) {
         return false;
+      }
       Entry e = (Entry)o;
       K o1 = getKey();
       K o2 = (K)e.getKey();
-      return (o1 == null ? o2 == null : myHashingStrategy.equals(o1,o2)) && eq(getValue(), e.getValue());
+      return (o1 == null ? o2 == null : myHashingStrategy.equals(o1, o2)) && eq(getValue(), e.getValue());
     }
 
     public int hashCode() {
       // If not acting as entry, just use default.
-      if (lastReturned == null)
+      if (lastReturned == null) {
         return super.hashCode();
+      }
 
       Object k = getKey();
       Object v = getValue();
-      return ((k == null) ? 0 : k.hashCode()) ^
-             ((v == null) ? 0 : v.hashCode());
+      return (k == null ? 0 : k.hashCode()) ^
+             (v == null ? 0 : v.hashCode());
     }
 
     public String toString() {
       // If not acting as entry, just use default.
-      if (lastReturned == null)
+      if (lastReturned == null) {
         return super.toString();
-      else
+      }
+      else {
         return getKey() + "=" + getValue();
+      }
     }
 
-    boolean eq(Object o1, Object o2) {
-      return (o1 == null ? o2 == null : o1.equals(o2));
+    private boolean eq(Object o1, Object o2) {
+      return o1 == null ? o2 == null : o1.equals(o2);
     }
-
   }
 
-  final class KeySet extends AbstractSet<K> {
+  private final class KeySet extends AbstractSet<K> {
+    @NotNull
     @Override
     public Iterator<K> iterator() {
       return new KeyIterator();
     }
+
     @Override
     public int size() {
       return ConcurrentHashMap.this.size();
     }
+
     @Override
     public boolean contains(Object o) {
       return containsKey(o);
     }
+
     @Override
     public boolean remove(Object o) {
       return ConcurrentHashMap.this.remove(o) != null;
     }
+
     @Override
     public void clear() {
       ConcurrentHashMap.this.clear();
     }
+
+    @NotNull
     @Override
     public Object[] toArray() {
       Collection<K> c = new ArrayList<K>();
-      for (Iterator<K> i = iterator(); i.hasNext(); )
-        c.add(i.next());
+      for (K k : this) {
+        c.add(k);
+      }
       return c.toArray();
     }
+
+    @NotNull
     @Override
-    public <T> T[] toArray(T[] a) {
+    public <T> T[] toArray(@NotNull T[] a) {
       Collection<K> c = new ArrayList<K>();
-      for (Iterator<K> i = iterator(); i.hasNext(); )
-        c.add(i.next());
+      for (K k : this) {
+        c.add(k);
+      }
       return c.toArray(a);
     }
   }
 
-  final class Values extends AbstractCollection<V> {
+  private final class Values extends AbstractCollection<V> {
+    @NotNull
     @Override
     public Iterator<V> iterator() {
       return new ValueIterator();
     }
+
     @Override
     public int size() {
       return ConcurrentHashMap.this.size();
     }
+
     @Override
     public boolean contains(Object o) {
       return containsValue(o);
     }
+
     @Override
     public void clear() {
       ConcurrentHashMap.this.clear();
     }
+
+    @NotNull
     @Override
     public Object[] toArray() {
       Collection<V> c = new ArrayList<V>();
-      for (Iterator<V> i = iterator(); i.hasNext(); )
-        c.add(i.next());
+      for (V v : this) {
+        c.add(v);
+      }
       return c.toArray();
     }
+
+    @NotNull
     @Override
-    public <T> T[] toArray(T[] a) {
+    public <T> T[] toArray(@NotNull T[] a) {
       Collection<V> c = new ArrayList<V>();
-      for (Iterator<V> i = iterator(); i.hasNext(); )
-        c.add(i.next());
+      for (V v : this) {
+        c.add(v);
+      }
       return c.toArray(a);
     }
   }
 
-  final class EntrySet extends AbstractSet<Entry<K,V>> {
+  private final class EntrySet extends AbstractSet<Entry<K, V>> {
+    @NotNull
     @Override
-    public Iterator<Entry<K,V>> iterator() {
+    public Iterator<Entry<K, V>> iterator() {
       return new EntryIterator();
     }
+
     @Override
     public boolean contains(Object o) {
-      if (!(o instanceof Entry))
+      if (!(o instanceof Entry)) {
         return false;
-      Entry<K,V> e = (Entry<K,V>)o;
+      }
+      Entry<K, V> e = (Entry<K, V>)o;
       V v = get(e.getKey());
       return v != null && v.equals(e.getValue());
     }
+
     @Override
     public boolean remove(Object o) {
-      if (!(o instanceof Entry))
+      if (!(o instanceof Entry)) {
         return false;
-      Entry<K,V> e = (Entry<K,V>)o;
+      }
+      Entry<K, V> e = (Entry<K, V>)o;
       return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
     }
+
     @Override
     public int size() {
       return ConcurrentHashMap.this.size();
     }
+
     @Override
     public void clear() {
       ConcurrentHashMap.this.clear();
     }
+
+    @NotNull
     @Override
     public Object[] toArray() {
       // Since we don't ordinarily have distinct Entry objects, we
       // must pack elements using exportable SimpleEntry
-      Collection<Entry<K,V>> c = new ArrayList<Entry<K,V>>(size());
-      for (Iterator<Entry<K,V>> i = iterator(); i.hasNext(); )
-        c.add(new SimpleEntry(i.next()));
+      Collection<Entry<K, V>> c = new ArrayList<Entry<K, V>>(size());
+      for (Entry<K, V> entry : this) {
+        c.add(new SimpleEntry(entry));
+      }
       return c.toArray();
     }
+
+    @NotNull
     @Override
-    public <T> T[] toArray(T[] a) {
-      Collection<Entry<K,V>> c = new ArrayList<Entry<K,V>>(size());
-      for (Iterator<Entry<K,V>> i = iterator(); i.hasNext(); )
-        c.add(new SimpleEntry(i.next()));
+    public <T> T[] toArray(@NotNull T[] a) {
+      Collection<Entry<K, V>> c = new ArrayList<Entry<K, V>>(size());
+      for (Entry<K, V> entry : this) {
+        c.add(new SimpleEntry(entry));
+      }
       return c.toArray(a);
     }
-
   }
 
   /**
    * This duplicates java.util.AbstractMap.SimpleEntry until this class
    * is made accessible.
    */
-  final class SimpleEntry implements Entry<K,V> {
-    K key;
-    V value;
+  final class SimpleEntry implements Entry<K, V> {
+    private final K key;
+    private V value;
 
     public SimpleEntry(K key, V value) {
-      this.key   = key;
+      this.key = key;
       this.value = value;
     }
 
-    public SimpleEntry(Entry<K,V> e) {
+    public SimpleEntry(Entry<K, V> e) {
       key = e.getKey();
       value = e.getValue();
     }
@@ -1321,16 +1423,16 @@
     }
 
     public boolean equals(Object o) {
-      if (!(o instanceof Entry))
+      if (!(o instanceof Entry)) {
         return false;
+      }
       Entry e = (Entry)o;
       K o2 = (K)e.getKey();
-      return (key == null ? o2 == null : myHashingStrategy.equals(key,o2)) && eq(value, e.getValue());
+      return (key == null ? o2 == null : myHashingStrategy.equals(key, o2)) && eq(value, e.getValue());
     }
 
     public int hashCode() {
-      return ((key   == null)   ? 0 :   key.hashCode()) ^
-             ((value == null)   ? 0 : value.hashCode());
+      return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
     }
 
     public String toString() {
@@ -1338,7 +1440,7 @@
     }
 
     boolean eq(Object o1, Object o2) {
-      return (o1 == null ? o2 == null : o1.equals(o2));
+      return o1 == null ? o2 == null : o1.equals(o2);
     }
   }
 
@@ -1348,27 +1450,28 @@
    * Save the state of the <tt>ConcurrentHashMap</tt>
    * instance to a stream (i.e.,
    * serialize it).
+   *
    * @param s the stream
-   * @serialData
-   * the key (Object) and value (Object)
+   * @serialData the key (Object) and value (Object)
    * for each key-value mapping, followed by a null pair.
    * The key-value mappings are emitted in no particular order.
    */
-  private void writeObject(java.io.ObjectOutputStream s) throws IOException {
+  private void writeObject(ObjectOutputStream s) throws IOException {
     s.defaultWriteObject();
 
-    for (int k = 0; k < segments.length; ++k) {
-      Segment seg = segments[k];
+    for (Segment seg : segments) {
       seg.lock();
       try {
         HashEntry[] tab = seg.table;
-        for (int i = 0; i < tab.length; ++i) {
-          for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i]; e != null; e = e.next) {
+        for (HashEntry tabEntry : tab) {
+          HashEntry<K, V> entry = (HashEntry<K, V>)tabEntry;
+          for (HashEntry<K, V> e = entry; e != null; e = e.next) {
             s.writeObject(e.key);
             s.writeObject(e.value);
           }
         }
-      } finally {
+      }
+      finally {
         seg.unlock();
       }
     }
@@ -1380,23 +1483,25 @@
    * Reconstitute the <tt>ConcurrentHashMap</tt>
    * instance from a stream (i.e.,
    * deserialize it).
+   *
    * @param s the stream
    */
-  private void readObject(java.io.ObjectInputStream s)
-    throws IOException, ClassNotFoundException  {
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException {
     s.defaultReadObject();
 
     // Initialize each segment to be minimally sized, and let grow.
-    for (int i = 0; i < segments.length; ++i) {
-      segments[i].setTable(new HashEntry[1]);
+    for (Segment segment : segments) {
+      segment.setTable(new HashEntry[1]);
     }
 
     // Read the keys and values, and put the mappings in the table
-    for (;;) {
-      K key = (K) s.readObject();
-      V value = (V) s.readObject();
-      if (key == null)
+    while (true) {
+      K key = (K)s.readObject();
+      V value = (V)s.readObject();
+      if (key == null) {
         break;
+      }
       put(key, value);
     }
   }
@@ -1405,9 +1510,9 @@
   public int computeHashCode(final K object) {
     int h = object.hashCode();
     h += ~(h << 9);
-    h ^=  (h >>> 14);
-    h +=  (h << 4);
-    h ^=  (h >>> 10);
+    h ^= h >>> 14;
+    h += h << 4;
+    h ^= h >>> 10;
     return h;
   }
 
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentHashSet.java b/platform/util/src/com/intellij/util/containers/ConcurrentHashSet.java
index 3db9eff..59a2240 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentHashSet.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentHashSet.java
@@ -17,6 +17,7 @@
 package com.intellij.util.containers;
 
 import gnu.trove.TObjectHashingStrategy;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
 import java.util.Iterator;
@@ -32,47 +33,60 @@
   public ConcurrentHashSet() {
     map = new ConcurrentHashMap<K, Boolean>();
   }
-  public ConcurrentHashSet(TObjectHashingStrategy<K> hashingStrategy) {
+  public ConcurrentHashSet(@NotNull TObjectHashingStrategy<K> hashingStrategy) {
     map = new ConcurrentHashMap<K, Boolean>(hashingStrategy);
   }
 
+  @Override
   public int size() {
     return map.size();
   }
 
+  @Override
   public boolean isEmpty() {
     return map.isEmpty();
   }
 
+  @Override
   public boolean contains(Object o) {
     return map.containsKey(o);
   }
 
+  @NotNull
+  @Override
   public Iterator<K> iterator() {
     return map.keySet().iterator();
   }
 
+  @NotNull
+  @Override
   public Object[] toArray() {
     return map.keySet().toArray();
   }
 
-  public <T> T[] toArray(T[] a) {
+  @NotNull
+  @Override
+  public <T> T[] toArray(@NotNull T[] a) {
     return map.keySet().toArray(a);
   }
 
+  @Override
   public boolean add(K o) {
     return map.putIfAbsent(o, Boolean.TRUE) == null;
   }
 
+  @Override
   public boolean remove(Object o) {
     return map.keySet().remove(o);
   }
 
-  public boolean containsAll(Collection<?> c) {
+  @Override
+  public boolean containsAll(@NotNull Collection<?> c) {
     return map.keySet().containsAll(c);
   }
 
-  public boolean addAll(Collection<? extends K> c) {
+  @Override
+  public boolean addAll(@NotNull Collection<? extends K> c) {
     boolean ret = false;
     for (K o : c) {
       ret |= add(o);
@@ -81,14 +95,17 @@
     return ret;
   }
 
-  public boolean retainAll(Collection<?> c) {
+  @Override
+  public boolean retainAll(@NotNull Collection<?> c) {
     return map.keySet().retainAll(c);
   }
 
-  public boolean removeAll(Collection<?> c) {
+  @Override
+  public boolean removeAll(@NotNull Collection<?> c) {
     return map.keySet().removeAll(c);
   }
 
+  @Override
   public void clear() {
     map.clear();
   }
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java
index d589a77..469342e 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java
@@ -22,6 +22,7 @@
  */
 package com.intellij.util.containers;
 
+import com.intellij.util.IncorrectOperationException;
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.TestOnly;
@@ -33,31 +34,33 @@
 /**
  * Fully copied from java.util.WeakHashMap except "get" method optimization.
  */
-abstract class ConcurrentRefHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V> {
-  public interface Key<K, V>{
+abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, TObjectHashingStrategy<K> {
+  protected final ReferenceQueue<K> myReferenceQueue = new ReferenceQueue<K>();
+  private final ConcurrentHashMap<Key<K, V>, V> myMap; // hashing strategy must be canonical, we compute corresponding hash codes using our own myHashingStrategy
+  @NotNull
+  private final TObjectHashingStrategy<K> myHashingStrategy;
+
+  public interface Key<K, V> {
     K get();
+
     V getValue();
+
     // MUST work even with gced references for the code in processQueue to work
     boolean equals(Object o);
+
     int hashCode();
   }
 
-  protected abstract Key<K, V> createKey(@NotNull K key, V value);
+  protected abstract Key<K, V> createKey(@NotNull K key, V value, @NotNull TObjectHashingStrategy<K> hashingStrategy);
 
 
-  private static class HardKey<K,V> implements Key<K,V> {
+  private static class HardKey<K, V> implements Key<K, V> {
     private K myKey;
     private int myHash;
-    private final V value;
 
-    public HardKey(K key, V value) {
-      this.value = value;
-      setKey(key);
-    }
-
-    private void setKey(K key) {
+    private void setKey(K key, final int hash) {
       myKey = key;
-      myHash = key == null ? 0 : key.hashCode();
+      myHash = hash;
     }
 
     @Override
@@ -67,7 +70,7 @@
 
     @Override
     public V getValue() {
-      return value;
+      return null;
     }
 
     public boolean equals(Object o) {
@@ -85,68 +88,70 @@
     }
   }
 
-  private final ConcurrentHashMap<Key<K, V>, V> myMap;
   private static final Key NULL_KEY = new Key() {
     @Override
-    public Object get() { return null; }
+    public Object get() {
+      return null;
+    }
+
     @Override
-    public Object getValue() { return null; }
+    public Object getValue() {
+      return null;
+    }
   };
 
-  protected final ReferenceQueue<K> myReferenceQueue = new ReferenceQueue<K>();
-
+  // returns true if some keys were processed
   boolean processQueue() {
-    Key<K,V> wk;
+    Key<K, V> wk;
     boolean processed = false;
-    while((wk = (Key)myReferenceQueue.poll()) != null){
+    while ((wk = (Key)myReferenceQueue.poll()) != null) {
       V value = wk.getValue();
-      myMap.remove(wk, wk.hashCode(), value);
+      myMap.remove(wk, value);
       processed = true;
     }
     return processed;
   }
 
-  public ConcurrentRefHashMap(int initialCapacity, float loadFactor) {
-    myMap = new ConcurrentHashMap<Key<K, V>, V>(initialCapacity, loadFactor, 4);
-  }
-
-  public ConcurrentRefHashMap(int initialCapacity) {
-    myMap = new ConcurrentHashMap<Key<K, V>, V>(initialCapacity);
-  }
-
-  public ConcurrentRefHashMap() {
-    myMap = new ConcurrentHashMap<Key<K, V>, V>();
-  }
-
-  public ConcurrentRefHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<K> hashingStrategy) {
-    myMap = new ConcurrentHashMap<Key<K, V>, V>(initialCapacity, loadFactor, concurrencyLevel, ConcurrentRefHashMap.<K,V>convertKToKeyK(hashingStrategy));
-  }
-
   public ConcurrentRefHashMap(Map<? extends K, ? extends V> t) {
-    this(Math.max(2 * t.size(), 11), 0.75f);
+    this(Math.max(2 * t.size(), 11), ConcurrentHashMap.DEFAULT_LOAD_FACTOR);
     putAll(t);
   }
 
+  public ConcurrentRefHashMap() {
+    this(ConcurrentHashMap.DEFAULT_INITIAL_CAPACITY);
+  }
+
+  public ConcurrentRefHashMap(int initialCapacity) {
+    this(initialCapacity, ConcurrentHashMap.DEFAULT_LOAD_FACTOR);
+  }
+
+  private static final TObjectHashingStrategy THIS = new TObjectHashingStrategy() {
+    @Override
+    public int computeHashCode(Object object) {
+      throw new IncorrectOperationException();
+    }
+
+    @Override
+    public boolean equals(Object o1, Object o2) {
+      throw new IncorrectOperationException();
+    }
+  };
+  public ConcurrentRefHashMap(int initialCapacity, float loadFactor) {
+    this(initialCapacity, loadFactor, 4, THIS);
+  }
+
   public ConcurrentRefHashMap(@NotNull final TObjectHashingStrategy<K> hashingStrategy) {
-    myMap = new ConcurrentHashMap<Key<K, V>, V>(ConcurrentRefHashMap.<K,V>convertKToKeyK(hashingStrategy));
+    this(ConcurrentHashMap.DEFAULT_INITIAL_CAPACITY, ConcurrentHashMap.DEFAULT_LOAD_FACTOR, 2, hashingStrategy);
   }
 
-  @NotNull
-  private static <K,V> TObjectHashingStrategy<Key<K, V>> convertKToKeyK(@NotNull final TObjectHashingStrategy<K> hashingStrategy) {
-    return new TObjectHashingStrategy<Key<K, V>>() {
-      @Override
-      public int computeHashCode(final Key<K, V> object) {
-        return hashingStrategy.computeHashCode(object.get());
-      }
-
-      @Override
-      public boolean equals(final Key<K, V> o1, final Key<K, V> o2) {
-        return hashingStrategy.equals(o1.get(), o2.get());
-      }
-    };
+  public ConcurrentRefHashMap(int initialCapacity,
+                              float loadFactor,
+                              int concurrencyLevel,
+                              @NotNull TObjectHashingStrategy<K> hashingStrategy) {
+    myHashingStrategy = hashingStrategy == THIS ? this : hashingStrategy;
+    myMap = new ConcurrentHashMap<Key<K, V>, V>(initialCapacity, loadFactor, concurrencyLevel, CANONICAL);
   }
 
-
   @Override
   public int size() {
     return entrySet().size();
@@ -160,40 +165,40 @@
   @Override
   public boolean containsKey(Object key) {
     // optimization:
-    if (key == null){
+    if (key == null) {
       return myMap.containsKey(NULL_KEY);
     }
-    HardKey<K,V> hardKey = createHardKey((K)key);
+    HardKey<K, V> hardKey = createHardKey((K)key);
     boolean result = myMap.containsKey(hardKey);
     releaseHardKey(hardKey);
     return result;
   }
 
-  private static final ThreadLocal<HardKey> HARD_KEY = new ThreadLocal<HardKey>(){
+  private static final ThreadLocal<HardKey> HARD_KEY = new ThreadLocal<HardKey>() {
     @Override
     protected HardKey initialValue() {
-      return new HardKey(null, null);
+      return new HardKey();
     }
   };
 
-  private static <K,V> HardKey<K,V> createHardKey(K key) {
+  private HardKey<K, V> createHardKey(K key) {
     HardKey hardKey = HARD_KEY.get();
-    hardKey.setKey(key);
+    hardKey.setKey(key, myHashingStrategy.computeHashCode(key));
     return hardKey;
   }
 
   private static void releaseHardKey(HardKey key) {
-    key.setKey(null);
+    key.setKey(null, 0);
   }
 
   @Override
   public V get(Object key) {
     //return myMap.get(WeakKey.create(key));
     // optimization:
-    if (key == null){
+    if (key == null) {
       return myMap.get(NULL_KEY);
     }
-    HardKey<K,V> hardKey = createHardKey((K)key);
+    HardKey<K, V> hardKey = createHardKey((K)key);
     V result = myMap.get(hardKey);
     releaseHardKey(hardKey);
     return result;
@@ -202,7 +207,7 @@
   @Override
   public V put(K key, V value) {
     processQueue();
-    Key<K, V> weakKey = key == null ? NULL_KEY : createKey(key, value);
+    Key<K, V> weakKey = key == null ? NULL_KEY : createKey(key, value, myHashingStrategy);
     return myMap.put(weakKey, value);
   }
 
@@ -211,10 +216,10 @@
     processQueue();
 
     // optimization:
-    if (key == null){
+    if (key == null) {
       return myMap.remove(NULL_KEY);
     }
-    HardKey hardKey = createHardKey(key);
+    HardKey hardKey = createHardKey((K)key);
     V result = myMap.remove(hardKey);
     releaseHardKey(hardKey);
     return result;
@@ -226,13 +231,13 @@
     myMap.clear();
   }
 
-  private static class Entry<K,V> implements Map.Entry<K,V> {
-    private final Map.Entry<?,V> ent;
-    private final K key;	/* Strong reference to key, so that the GC
+  private static class RefEntry<K, V> implements Map.Entry<K, V> {
+    private final Map.Entry<?, V> ent;
+    private final K key; /* Strong reference to key, so that the GC
                                  will leave it alone as long as this Entry
                                  exists */
 
-    Entry(Map.Entry<?,V> ent, K key) {
+    RefEntry(Map.Entry<?, V> ent, K key) {
       this.ent = ent;
       this.key = key;
     }
@@ -269,27 +274,27 @@
   }
 
   /* Internal class for entry sets */
-  private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
-    Set<Map.Entry<Key<K, V>,V>> hashEntrySet = myMap.entrySet();
+  private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+    Set<Map.Entry<Key<K, V>, V>> hashEntrySet = myMap.entrySet();
 
     @NotNull
     @Override
-    public Iterator<Map.Entry<K,V>> iterator() {
-      return new Iterator<Map.Entry<K,V>>() {
-        Iterator<Map.Entry<Key<K, V>,V>> hashIterator = hashEntrySet.iterator();
-        Entry<K,V> next = null;
+    public Iterator<Map.Entry<K, V>> iterator() {
+      return new Iterator<Map.Entry<K, V>>() {
+        Iterator<Map.Entry<Key<K, V>, V>> hashIterator = hashEntrySet.iterator();
+        RefEntry<K, V> next = null;
 
         @Override
         public boolean hasNext() {
-          while(hashIterator.hasNext()){
+          while (hashIterator.hasNext()) {
             Map.Entry<Key<K, V>, V> ent = hashIterator.next();
             Key<K, V> wk = ent.getKey();
             K k = null;
-            if (wk != null && (k = wk.get()) == null){
+            if (wk != null && (k = wk.get()) == null) {
               /* Weak key has been cleared by GC */
               continue;
             }
-            next = new Entry<K,V>(ent, k);
+            next = new RefEntry<K, V>(ent, k);
             return true;
           }
           return false;
@@ -300,7 +305,7 @@
           if (next == null && !hasNext()) {
             throw new NoSuchElementException();
           }
-          Entry<K,V> e = next;
+          RefEntry<K, V> e = next;
           next = null;
           return e;
         }
@@ -320,7 +325,7 @@
     @Override
     public int size() {
       int j = 0;
-      for(Iterator i = iterator(); i.hasNext(); i.next()) j++;
+      for (Iterator i = iterator(); i.hasNext(); i.next()) j++;
       return j;
     }
 
@@ -328,14 +333,14 @@
     public boolean remove(Object o) {
       processQueue();
       if (!(o instanceof Map.Entry)) return false;
-      Map.Entry e = (Map.Entry)o;
-      Object ev = e.getValue();
+      Map.Entry<K,V> e = (Map.Entry)o;
+      V ev = e.getValue();
 
-      HardKey key = createHardKey(o);
+      HardKey key = createHardKey(e.getKey());
 
       V hv = myMap.get(key);
       boolean toRemove = hv == null ? ev == null && myMap.containsKey(key) : hv.equals(ev);
-      if (toRemove){
+      if (toRemove) {
         myMap.remove(key);
       }
 
@@ -354,14 +359,13 @@
       }
       return h;
     }
-
   }
 
-  private Set<Map.Entry<K,V>> entrySet = null;
+  private Set<Map.Entry<K, V>> entrySet = null;
 
   @NotNull
   @Override
-  public Set<Map.Entry<K,V>> entrySet() {
+  public Set<Map.Entry<K, V>> entrySet() {
     if (entrySet == null) entrySet = new EntrySet();
     return entrySet;
   }
@@ -369,25 +373,41 @@
   @Override
   public V putIfAbsent(@NotNull final K key, final V value) {
     processQueue();
-    return myMap.putIfAbsent(createKey(key, value), value);
+    return myMap.putIfAbsent(createKey(key, value, myHashingStrategy), value);
   }
 
   @Override
   public boolean remove(@NotNull final Object key, final Object value) {
     processQueue();
-    return myMap.remove(createKey((K)key, (V)value), value);
+    return myMap.remove(createKey((K)key, (V)value, myHashingStrategy), value);
   }
 
   @Override
   public boolean replace(@NotNull final K key, @NotNull final V oldValue, @NotNull final V newValue) {
     processQueue();
-    return myMap.replace(createKey(key, oldValue), oldValue,newValue);
+    return myMap.replace(createKey(key, oldValue, myHashingStrategy), oldValue, newValue);
   }
 
   @Override
   public V replace(@NotNull final K key, @NotNull final V value) {
     processQueue();
-    return myMap.replace(createKey(key, value), value);
+    return myMap.replace(createKey(key, value, myHashingStrategy), value);
+  }
+
+  // MAKE SURE IT CONSISTENT WITH com.intellij.util.containers.ConcurrentHashMap
+  @Override
+  public int computeHashCode(final K object) {
+    int h = object.hashCode();
+    h += ~(h << 9);
+    h ^= (h >>> 14);
+    h += (h << 4);
+    h ^= (h >>> 10);
+    return h;
+  }
+
+  @Override
+  public boolean equals(final K o1, final K o2) {
+    return o1.equals(o2);
   }
 
   @TestOnly
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentRefValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentRefValueHashMap.java
index 61a3556..41f3d9c 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentRefValueHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentRefValueHashMap.java
@@ -19,14 +19,15 @@
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 import java.lang.ref.ReferenceQueue;
 import java.util.*;
 import java.util.HashSet;
 import java.util.concurrent.ConcurrentMap;
 
-abstract class ConcurrentRefValueHashMap<K,V> implements ConcurrentMap<K,V> {
-  private final ConcurrentHashMap<K,MyValueReference<K, V>> myMap;
+abstract class ConcurrentRefValueHashMap<K, V> implements ConcurrentMap<K, V> {
+  private final ConcurrentHashMap<K, MyValueReference<K, V>> myMap;
   protected final ReferenceQueue<V> myQueue = new ReferenceQueue<V>();
 
   public ConcurrentRefValueHashMap(@NotNull Map<K, V> map) {
@@ -37,25 +38,35 @@
   public ConcurrentRefValueHashMap() {
     myMap = new ConcurrentHashMap<K, MyValueReference<K, V>>();
   }
+
   public ConcurrentRefValueHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
     myMap = new ConcurrentHashMap<K, MyValueReference<K, V>>(initialCapacity, loadFactor, concurrencyLevel);
   }
-  public ConcurrentRefValueHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<K> hashingStrategy) {
+
+  public ConcurrentRefValueHashMap(int initialCapacity,
+                                   float loadFactor,
+                                   int concurrencyLevel,
+                                   @NotNull TObjectHashingStrategy<K> hashingStrategy) {
     myMap = new ConcurrentHashMap<K, MyValueReference<K, V>>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
   }
 
   protected interface MyValueReference<K, V> {
     @NotNull
     K getKey();
+
     V get();
   }
 
-  private void processQueue() {
-    while(true){
+  boolean processQueue() {
+    boolean processed = false;
+
+    while (true) {
       MyValueReference<K, V> ref = (MyValueReference<K, V>)myQueue.poll();
       if (ref == null) break;
       myMap.remove(ref.getKey(), ref);
+      processed = true;
     }
+    return processed;
   }
 
   @Override
@@ -210,9 +221,14 @@
     @NonNls String s = "map size:" + size() + " [";
     for (K k : myMap.keySet()) {
       Object v = get(k);
-      s += "'"+k + "': '" +v+"', ";
+      s += "'" + k + "': '" + v + "', ";
     }
     s += "] ";
     return s;
   }
+
+  @TestOnly
+  int underlyingMapSize() {
+    return myMap.size();
+  }
 }
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java
index cd028d2..0bd2122 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java
@@ -29,15 +29,15 @@
 import java.lang.ref.SoftReference;
 import java.util.Map;
 
-public final class ConcurrentSoftHashMap<K,V> extends ConcurrentRefHashMap<K,V> {
+public final class ConcurrentSoftHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
   private static class SoftKey<K, V> extends SoftReference<K> implements ConcurrentRefHashMap.Key<K, V> {
-    private final int myHash;	/* Hashcode of key, stored here since the key may be tossed by the GC */
+    private final int myHash; // Hashcode of key, stored here since the key may be tossed by the GC
     private final V value;
 
-    private SoftKey(@NotNull K k, V v, ReferenceQueue<K> q) {
+    private SoftKey(@NotNull K k, final int hash, V v, @NotNull ReferenceQueue<K> q) {
       super(k, q);
       value = v;
-      myHash = k.hashCode();
+      myHash = hash;
     }
 
     @Override
@@ -47,11 +47,11 @@
 
     public boolean equals(Object o) {
       if (this == o) return true;
-      if (!(o instanceof ConcurrentRefHashMap.Key)) return false;
+      if (!(o instanceof Key)) return false;
       Object t = get();
-      Object u = ((ConcurrentRefHashMap.Key)o).get();
-      if (t == null || u == null) return false;
+      Object u = ((Key)o).get();
       if (t == u) return true;
+      if (t == null || u == null) return false;
       return t.equals(u);
     }
 
@@ -61,8 +61,8 @@
   }
 
   @Override
-  protected ConcurrentRefHashMap.Key<K, V> createKey(@NotNull K key, V value) {
-    return new SoftKey<K, V>(key, value, myReferenceQueue);
+  protected ConcurrentRefHashMap.Key<K, V> createKey(@NotNull K key, V value, @NotNull TObjectHashingStrategy<K> hashingStrategy) {
+    return new SoftKey<K, V>(key, hashingStrategy.computeHashCode(key), value, myReferenceQueue);
   }
 
   public ConcurrentSoftHashMap(int initialCapacity, float loadFactor) {
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java
index 93cc863..44c5408 100644
--- a/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java
@@ -32,15 +32,15 @@
 /**
  * Fully copied from java.util.WeakHashMap except "get" method optimization.
  */
-public final class ConcurrentWeakHashMap<K,V> extends ConcurrentRefHashMap<K,V> {
+public final class ConcurrentWeakHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
   private static class WeakKey<K, V> extends WeakReference<K> implements Key<K, V> {
     private final int myHash; /* Hashcode of key, stored here since the key may be tossed by the GC */
     private final V value;
 
-    private WeakKey(@NotNull K k, V v, ReferenceQueue<K> q) {
+    private WeakKey(@NotNull K k, final int hash, V v, ReferenceQueue<K> q) {
       super(k, q);
       value = v;
-      myHash = k.hashCode();
+      myHash = hash;
     }
 
     @Override
@@ -64,8 +64,8 @@
   }
 
   @Override
-  protected Key<K, V> createKey(@NotNull K key, V value) {
-    return new WeakKey<K, V>(key, value, myReferenceQueue);
+  protected Key<K, V> createKey(@NotNull K key, V value, @NotNull TObjectHashingStrategy<K> hashingStrategy) {
+    return new WeakKey<K, V>(key, hashingStrategy.computeHashCode(key), value, myReferenceQueue);
   }
 
   public ConcurrentWeakHashMap(int initialCapacity, float loadFactor) {
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index bf98ac2..87460f5 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
@@ -54,6 +54,11 @@
   }
 
   @NotNull
+  public static <K, V> Map<K, V> newHashMap(Pair<K, V> first, Pair<K, V>... entries) {
+    return ContainerUtilRt.newHashMap(first, entries);
+  }
+
+  @NotNull
   public static <K, V> Map<K, V> newHashMap(@NotNull List<K> keys, @NotNull List<V> values) {
     return ContainerUtilRt.newHashMap(keys, values);
   }
@@ -1029,6 +1034,15 @@
   }
 
   /**
+   * @param appendTail specify whether additional values should be appended in front or after the list
+   * @return read-only list consisting of the elements from specified list with some additional values
+   */
+  @NotNull
+  public static <T> List<T> concat(boolean appendTail, @NotNull List<? extends T> list, T... values) {
+    return appendTail ? concat(list, list(values)) : concat(list(values), list);
+  }
+
+  /**
    * @return read-only list consisting of the two lists added together
    */
   @NotNull
diff --git a/platform/util/src/com/intellij/util/io/BooleanDataDescriptor.java b/platform/util/src/com/intellij/util/io/BooleanDataDescriptor.java
index 1b5531b..bc5e668 100644
--- a/platform/util/src/com/intellij/util/io/BooleanDataDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/BooleanDataDescriptor.java
@@ -31,4 +31,8 @@
   public int toInt(Boolean aBoolean) {
     return aBoolean == Boolean.TRUE ? 1 : 0;
   }
+
+  protected boolean isCompactFormat() {
+    return true;
+  }
 }
diff --git a/platform/util/src/com/intellij/util/io/DataOutputStream.java b/platform/util/src/com/intellij/util/io/DataOutputStream.java
index 97ee34b..67097e1 100644
--- a/platform/util/src/com/intellij/util/io/DataOutputStream.java
+++ b/platform/util/src/com/intellij/util/io/DataOutputStream.java
@@ -34,4 +34,14 @@
     out.write(b, off, len);
     written += len;
   }
+
+  public int getWrittenBytesCount() {
+    return written;
+  }
+
+  public int resetWrittenBytesCount() {
+    int result = written;
+    written = 0;
+    return result;
+  }
 }
diff --git a/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java b/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java
index 7dfe1f4..715c496 100644
--- a/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java
@@ -24,6 +24,12 @@
 import java.io.IOException;
 
 public abstract class InlineKeyDescriptor<T> implements KeyDescriptor<T> {
+  private final boolean myCompactFormat = isCompactFormat();
+
+  protected boolean isCompactFormat() {
+    return false;
+  }
+
   public final int getHashCode(T value) {
     return toInt(value);
   }
@@ -33,11 +39,16 @@
   }
 
   public final void save(DataOutput out, T value) throws IOException {
-    out.writeInt(toInt(value));
+    int v = toInt(value);
+    if (myCompactFormat) DataInputOutputUtil.writeINT(out, v);
+    else out.writeInt(v);
   }
 
   public final T read(DataInput in) throws IOException {
-    return fromInt(in.readInt());
+    int n;
+    if (myCompactFormat) n = DataInputOutputUtil.readINT(in);
+    else n = in.readInt();
+    return fromInt(n);
   }
 
   public abstract T fromInt(int n);
diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java
index 751f55e..adbd305 100644
--- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java
+++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java
@@ -60,7 +60,7 @@
   private boolean myExternalKeysNoMapping;
 
   private static final int DIRTY_MAGIC = 0xbabe1977;
-  private static final int VERSION = 6 + IntToIntBtree.version();
+  private static final int VERSION = 7 + IntToIntBtree.version();
   private static final int CORRECTLY_CLOSED_MAGIC = 0xebabafc + VERSION + PAGE_SIZE;
   @NotNull private static final Version ourVersion = new Version(CORRECTLY_CLOSED_MAGIC, DIRTY_MAGIC);
   private static final int KEY_SHIFT = 1;
diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
index 363a75b..543483c 100644
--- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
+++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
@@ -39,7 +39,7 @@
  * @author jeka
  */
 @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
-abstract class PersistentEnumeratorBase<Data> implements Forceable, Closeable {
+abstract public class PersistentEnumeratorBase<Data> implements Forceable, Closeable {
   protected static final Logger LOG = Logger.getInstance("#com.intellij.util.io.PersistentEnumerator");
   protected static final int NULL_ID = 0;
 
@@ -427,10 +427,14 @@
     comparer.close();
 
     if (sameValue[0]) return true;
-
+    if (serializationEquivalenceIsExhausting()) return false;
     return myDataDescriptor.isEqual(valueOf(idx), value);
   }
 
+  protected boolean serializationEquivalenceIsExhausting() {
+    return false;
+  }
+
   protected int writeData(final Data value, int hashCode) {
     try {
       markDirty(true);
@@ -498,7 +502,7 @@
     return pos;
   }
 
-  protected boolean iterateData(final Processor<Data> processor) throws IOException {
+  public boolean iterateData(final Processor<Data> processor) throws IOException {
     lockStorage();
     try {
       if (myKeyStorage == null) {
@@ -509,7 +513,12 @@
       myKeyStorage.force();
 
       DataInputStream keysStream = new DataInputStream(new BufferedInputStream(new LimitedInputStream(new FileInputStream(keystreamFile()),
-                                                                                                      myKeyStoreFileLength)));
+                                                                                                      myKeyStoreFileLength) {
+        @Override
+        public int available() throws IOException {
+          return remainingLimit();
+        }
+      }, 32768));
       try {
         try {
           while (true) {
diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java
index 6725c21..8c50529 100644
--- a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java
+++ b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java
@@ -88,16 +88,6 @@
     }
   }
 
-  private long smallWrites;
-  private int smallWritesCount;
-  private long largeWrites;
-  private int largeWritesCount;
-  private int requests;
-
-  private static final int POSITIVE_VALUE_SHIFT = 1;
-  private static final int BYTE_LENGTH_INT_ADDRESS = 1 + 4;
-  private static final int INT_LENGTH_LONG_ADDRESS = 4 + 8;
-
   public long appendBytes(ByteSequence data, long prevChunkAddress) throws IOException {
     return appendBytes(data.getBytes(), data.getOffset(), data.getLength(), prevChunkAddress);
   }
@@ -106,40 +96,28 @@
     assert !myCompactionMode;
     long result = mySize; // volatile read
     final CacheValue<DataOutputStream> appender = ourAppendersCache.get(myPath);
-    int serviceFieldsSizeIncrease;
 
+    DataOutputStream dataOutputStream;
     try {
-      DataOutputStream dataOutputStream = appender.get();
-      ++requests;
-      
-      if (dataLength + POSITIVE_VALUE_SHIFT < 0x80 && prevChunkAddress < Integer.MAX_VALUE) {
-        ++smallWritesCount;
-        smallWrites += dataLength;
-        dataOutputStream.write(-dataLength - POSITIVE_VALUE_SHIFT);
-        dataOutputStream.writeInt((int)prevChunkAddress);
-        serviceFieldsSizeIncrease = BYTE_LENGTH_INT_ADDRESS;
-      } else {
-        ++largeWritesCount;
-        largeWrites += dataLength;
-        dataOutputStream.writeInt(dataLength);
-        dataOutputStream.writeLong(prevChunkAddress);
-        serviceFieldsSizeIncrease = INT_LENGTH_LONG_ADDRESS;
-      }
+      dataOutputStream = appender.get();
+      dataOutputStream.resetWrittenBytesCount();
+
+      DataInputOutputUtil.writeINT(dataOutputStream, dataLength);
+      writePrevChunkAddress(prevChunkAddress, result, dataOutputStream);
+
       dataOutputStream.write(data, offset, dataLength);
-      if (IOStatistics.DEBUG && (requests % IOStatistics.KEYS_FACTOR_MASK) == 0) {
-        IOStatistics.dump("Small writes:"+smallWritesCount +", bytes:"+smallWrites + ", largeWrites:"+largeWritesCount
-                          + ", bytes:"+largeWrites+", total:"+requests + "@"+myFile.getPath());
-      }
+      mySize += dataOutputStream.resetWrittenBytesCount();  // volatile write
     }
     finally {
       appender.release();
     }
-    mySize += dataLength + serviceFieldsSizeIncrease;  // volatile write
 
     return result;
   }
 
   private final byte[] myBuffer = new byte[1024];
+  private final UnsyncByteArrayInputStream myBufferStreamWrapper = new UnsyncByteArrayInputStream(myBuffer);
+  private final DataInputStream myBufferDataStreamWrapper = new DataInputStream(myBufferStreamWrapper);
 
   public int compactValues(List<PersistentHashMap.CompactionRecordInfo> infos, PersistentHashMapValueStorage storage) throws IOException {
     PriorityQueue<PersistentHashMap.CompactionRecordInfo> records = new PriorityQueue<PersistentHashMap.CompactionRecordInfo>(
@@ -155,7 +133,7 @@
     records.addAll(infos);
 
     final int fileBufferLength = 256 * 1024;
-    final int maxRecordHeader = Math.max(BYTE_LENGTH_INT_ADDRESS, INT_LENGTH_LONG_ADDRESS);
+    final int maxRecordHeader = 5 /* max length - variable int */ + 10 /* max long offset*/;
     final byte[] buffer = new byte[fileBufferLength + maxRecordHeader];
     byte[] recordBuffer = {};
 
@@ -184,7 +162,8 @@
           // record start is inside our buffer
 
           final int recordStartInBuffer = (int) (info.valueAddress - readStartOffset);
-          final int sizePart = buffer[recordStartInBuffer];
+          myBufferStreamWrapper.init(buffer, recordStartInBuffer, buffer.length);
+
           final long prevChunkAddress;
           int chunkSize;
           final int dataOffset;
@@ -201,15 +180,10 @@
             }
           }
 
-          if (sizePart < 0) {
-            chunkSize = -sizePart - POSITIVE_VALUE_SHIFT;
-            prevChunkAddress = Bits.getInt(buffer, recordStartInBuffer + 1);
-            dataOffset = BYTE_LENGTH_INT_ADDRESS;
-          } else {
-            chunkSize = Bits.getInt(buffer, recordStartInBuffer);
-            prevChunkAddress = Bits.getLong(buffer, recordStartInBuffer + 4);
-            dataOffset = INT_LENGTH_LONG_ADDRESS;
-          }
+          int available = myBufferStreamWrapper.available();
+          chunkSize = DataInputOutputUtil.readINT(myBufferDataStreamWrapper);
+          prevChunkAddress = readPrevChunkAddress(info.valueAddress + (available - myBufferStreamWrapper.available()));
+          dataOffset = available - myBufferStreamWrapper.available();
 
           byte[] b;
           if (info.value != null) {
@@ -325,32 +299,21 @@
         if (chunk < 0 || chunk > mySize) throw new PersistentEnumeratorBase.CorruptedException(myFile);
         int len = (int)Math.min(myBuffer.length, mySize - chunk);
         reader.get(chunk, myBuffer, 0, len);
+        myBufferStreamWrapper.init(myBuffer, 0, len);
 
-        final int sizePart = myBuffer[0];
-        final long prevChunkAddress;
-        final int chunkSize;
+        final int chunkSize = DataInputOutputUtil.readINT(myBufferDataStreamWrapper);
+        final long prevChunkAddress = readPrevChunkAddress(chunk);
+        final int headerOffset = len - myBufferStreamWrapper.available();
 
-        if (sizePart < 0) {
-          chunkSize = -sizePart - POSITIVE_VALUE_SHIFT;
-          prevChunkAddress = Bits.getInt(myBuffer, 1);
-          byte[] b = new byte[(result != null ? result.length:0) + chunkSize];
-          if (result != null) System.arraycopy(result, 0, b, b.length - result.length, result.length);
-          result = b;
+        byte[] b = new byte[(result != null ? result.length:0) + chunkSize];
+        if (result != null) System.arraycopy(result, 0, b, b.length - result.length, result.length);
+        result = b;
 
-          checkPreconditions(result, chunkSize, 0);
-          System.arraycopy(myBuffer, BYTE_LENGTH_INT_ADDRESS, result, 0, chunkSize);
+        checkPreconditions(result, chunkSize, 0);
+        if (chunkSize < myBuffer.length - headerOffset) {
+          System.arraycopy(myBuffer, headerOffset, result, 0, chunkSize);
         } else {
-          chunkSize = Bits.getInt(myBuffer, 0);
-          prevChunkAddress = Bits.getLong(myBuffer, 4);
-          byte[] b = new byte[(result != null ? result.length:0) + chunkSize];
-          if (result != null) System.arraycopy(result, 0, b, b.length - result.length, result.length);
-          result = b;
-
-          if (chunkSize < myBuffer.length - INT_LENGTH_LONG_ADDRESS) {
-            System.arraycopy(myBuffer, INT_LENGTH_LONG_ADDRESS, result, 0, chunkSize);
-          } else {
-            reader.get(chunk + INT_LENGTH_LONG_ADDRESS, result, 0, chunkSize);
-          }
+          reader.get(chunk + headerOffset, result, 0, chunkSize);
         }
 
         if (prevChunkAddress >= chunk) throw new PersistentEnumeratorBase.CorruptedException(myFile);
@@ -379,6 +342,26 @@
     return new ReadResult(tailChunkAddress, result);
   }
 
+  private long readPrevChunkAddress(long chunk) throws IOException {
+    final int prevOffsetDiff = DataInputOutputUtil.readINT(myBufferDataStreamWrapper);
+    if (prevOffsetDiff < 0) {
+      return chunk - (-prevOffsetDiff | ((long)DataInputOutputUtil.readINT(myBufferDataStreamWrapper) << 32));
+    }
+    assert prevOffsetDiff < chunk;
+    return prevOffsetDiff != 0 ? chunk - prevOffsetDiff : 0;
+  }
+
+  private static void writePrevChunkAddress(long prevChunkAddress, long currentChunkAddress, DataOutputStream dataOutputStream) throws IOException {
+    long diff = currentChunkAddress - prevChunkAddress;
+
+    if (diff < Integer.MAX_VALUE || prevChunkAddress == 0)
+      DataInputOutputUtil.writeINT(dataOutputStream, prevChunkAddress == 0 ? 0 : (int)diff);
+    else {
+      DataInputOutputUtil.writeINT(dataOutputStream, -(int)diff);
+      DataInputOutputUtil.writeINT(dataOutputStream, (int)(diff >>> 32));
+    }
+  }
+
   public long getSize() {
     return mySize;
   }
diff --git a/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java b/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java
index 830a7e0..d35da96 100644
--- a/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java
+++ b/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java
@@ -22,7 +22,7 @@
 public class UnsyncByteArrayInputStream extends InputStream {
   protected byte[] myBuffer;
   private int myPosition;
-  private final int myCount;
+  private int myCount;
   private int myMarkedPosition;
 
   public UnsyncByteArrayInputStream(@NotNull byte[] buf) {
@@ -30,6 +30,10 @@
   }
 
   public UnsyncByteArrayInputStream(byte[] buf, int offset, int length) {
+    init(buf, offset, length);
+  }
+
+  public void init(byte[] buf, int offset, int length) {
     myBuffer = buf;
     myPosition = offset;
     myCount = length;
diff --git a/platform/util/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java b/platform/util/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java
new file mode 100644
index 0000000..b89ef90
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.util.containers;
+
+import gnu.trove.TObjectHashingStrategy;
+import junit.framework.TestCase;
+
+import java.lang.ref.SoftReference;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ConcurrentMapsTest extends TestCase {
+  public void testKeysRemovedWhenIdentityStrategyIsUsed() {
+    ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>(TObjectHashingStrategy.IDENTITY);
+    map.put(new Object(), new Object());
+
+    do {
+      System.gc();
+    }
+    while (!map.processQueue());
+    map.put(this, this);
+    assertEquals(1, map.underlyingMapSize());
+  }
+
+  public void testRemoveFromSoftEntrySet() {
+    ConcurrentSoftHashMap<Object, Object> map = new ConcurrentSoftHashMap<Object, Object>();
+    map.put(this, this);
+    Set<Map.Entry<Object,Object>> entries = map.entrySet();
+    assertEquals(1, entries.size());
+    Map.Entry<Object, Object> entry = entries.iterator().next();
+    entries.remove(entry);
+
+    assertTrue(map.isEmpty());
+  }
+
+  public void testRemoveFromWeakEntrySet() {
+    ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>();
+    map.put(this, this);
+    Set<Map.Entry<Object,Object>> entries = map.entrySet();
+    assertEquals(1, entries.size());
+    Map.Entry<Object, Object> entry = entries.iterator().next();
+    entries.remove(entry);
+
+    assertTrue(map.isEmpty());
+  }
+
+  public void testTossedWeakKeysAreRemoved() {
+    ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>();
+    map.put(new Object(), new Object());
+
+    do {
+      System.gc();
+    }
+    while (!map.processQueue());
+    assertEquals(0, map.underlyingMapSize());
+    map.put(this, this);
+    assertEquals(1, map.underlyingMapSize());
+  }
+
+  public static void tryGcSoftlyReachableObjects() {
+    SoftReference reference = new SoftReference(new Object());
+    List<Object> list = ContainerUtil.newArrayList();
+    while (reference.get() != null) {
+      list.add(new SoftReference<byte[]>(new byte[(int)Runtime.getRuntime().freeMemory() / 2]));
+    }
+  }
+
+  public void testTossedSoftKeysAreRemoved() {
+    ConcurrentSoftHashMap<Object, Object> map = new ConcurrentSoftHashMap<Object, Object>();
+    map.put(new Object(), new Object());
+
+    tryGcSoftlyReachableObjects();
+    do {
+      System.gc();
+    }
+    while (!map.processQueue());
+    assertEquals(0, map.underlyingMapSize());
+    map.put(this, this);
+    assertEquals(1, map.underlyingMapSize());
+  }
+
+  public void testTossedWeakValueIsRemoved() {
+    ConcurrentWeakValueHashMap<Object, Object> map = new ConcurrentWeakValueHashMap<Object, Object>();
+    map.put(new Object(), new Object());
+
+    do {
+      System.gc();
+    }
+    while (!map.processQueue());
+    assertEquals(0, map.underlyingMapSize());
+    map.put(this, this);
+    assertEquals(1, map.underlyingMapSize());
+  }
+  public void testTossedSoftValueIsRemoved() {
+    ConcurrentSoftValueHashMap<Object, Object> map = new ConcurrentSoftValueHashMap<Object, Object>();
+    map.put(new Object(), new Object());
+
+    tryGcSoftlyReachableObjects();
+    do {
+      System.gc();
+    }
+    while (!map.processQueue());
+    assertEquals(0, map.underlyingMapSize());
+    map.put(this, this);
+    assertEquals(1, map.underlyingMapSize());
+  }
+}
diff --git a/platform/util/testSrc/com/intellij/util/containers/ConcurrentWeakHashMapTest.java b/platform/util/testSrc/com/intellij/util/containers/ConcurrentWeakHashMapTest.java
deleted file mode 100644
index c76d8ec6..0000000
--- a/platform/util/testSrc/com/intellij/util/containers/ConcurrentWeakHashMapTest.java
+++ /dev/null
@@ -1,33 +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.util.containers;
-
-import gnu.trove.TObjectHashingStrategy;
-import junit.framework.TestCase;
-
-public class ConcurrentWeakHashMapTest extends TestCase {
-  public void testKeysRemovedWhenIdentityStrategyIsUsed() {
-    ConcurrentWeakHashMap<Object, Object> map = new ConcurrentWeakHashMap<Object, Object>(TObjectHashingStrategy.IDENTITY);
-    map.put(new Object(), new Object());
-
-    do {
-      System.gc();
-    }
-    while (!map.processQueue());
-    map.put(this, this);
-    assertEquals(1, map.underlyingMapSize());
-  }
-}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
index a9ef16c..df28526 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
@@ -340,7 +340,7 @@
     private Range getLastRangeBeforeLine(int line) {
       Range result = null;
       for (Range range : myRanges) {
-        if (range.isMoreThen(line)) return result;
+        if (range.isAfter(line)) return result;
         result = range;
       }
       return result;
@@ -439,7 +439,7 @@
           if (prev.getHighlighter() != null) {
             prev.getHighlighter().dispose();
           }
-          prev = prev.mergeWith(range, LineStatusTracker.this);
+          prev = prev.mergeWith(range);
         }
         else {
           result.add(prev);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
index 219e330..6900d46 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
@@ -19,12 +19,14 @@
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.util.diff.Diff;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * author: lesya
  */
 public class Range {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.ex.Range");
+  private static final Logger LOG = Logger.getInstance(Range.class);
   public static final byte MODIFIED = 1;
   public static final byte INSERTED = 2;
   public static final byte DELETED = 3;
@@ -34,10 +36,9 @@
   private final int myUpToDateOffset1;
   private final int myUpToDateOffset2;
   private final byte myType;
-  private RangeHighlighter myRangeHighlighter;
+  @Nullable private RangeHighlighter myRangeHighlighter;
 
-  public static Range createOn(Diff.Change change, int shift, int upToDateShift) {
-
+  public static Range createOn(@NotNull Diff.Change change, int shift, int upToDateShift) {
     byte type = getChangeTypeFrom(change);
 
     int offset1 = shift + change.line1;
@@ -49,7 +50,7 @@
     return new Range(offset1, offset2, uOffset1, uOffset2, type);
   }
 
-  private static byte getChangeTypeFrom(Diff.Change change) {
+  private static byte getChangeTypeFrom(@NotNull Diff.Change change) {
     if ((change.deleted > 0) && (change.inserted > 0)) return MODIFIED;
     if ((change.deleted > 0)) return DELETED;
     if ((change.inserted > 0)) return INSERTED;
@@ -73,8 +74,7 @@
     if (!(object instanceof Range)) return false;
     Range other = (Range)object;
     return
-      (myOffset1 == other.myOffset1)
-      && (myUpToDateOffset1 == other.myUpToDateOffset1)
+      (myUpToDateOffset1 == other.myUpToDateOffset1)
       && (myUpToDateOffset2 == other.myUpToDateOffset2)
       && (myOffset1 == other.myOffset1)
       && (myOffset2 == other.myOffset2)
@@ -82,20 +82,11 @@
   }
 
   public String toString() {
-    StringBuffer result = new StringBuffer();
-    result.append(String.valueOf(myOffset1));
-    result.append(", ");
-    result.append(String.valueOf(myOffset2));
-    result.append(", ");
-    result.append(String.valueOf(myUpToDateOffset1));
-    result.append(", ");
-    result.append(String.valueOf(myUpToDateOffset2));
-    result.append(", ");
-    result.append(getTypeName());
-    return result.toString();
+    return String.format("%s, %s, %s, %s, %s", myOffset1, myOffset2, myUpToDateOffset1, myUpToDateOffset2, getTypeName());
   }
 
-  @NonNls private String getTypeName() {
+  @NonNls
+  private String getTypeName() {
     switch (myType) {
       case MODIFIED:
         return "MODIFIED";
@@ -115,24 +106,11 @@
     return myUpToDateOffset2 - myUpToDateOffset1;
   }
 
-  public boolean isInRange(int from, int to) {
-    return (myOffset2 >= from && myOffset1 <= from) ||
-           ((myOffset1 <= to) && (myOffset2 >= to));
-  }
-
   public void shift(int shift) {
     myOffset1 += shift;
     myOffset2 += shift;
   }
 
-  public boolean isAfter(int to) {
-    return myOffset1 > to;
-  }
-
-  public int getCurrentLength() {
-    return myOffset2 - myOffset1;
-  }
-
   public int getOffset1() {
     return myOffset1;
   }
@@ -149,17 +127,18 @@
     return myUpToDateOffset2;
   }
 
-  public boolean canBeMergedWith(Range range) {
+  public boolean canBeMergedWith(@NotNull Range range) {
     return myOffset2 == range.myOffset1;
   }
 
-  public Range mergeWith(Range range, LineStatusTracker tracker) {
+  @NotNull
+  public Range mergeWith(@NotNull Range range) {
     return new Range(myOffset1, range.myOffset2, myUpToDateOffset1, range.myUpToDateOffset2, mergedStatusWith(range));
   }
 
-  private byte mergedStatusWith(Range range) {
+  private byte mergedStatusWith(@NotNull Range range) {
     byte type = myType;
-    if (myType != range.myType) type = Range.MODIFIED;
+    if (myType != range.myType) type = MODIFIED;
     return type;
   }
 
@@ -171,6 +150,7 @@
     myRangeHighlighter = highlighter;
   }
 
+  @Nullable
   public RangeHighlighter getHighlighter() {
     return myRangeHighlighter;
   }
@@ -185,7 +165,7 @@
     return myOffset1 <= line && myOffset2 >= line;
   }
 
-  public boolean isMoreThen(int line) {
+  public boolean isAfter(int line) {
     if (myType == DELETED)
       return (getOffset1() - 1) > line;
     else
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
index 0dba442..49e2e4a 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
@@ -64,7 +64,7 @@
     //Perhaps we always should have a root node 'Debugger' with separate nodes for language-specific settings under it.
     //However for AppCode there is only one language which is clearly associated with the product
     //This code should removed when we extract the common debugger settings to the root node.
-    if (PlatformUtils.isAppCode() && rootConfigurable == null && configurables.size() == 1) {
+    if (PlatformUtils.isCidr() && rootConfigurable == null && configurables.size() == 1) {
       rootConfigurable = configurables.get(0);
       configurables = Collections.emptyList();
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java
index 4f25ccc92..57f9240 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.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 com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.AppUIUtil;
 import com.intellij.xdebugger.XSourcePosition;
@@ -44,6 +45,7 @@
   private OpenFileDescriptor myOpenFileDescriptor;
   private boolean myUseSelection;
   private GutterIconRenderer myGutterIconRenderer;
+  private static final Key<Boolean> EXECUTION_POINT_HIGHLIGHTER_KEY = Key.create("EXECUTION_POINT_HIGHLIGHTER_KEY");
 
   public ExecutionPointHighlighter(final Project project) {
     myProject = project;
@@ -151,6 +153,7 @@
     EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
     myRangeHighlighter = myEditor.getMarkupModel().addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER,
                                                                       scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES));
+    myRangeHighlighter.putUserData(EXECUTION_POINT_HIGHLIGHTER_KEY, true);
     myRangeHighlighter.setGutterIconRenderer(myGutterIconRenderer);
   }
 }
diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
index a25c49d..a5fc96c 100644
--- a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
+++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.java
@@ -102,9 +102,18 @@
     if (!StringUtil.isEmpty(byteCode)) {
       component.setText(byteCode, element);
     } else {
-      PsiClass containingClass = getContainingClass(element);
-      PsiFile containingFile = element.getContainingFile();
-      component.setText("No bytecode found for " + SymbolPresentationUtil.getSymbolPresentableText(containingClass != null ? containingClass : containingFile));
+      PsiElement presentableElement = getContainingClass(element);
+      if (presentableElement == null) {
+        presentableElement = element.getContainingFile();
+        if (presentableElement == null && element instanceof PsiNamedElement) {
+          presentableElement = element;
+        }
+        if (presentableElement == null) {
+          component.setText("No bytecode found");
+          return;
+        }
+      }
+      component.setText("No bytecode found for " + SymbolPresentationUtil.getSymbolPresentableText(presentableElement));
     }
     content.setDisplayName(getTitle(element));
   }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index b3c238e..44b5be3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -3,6 +3,9 @@
   <extensions xmlns="com.intellij">
 
     <!--group.names.abstraction.issues-->
+    <localInspection language="JAVA" shortName="BooleanParameter" bundle="com.siyeh.InspectionGadgetsBundle" key="boolean.parameter.display.name"
+                     groupBundle="messages.InspectionsBundle" groupKey="group.names.abstraction.issues" enabledByDefault="false"
+                     level="WARNING" implementationClass="com.siyeh.ig.abstraction.BooleanParameterInspection"/>
     <localInspection language="JAVA" shortName="CastToConcreteClass" bundle="com.siyeh.InspectionGadgetsBundle" key="cast.to.concrete.class.display.name"
                      groupBundle="messages.InspectionsBundle" groupKey="group.names.abstraction.issues" enabledByDefault="false"
                      level="WARNING" implementationClass="com.siyeh.ig.abstraction.CastToConcreteClassInspection"/>
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index 7da4e06..694189a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -400,15 +400,12 @@
 anonymous.class.field.hides.containing.method.variable.problem.descriptor=Anonymous class field <code>#ref</code> hides variable in containing method #loc
 anonymous.class.variable.hides.containing.method.variable.problem.descriptor=Anonymous class local variable <code>#ref</code> hides variable in containing method #loc
 channel.opened.not.closed.display.name=Channel opened but not safely closed
-channel.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc
 drivermanager.call.display.name=Use of DriverManager to get JDBC connection
 drivermanager.call.problem.descriptor=Call to <code>DriverManager.#ref()</code> #loc
 hibernate.resource.opened.not.closed.display.name=Hibernate resource opened but not safely closed
-hibernate.resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc
 i.o.resource.opened.not.closed.display.name=I/O resource opened but not safely closed
 resource.opened.not.closed.problem.descriptor=''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc
 jdbc.resource.opened.not.closed.display.name=JDBC resource opened but not safely closed
-jdbc.resource.opened.not.closed.problem.descriptor=JDBC ''{0}'' should be opened in front of a ''try'' block and closed in the corresponding ''finally'' block #loc
 jndi.resource.opened.not.closed.display.name=JNDI resource opened but not safely closed
 socket.opened.not.closed.display.name=Socket opened but not safely closed
 annotation.class.display.name=Annotation class
@@ -2033,4 +2030,8 @@
 junit.datapoint.problem.descriptor={1}s annotated with @DataPoint should be {0}
 inner.class.referenced.via.subclass.display.name=Inner class referenced via subclass
 inner.class.referenced.via.subclass.problem.descriptor=Inner class <code>#ref</code> declared in class ''{0}'' but referenced via subclass ''{1}'' #loc
-inner.class.referenced.via.subclass.quickfix=Rationalize inner class access
\ No newline at end of file
+inner.class.referenced.via.subclass.quickfix=Rationalize inner class access
+boolean.parameter.display.name='public' method with 'boolean' parameter
+boolean.parameter.problem.descriptor='public' method <code>#ref</code> with 'boolean' parameter
+boolean.parameters.problem.descriptor='public' method <code>#ref</code> with 'boolean' parameters
+boolean.parameter.only.report.multiple.option=Only report methods with multiple boolean parameters
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
index 1aa6827..7cd60f3b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
@@ -41,15 +41,6 @@
 
   private boolean myOnTheFly = false;
 
-  /**
-   * To appear in "Apply Fix" statement when multiple Quick Fixes exist
-   */
-  @Override
-  @NotNull
-  public String getFamilyName() {
-    return "";
-  }
-
   @Override
   public final void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
     final PsiElement problemElement = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java
new file mode 100644
index 0000000..5513f42
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.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 com.siyeh.ig.abstraction;
+
+import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PropertyUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class BooleanParameterInspection extends BaseInspection {
+
+  @SuppressWarnings("PublicField")
+  public boolean onlyReportMultiple = false;
+
+  @Nls
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return InspectionGadgetsBundle.message("boolean.parameter.display.name");
+  }
+
+  @NotNull
+  @Override
+  protected String buildErrorString(Object... infos) {
+    if (((Integer)infos[0]).intValue() == 1) {
+      return InspectionGadgetsBundle.message("boolean.parameter.problem.descriptor");
+    }
+    else {
+      return InspectionGadgetsBundle.message("boolean.parameters.problem.descriptor");
+    }
+  }
+
+  @Nullable
+  @Override
+  public JComponent createOptionsPanel() {
+    return new SingleCheckboxOptionsPanel(
+      InspectionGadgetsBundle.message("boolean.parameter.only.report.multiple.option"), this, "onlyReportMultiple");
+  }
+
+  @Override
+  public BaseInspectionVisitor buildVisitor() {
+    return new BooleanParameterVisitor();
+  }
+
+  private class BooleanParameterVisitor extends BaseInspectionVisitor {
+
+    @Override
+    public void visitMethod(PsiMethod method) {
+      super.visitMethod(method);
+      if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
+        final PsiClass aClass = method.getContainingClass();
+        if (aClass == null || !aClass.isInterface()) {
+          return;
+        }
+      }
+      if (PropertyUtil.isSimpleSetter(method)) {
+        return;
+      }
+      final PsiParameterList parameterList = method.getParameterList();
+      final PsiParameter[] parameters = parameterList.getParameters();
+      int count = 0;
+      for (PsiParameter parameter : parameters) {
+        final PsiType type = parameter.getType();
+        if (!PsiPrimitiveType.BOOLEAN.equals(type)) {
+          continue;
+        }
+        count++;
+        if (count > 1) {
+          break;
+        }
+      }
+
+      if (count == 0 || onlyReportMultiple && count == 1) {
+        return;
+      }
+      registerMethodError(method, Integer.valueOf(count));
+    }
+  }
+}
+
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
index 53ef3d2..2180e66d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
@@ -108,6 +108,12 @@
         "declare.collection.as.interface.quickfix", typeString);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Weaken type";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
index d0f9349..a312008 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
@@ -64,6 +64,11 @@
   }
 
   private static class OverlyStrongCastFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
index f036539..a0eede4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
@@ -128,6 +128,12 @@
       return InspectionGadgetsBundle.message("type.may.be.weakened.quickfix", fqClassName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Weaken type";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
@@ -202,6 +208,9 @@
         if (declarationScope instanceof PsiCatchSection) {
           // do not weaken catch block parameters
           return;
+        } else if (declarationScope instanceof PsiLambdaExpression && parameter.getTypeElement() == null) {
+          //no need to check inferred lambda params
+          return;
         }
         else if (declarationScope instanceof PsiMethod) {
           final PsiMethod method = (PsiMethod)declarationScope;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
index cd4eb42..2081435 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
@@ -51,6 +51,12 @@
       return InspectionGadgetsBundle.message("assignment.used.as.condition.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiAssignmentExpression expression = (PsiAssignmentExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
index 7b0d4e3..cc40f05 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
@@ -105,6 +105,12 @@
         elementText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Extract to separate statement";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
index e93df55..478164c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
@@ -136,6 +136,12 @@
         signText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
index f893ac2..38bafe6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
@@ -175,6 +175,11 @@
       return InspectionGadgetsBundle.message(
         "pointless.bitwise.expression.simplify.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/ShiftOutOfRangeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/ShiftOutOfRangeInspection.java
index eee9459..e7a224f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/ShiftOutOfRangeInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/ShiftOutOfRangeInspection.java
@@ -87,6 +87,12 @@
         Integer.valueOf(value), Integer.valueOf(newValue));
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Fix shift value";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java
index 430e2ee..3346fdb 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java
@@ -69,6 +69,11 @@
   }
 
   private static class ReplaceWithParseMethodFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
@@ -114,6 +119,12 @@
         "archaic.system.property.accessors.replace.standard.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
index 540354d..ae477e5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
@@ -75,6 +75,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with implicit equals";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
index 0eee77f..ae607f1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
@@ -81,6 +81,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with Arrays.equals";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
index 2e46a81..d5a3b68 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
@@ -79,6 +79,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with implicit 'hashCode'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java
index 77fd142..832cb68 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java
@@ -214,6 +214,12 @@
       return InspectionGadgetsBundle.message("cast.conflicts.with.instanceof.quickfix1", myCastType, myInstanceofType);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace cast type";
+    }
+
     @Override
     protected PsiElement replace(PsiTypeElement castTypeElement, PsiTypeElement instanceofTypeElement) {
       return castTypeElement.replace(instanceofTypeElement);
@@ -230,6 +236,12 @@
       myCastType = castType;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace instanceOf type";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
index afca4c1..55c5da3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
@@ -64,6 +64,12 @@
         "class.new.instance.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyInitializerInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyInitializerInspection.java
index 4a3976d..1cbc998 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyInitializerInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EmptyInitializerInspection.java
@@ -56,6 +56,11 @@
   }
 
   private static class EmptyInitializerFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
index 84307f7..20649cf 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
@@ -86,6 +86,12 @@
       this.removeToString = removeToString;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make Array.toString() implicit";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/InnerClassReferencedViaSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/InnerClassReferencedViaSubclassInspection.java
index 0270384..36eac11 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/InnerClassReferencedViaSubclassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/InnerClassReferencedViaSubclassInspection.java
@@ -60,6 +60,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("inner.class.referenced.via.subclass.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
index b21554f..f3af8bd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
@@ -65,6 +65,11 @@
   private static class MathRandomCastToIntegerFix extends InspectionGadgetsFix {
     @Override
     @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+    @Override
+    @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message(
         "math.random.cast.to.int.quickfix");
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
index f72d9d5..0532b9c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
@@ -62,6 +62,11 @@
 
   private static class NewStringBufferWithCharArgumentFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
index cf34693..b7a765d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
@@ -63,6 +63,12 @@
       return InspectionGadgetsBundle.message("non.short.circuit.boolean.expression.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiPolyadicExpression expression = (PsiPolyadicExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
index 77bc67c..65a1f8e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
@@ -64,6 +64,11 @@
       return InspectionGadgetsBundle.message(
         "static.method.via.subclass.rationalize.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
index feffc6e..b80bc1d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
@@ -59,6 +59,11 @@
   }
 
   private static class StaticFieldOnSubclassFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
index 812b105..2331526 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
@@ -68,6 +68,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return InspectionGadgetsBundle.message("string.concatenation.in.format.call.plural.quickfix"); 
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement().getParent().getParent();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInMessageFormatCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInMessageFormatCallInspection.java
index 0ba3920..67448d5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInMessageFormatCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInMessageFormatCallInspection.java
@@ -67,6 +67,12 @@
       return InspectionGadgetsBundle.message("string.concatenation.in.format.call.quickfix", variableName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace concatenation with argument";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
index 4d6dae4..4fa34c6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
@@ -90,6 +90,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Fix property access";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java
index 083e39f..1788bfa 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java
@@ -58,6 +58,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("class.may.be.interface.convert.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected boolean prepareForWriting() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ListenerMayUseAdapterInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ListenerMayUseAdapterInspection.java
index 96aed1e..dff210f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ListenerMayUseAdapterInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ListenerMayUseAdapterInspection.java
@@ -84,6 +84,12 @@
         adapterClass.getName());
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with adapter";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java
index 92c3d133..ec87f2a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingDeprecatedAnnotationInspection.java
@@ -59,6 +59,12 @@
       return InspectionGadgetsBundle.message("missing.deprecated.annotation.add.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement identifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java
index 0e1c587..3c18cc3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java
@@ -89,6 +89,11 @@
       return InspectionGadgetsBundle.message(
         "missing.override.annotation.add.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/PublicConstructorInNonPublicClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/PublicConstructorInNonPublicClassInspection.java
index 7cf7cc5..ec357ae 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/PublicConstructorInNonPublicClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/PublicConstructorInNonPublicClassInspection.java
@@ -72,6 +72,12 @@
       this.modifier = modifier;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Fix constructor modifier";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/UtilityClassWithPublicConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/UtilityClassWithPublicConstructorInspection.java
index 59d529e..273c944 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/UtilityClassWithPublicConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/UtilityClassWithPublicConstructorInspection.java
@@ -73,6 +73,12 @@
         Integer.valueOf(m_multipleConstructors ? 1 : 2));
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make constructors private";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java
index 040ac91..4708776 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java
@@ -67,6 +67,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("clone.doesnt.declare.clonenotsupportedexception.declare.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneableImplementsCloneInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneableImplementsCloneInspection.java
index 31552bb..6213c82 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneableImplementsCloneInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneableImplementsCloneInspection.java
@@ -71,6 +71,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("cloneable.class.without.clone.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
index d51b23e..beb27e4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
@@ -57,6 +57,11 @@
       return InspectionGadgetsBundle.message(
         "conditional.expression.with.identical.branches.collapse.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConfusingElseInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConfusingElseInspection.java
index 975a421..11062a3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConfusingElseInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConfusingElseInspection.java
@@ -71,6 +71,11 @@
   }
 
   private static class ConfusingElseFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
index 12bf1ce..abb3fb9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
@@ -81,6 +81,12 @@
         "constant.conditional.expression.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
index c3b87fe6..1afa566 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
@@ -64,6 +64,11 @@
   }
 
   private static class ConstantIfStatementFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
index 92eebc3..c503eac 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
@@ -60,6 +60,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("double.negation.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
index b82a755f..10f7984 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
@@ -61,6 +61,11 @@
   }
 
   private static class FallthruInSwitchStatementFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
index 3817162..2b1ff6b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
@@ -77,6 +77,12 @@
         "for.loop.replaceable.by.while.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspection.java
index d764cc3..b31da17 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2011 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.
@@ -17,11 +17,11 @@
 
 import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
 import com.intellij.psi.*;
-import com.intellij.psi.util.InheritanceUtil;
 import com.siyeh.HardcodedMethodConstants;
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.TypeUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -29,16 +29,13 @@
 
 public class ForLoopWithMissingComponentInspection extends BaseInspection {
 
-  /**
-   * @noinspection PublicField
-   */
+  @SuppressWarnings("PublicField")
   public boolean ignoreCollectionLoops = false;
 
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "for.loop.with.missing.component.display.name");
+    return InspectionGadgetsBundle.message("for.loop.with.missing.component.display.name");
   }
 
   @Override
@@ -49,43 +46,35 @@
     final boolean hasUpdate = ((Boolean)infos[2]).booleanValue();
     if (hasInitializer) {
       if (hasCondition) {
-        return InspectionGadgetsBundle.message(
-          "for.loop.with.missing.component.problem.descriptor3");
+        return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor3");
       }
       else if (hasUpdate) {
-        return InspectionGadgetsBundle.message(
-          "for.loop.with.missing.component.problem.descriptor2");
+        return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor2");
       }
       else {
-        return InspectionGadgetsBundle.message(
-          "for.loop.with.missing.component.problem.descriptor6");
+        return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor6");
       }
     }
     else if (hasCondition) {
       if (hasUpdate) {
-        return InspectionGadgetsBundle.message(
-          "for.loop.with.missing.component.problem.descriptor1");
+        return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor1");
       }
       else {
-        return InspectionGadgetsBundle.message(
-          "for.loop.with.missing.component.problem.descriptor5");
+        return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor5");
       }
     }
     else if (hasUpdate) {
-      return InspectionGadgetsBundle.message(
-        "for.loop.with.missing.component.problem.descriptor4");
+      return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor4");
     }
     else {
-      return InspectionGadgetsBundle.message(
-        "for.loop.with.missing.component.problem.descriptor7");
+      return InspectionGadgetsBundle.message("for.loop.with.missing.component.problem.descriptor7");
     }
   }
 
   @Override
   @Nullable
   public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "for.loop.with.missing.component.collection.loop.option"),
+    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("for.loop.with.missing.component.collection.loop.option"),
                                           this, "ignoreCollectionLoops");
   }
 
@@ -94,12 +83,10 @@
     return new ForLoopWithMissingComponentVisitor();
   }
 
-  private class ForLoopWithMissingComponentVisitor
-    extends BaseInspectionVisitor {
+  private class ForLoopWithMissingComponentVisitor extends BaseInspectionVisitor {
 
     @Override
-    public void visitForStatement(
-      @NotNull PsiForStatement statement) {
+    public void visitForStatement(@NotNull PsiForStatement statement) {
       super.visitForStatement(statement);
       final boolean hasCondition = hasCondition(statement);
       final boolean hasInitializer = hasInitializer(statement);
@@ -110,8 +97,7 @@
       if (ignoreCollectionLoops && isCollectionLoopStatement(statement)) {
         return;
       }
-      registerStatementError(statement, Boolean.valueOf(hasInitializer),
-                             Boolean.valueOf(hasCondition), Boolean.valueOf(hasUpdate));
+      registerStatementError(statement, Boolean.valueOf(hasInitializer), Boolean.valueOf(hasCondition), Boolean.valueOf(hasUpdate));
     }
 
     private boolean hasCondition(PsiForStatement statement) {
@@ -120,8 +106,7 @@
 
     private boolean hasInitializer(PsiForStatement statement) {
       final PsiStatement initialization = statement.getInitialization();
-      return initialization != null &&
-             !(initialization instanceof PsiEmptyStatement);
+      return initialization != null && !(initialization instanceof PsiEmptyStatement);
     }
 
     private boolean hasUpdate(PsiForStatement statement) {
@@ -130,47 +115,18 @@
     }
 
     private boolean isCollectionLoopStatement(PsiForStatement forStatement) {
-      final PsiStatement initialization =
-        forStatement.getInitialization();
+      final PsiStatement initialization = forStatement.getInitialization();
       if (!(initialization instanceof PsiDeclarationStatement)) {
         return false;
       }
-      final PsiDeclarationStatement declaration =
-        (PsiDeclarationStatement)initialization;
-      final PsiElement[] declaredElements =
-        declaration.getDeclaredElements();
+      final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization;
+      final PsiElement[] declaredElements = declaration.getDeclaredElements();
       for (PsiElement declaredElement : declaredElements) {
         if (!(declaredElement instanceof PsiVariable)) {
           continue;
         }
         final PsiVariable variable = (PsiVariable)declaredElement;
-        final PsiType variableType = variable.getType();
-        if (!(variableType instanceof PsiClassType)) {
-          continue;
-        }
-        final PsiClassType classType = (PsiClassType)variableType;
-        final PsiClass declaredClass = classType.resolve();
-        if (declaredClass == null) {
-          continue;
-        }
-        if (!InheritanceUtil.isInheritor(declaredClass,
-                                         CommonClassNames.JAVA_UTIL_ITERATOR)) {
-          continue;
-        }
-        final PsiExpression initialValue = variable.getInitializer();
-        if (initialValue == null) {
-          continue;
-        }
-        if (!(initialValue instanceof PsiMethodCallExpression)) {
-          continue;
-        }
-        final PsiMethodCallExpression initialCall =
-          (PsiMethodCallExpression)initialValue;
-        final PsiReferenceExpression initialMethodExpression =
-          initialCall.getMethodExpression();
-        final String initialCallName =
-          initialMethodExpression.getReferenceName();
-        if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName)) {
+        if (!TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_UTIL_ITERATOR)) {
           continue;
         }
         final PsiExpression condition = forStatement.getCondition();
@@ -181,11 +137,9 @@
       return false;
     }
 
-    private boolean isHasNext(PsiExpression condition,
-                              PsiVariable iterator) {
+    private boolean isHasNext(PsiExpression condition, PsiVariable iterator) {
       if (condition instanceof PsiBinaryExpression) {
-        final PsiBinaryExpression binaryExpression =
-          (PsiBinaryExpression)condition;
+        final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)condition;
         final PsiExpression lhs = binaryExpression.getLOperand();
         final PsiExpression rhs = binaryExpression.getROperand();
         return isHasNext(lhs, iterator) || isHasNext(rhs, iterator);
@@ -193,26 +147,22 @@
       if (!(condition instanceof PsiMethodCallExpression)) {
         return false;
       }
-      final PsiMethodCallExpression call =
-        (PsiMethodCallExpression)condition;
+      final PsiMethodCallExpression call = (PsiMethodCallExpression)condition;
       final PsiExpressionList argumentList = call.getArgumentList();
       final PsiExpression[] arguments = argumentList.getExpressions();
       if (arguments.length != 0) {
         return false;
       }
-      final PsiReferenceExpression methodExpression =
-        call.getMethodExpression();
+      final PsiReferenceExpression methodExpression = call.getMethodExpression();
       final String methodName = methodExpression.getReferenceName();
       if (!HardcodedMethodConstants.HAS_NEXT.equals(methodName)) {
         return false;
       }
-      final PsiExpression qualifier =
-        methodExpression.getQualifierExpression();
+      final PsiExpression qualifier = methodExpression.getQualifierExpression();
       if (!(qualifier instanceof PsiReferenceExpression)) {
         return true;
       }
-      final PsiReferenceExpression referenceExpression =
-        (PsiReferenceExpression)qualifier;
+      final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
       final PsiElement target = referenceExpression.resolve();
       return iterator.equals(target);
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
index f06b437..46eb89e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
@@ -74,6 +74,12 @@
         "if.may.be.conditional.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
index d8b2cdf..6cc7a98 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
@@ -69,6 +69,12 @@
         "if.statement.with.identical.branches.collapse.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(@NotNull Project project,
                       ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
index 95eaca0..cda6605 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
@@ -58,6 +58,11 @@
 
   private static class LoopWithImplicitTerminationConditionFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
index e0d905c..b8fee88 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
@@ -76,6 +76,11 @@
   }
 
   private static class NegatedConditionalFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
index c7caa05..d7dfbd6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
@@ -57,6 +57,12 @@
       return InspectionGadgetsBundle.message("negated.equality.expression.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
index 22ca6da..289c74c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
@@ -76,6 +76,12 @@
 
   private static class NegatedIfElseFix extends InspectionGadgetsFix {
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
index dd14773..917abf2 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
@@ -271,6 +271,11 @@
   }
 
   private class PointlessBooleanExpressionFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
index 1500f27..a958a67 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
@@ -80,6 +80,12 @@
       return InspectionGadgetsBundle.message("pointless.nullcheck.simplify.quickfix", myExpressionText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
index 6b1a1e3..9263063 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
@@ -70,6 +70,12 @@
         "constant.conditional.expression.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
index 5469e57..f93948f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
@@ -65,6 +65,12 @@
       return InspectionGadgetsBundle.message("simplifiable.equals.expression.quickfix", myMethodName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
index 02df887..0a88a12 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
@@ -65,6 +65,11 @@
   private static class TrivialIfFix extends InspectionGadgetsFix {
     @Override
     @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+    @Override
+    @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message(
         "constant.conditional.expression.simplify.quickfix");
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
index d7b654c..446e713 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
@@ -85,6 +85,11 @@
 
   private static class UnnecessaryConditionalFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnBreakStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnBreakStatementInspection.java
index 3f662822..4d3bca4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnBreakStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnBreakStatementInspection.java
@@ -55,6 +55,11 @@
 
   private static class UnnecessaryLabelOnBreakStatementFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnContinueStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnContinueStatementInspection.java
index 8dfbef3..4c422d1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnContinueStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryLabelOnContinueStatementInspection.java
@@ -55,6 +55,11 @@
 
   private static class UnnecessaryLabelOnContinueStatementFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/ConstantValueVariableUseInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/ConstantValueVariableUseInspection.java
index 8fbb831..3cd34b1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/ConstantValueVariableUseInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/ConstantValueVariableUseInspection.java
@@ -71,6 +71,12 @@
         myText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java
index 204e624..0ae7803 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java
@@ -58,6 +58,11 @@
 
   private static class OrredNotEqualExpressionFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
index 1b28605..786236f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
@@ -75,6 +75,12 @@
       return InspectionGadgetsBundle.message("return.date.calendar.field.quickfix", myType);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Return clone";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/CaughtExceptionImmediatelyRethrownInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/CaughtExceptionImmediatelyRethrownInspection.java
index 3988f48..58a1164 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/CaughtExceptionImmediatelyRethrownInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/CaughtExceptionImmediatelyRethrownInspection.java
@@ -85,6 +85,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Delete catch statement";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
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 207e5e7..4a9b58b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
@@ -80,6 +80,11 @@
   }
 
   private static class EmptyCatchBlockFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @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 41ed575..8e3fbeb 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java
@@ -60,6 +60,11 @@
   private static class RemoveTryFinallyBlockFix extends InspectionGadgetsFix {
     @Override
     @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+    @Override
+    @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message("remove.try.finally.block.quickfix");
     }
@@ -100,7 +105,12 @@
   }
 
   private static class RemoveFinallyBlockFix extends InspectionGadgetsFix {
-    @Override
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+   @Override
     @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message("remove.finally.block.quickfix");
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/NullThrownInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/NullThrownInspection.java
index f2cbb1c..c7be176 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/NullThrownInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/NullThrownInspection.java
@@ -49,6 +49,11 @@
   }
 
   private static class ThrowNullFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @NotNull
     @Override
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
index f080376..338992a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
@@ -124,6 +124,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Fix 'throws' clause";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/finalization/FinalizeNotProtectedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/finalization/FinalizeNotProtectedInspection.java
index c124c0f..e999566 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/finalization/FinalizeNotProtectedInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/finalization/FinalizeNotProtectedInspection.java
@@ -53,6 +53,11 @@
   }
 
   private static class ProtectedFinalizeFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddSerialVersionUIDFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddSerialVersionUIDFix.java
index fc3d228..e207bb6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddSerialVersionUIDFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddSerialVersionUIDFix.java
@@ -31,6 +31,12 @@
     return InspectionGadgetsBundle.message("add.serialversionuidfield.quickfix");
   }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
index c3600bf..b649973 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
@@ -30,6 +30,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class AddThisQualifierFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ChangeModifierFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ChangeModifierFix.java
index 80f932d..2be78a4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ChangeModifierFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ChangeModifierFix.java
@@ -43,6 +43,12 @@
                                            modifierText);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Change modifier";
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteImportFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteImportFix.java
index 21188c6..5499466 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteImportFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteImportFix.java
@@ -30,6 +30,12 @@
     return InspectionGadgetsBundle.message("delete.import.quickfix");
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
index ccd70d6..d76a992 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
@@ -40,6 +40,12 @@
       "smth.unnecessary.remove.quickfix", name);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Remove redundant statement";
+  }
+
   @Override
   protected void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
index 4ef8fea..7ab4204 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
@@ -30,6 +30,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class EqualityToEqualsFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
index e301dd0..9ef4c14 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
@@ -39,6 +39,12 @@
       "extract.parameter.as.local.variable.quickfix");
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeCloneableFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeCloneableFix.java
index 1d76d41..d78a3cd9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeCloneableFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeCloneableFix.java
@@ -46,6 +46,12 @@
     }
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Make 'Cloneable'";
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
index 9afcac8..80ebfa0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
@@ -54,6 +54,12 @@
                                            fieldName);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Make final";
+  }
+
   @Override
   protected void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java
index 36d168d..c0d5a8a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java
@@ -58,6 +58,12 @@
       "make.static.final.quickfix", fieldName);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Make static final";
+  }
+
   @Override
   protected void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeInitializerExplicitFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeInitializerExplicitFix.java
index 6b64b81..67dc8f5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeInitializerExplicitFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeInitializerExplicitFix.java
@@ -32,6 +32,11 @@
     return InspectionGadgetsBundle.message(
       "make.initialization.explicit.quickfix");
   }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeSerializableFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeSerializableFix.java
index a0a781a..24d0f62 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeSerializableFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeSerializableFix.java
@@ -34,6 +34,12 @@
       "make.class.serializable.quickfix");
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java
index f4fabe4..b2a24d7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java
@@ -24,6 +24,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class NormalizeDeclarationFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/RemoveModifierFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/RemoveModifierFix.java
index de6a2c4..65660aa 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/RemoveModifierFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/RemoveModifierFix.java
@@ -31,6 +31,12 @@
     this.modifierText = modifierText;
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Remove modifier";
+  }
+
   @Override
   @NotNull
   public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java
index 0a0f981..c35c36d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java
@@ -77,6 +77,12 @@
       return InspectionGadgetsBundle.message("abstract.method.overrides.abstract.method.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement methodNameIdentifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
index 8fb2549..46ef38b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
@@ -54,6 +54,11 @@
 
   private static class RedundantMethodOverrideFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/TypeParameterExtendsFinalClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/TypeParameterExtendsFinalClassInspection.java
index 6c01383..dda5dac 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/TypeParameterExtendsFinalClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/TypeParameterExtendsFinalClassInspection.java
@@ -59,6 +59,11 @@
   }
 
   private static class TypeParameterExtendsFinalClassFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
index cf30a6d..2e0beba 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
@@ -236,5 +236,11 @@
     public String getName() {
       return "Introduce holder class";
     }
+
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
   }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
index bf6286f..9340ff4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
@@ -101,6 +101,12 @@
       return InspectionGadgetsBundle.message("absolute.alignment.in.user.interface.quickfix", shortClassName, myReplacement);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with constant";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
index 53adeb8..d25349c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
@@ -146,6 +146,11 @@
       return InspectionGadgetsBundle.message(
         "multiply.or.divide.by.power.of.two.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
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 da42176..bc1fbe0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
@@ -96,6 +96,12 @@
         elementName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make package-local";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
index 3946a0b..57d30db 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
@@ -264,6 +264,11 @@
   }
 
   private static class SimplifiableIfStatementFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
index 68f623b..c319ff3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
@@ -53,6 +53,11 @@
 
   private static class SingleCharacterStartsWithFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
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 c7c734b..2aa3c07 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/ClassWithoutConstructorInspection.java
@@ -58,6 +58,12 @@
         "class.without.constructor.create.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java
index 2613826..f8dace6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java
@@ -70,6 +70,11 @@
       return InspectionGadgetsBundle.message(
         "html.tag.can.be.javadoc.tag.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java
index c1f05d7..780a44b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java
@@ -65,6 +65,11 @@
       return InspectionGadgetsBundle.message(
         "unnecessary.inherit.doc.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java
index 63b1d75..554deb5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java
@@ -99,6 +99,12 @@
         "unnecessary.javadoc.link.quickfix", tagName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Remove redundant tag";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
index 798d53e..292d106 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
@@ -108,6 +108,12 @@
       return InspectionGadgetsBundle.message("auto.boxing.make.boxing.explicit.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiExpression expression = (PsiExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
index 0befc94..fa83ad8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
@@ -121,6 +121,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("auto.unboxing.make.unboxing.explicit.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
index e394370..f0b1e40 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
@@ -50,6 +50,11 @@
   }
 
   private static class ForEachFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/VarargParameterInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/VarargParameterInspection.java
index 07f12b2..6b03778 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/VarargParameterInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/VarargParameterInspection.java
@@ -67,6 +67,12 @@
       return InspectionGadgetsBundle.message("variable.argument.method.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
index 30608ed..8670e0a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
@@ -56,6 +56,12 @@
       return InspectionGadgetsBundle.message("assertequals.called.on.arrays.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement methodNameIdentifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
index 82ac660..8fae6b0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
@@ -54,6 +54,12 @@
       return InspectionGadgetsBundle.message("assertequals.may.be.assertsame.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MakePublicStaticFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MakePublicStaticFix.java
index 7e8a6c2..0e54556 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MakePublicStaticFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MakePublicStaticFix.java
@@ -3,7 +3,6 @@
 import com.intellij.codeInspection.ProblemDescriptor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiField;
 import com.intellij.psi.PsiMember;
 import com.intellij.psi.PsiModifier;
 import com.intellij.psi.util.PsiUtil;
@@ -41,4 +40,10 @@
   public String getName() {
     return myName;
   }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Make public/static";
+  }
 }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
index 49a9bed..edf499d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
@@ -55,6 +55,11 @@
   }
 
   private static class FlipParametersFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MultipleExceptionsDeclaredOnTestMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MultipleExceptionsDeclaredOnTestMethodInspection.java
index e92b0c8..185025c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MultipleExceptionsDeclaredOnTestMethodInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MultipleExceptionsDeclaredOnTestMethodInspection.java
@@ -63,6 +63,12 @@
         "multiple.exceptions.declared.on.test.method.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java
index fafab66..5e0d2ff 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java
@@ -51,6 +51,11 @@
   }
 
   private static class AddSuperSetUpCall extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
index 72080f7..e5512ae 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
@@ -55,6 +55,12 @@
       return InspectionGadgetsBundle.message("simplify.junit.assertion.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement methodNameIdentifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java
index c521c99..4d2230e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java
@@ -63,6 +63,11 @@
       return InspectionGadgetsBundle.message(
         "teardown.calls.super.teardown.add.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
index 253b5803..ca0d990 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
@@ -52,6 +52,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("big.decimal.equals.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
index 355a086..803e89c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
@@ -87,6 +87,12 @@
         "cached.number.constructor.call.quickfix", className);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with '.valueOf' call";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
index 0ff6016..5b9a4c4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
@@ -78,6 +78,11 @@
   }
 
   private static class CharUsedInArithmeticContentFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
@@ -115,6 +120,12 @@
       return InspectionGadgetsBundle.message("char.used.in.arithmetic.context.cast.quickfix", typeText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Insert cast";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
index 33b67a8..6ea0bf6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
@@ -61,6 +61,11 @@
   }
 
   private static class ComparisonToNaNFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
index 7cc2729..4b08dd9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
@@ -52,6 +52,11 @@
 
   private static class ConfusingFloatingPointLiteralFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
index f94adeb..71b6a97 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
@@ -83,6 +83,11 @@
   }
 
   private static class MakeStrictFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConvertOctalLiteralToDecimalFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConvertOctalLiteralToDecimalFix.java
index a552caf..c4545e7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConvertOctalLiteralToDecimalFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConvertOctalLiteralToDecimalFix.java
@@ -25,6 +25,11 @@
 
 class ConvertOctalLiteralToDecimalFix
   extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
index ab41e96..b08e354 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
@@ -107,6 +107,12 @@
         replacementString);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with 'float'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
index 5d401d2..cee789f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
@@ -112,6 +112,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return InspectionGadgetsBundle.message("implicit.numeric.conversion.make.explicit.quickfix");
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
index 8b5368a..dfb4832 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
@@ -107,6 +107,12 @@
         replacementString);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with long literal";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
index a503387..bc78f3b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
@@ -68,6 +68,11 @@
       return InspectionGadgetsBundle.message(
         "long.literals.ending.with.lowercase.l.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
index f6cd53c..417f3e8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
@@ -77,6 +77,11 @@
   }
 
   private static class MakeStrictFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
index beb7869..a4739cb 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
@@ -140,6 +140,11 @@
   }
 
   private class PointlessArithmeticFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/RemoveLeadingZeroFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/RemoveLeadingZeroFix.java
index b080a5d..9ddd84a1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/RemoveLeadingZeroFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/RemoveLeadingZeroFix.java
@@ -35,6 +35,12 @@
       "remove.leading.zero.to.make.decimal.quickfix");
   }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
   @Override
   protected void doFix(Project project, ProblemDescriptor descriptor)
     throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
index 8a71995..e8bf9a9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
@@ -75,6 +75,11 @@
   }
 
   private static class UnnecessaryExplicitNumericCastFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @NotNull
     @Override
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
index 8ab4cf6..da8d231 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
@@ -58,6 +58,11 @@
       return InspectionGadgetsBundle.message(
         "unnecessary.unary.minus.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
index d41663d..95cffc6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
@@ -97,6 +97,12 @@
         argumentText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with 'new BigDecimal'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
index c677d98..9623391 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
@@ -77,6 +77,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement().getParent().getParent();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java
index fab1858..ce85003 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java
@@ -76,6 +76,12 @@
       return InspectionGadgetsBundle.message("boolean.constructor.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiNewExpression expression = (PsiNewExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BoxingBoxedValueInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BoxingBoxedValueInspection.java
index e7ee81d..01e0a3e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BoxingBoxedValueInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BoxingBoxedValueInspection.java
@@ -83,6 +83,12 @@
         "boxing.boxed.value.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
index a317412..f360ad1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
@@ -76,6 +76,11 @@
   }
 
   private static class InlineCallFix extends InspectionGadgetsFix {
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
index 6c5b9b6..1572b1b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
@@ -84,6 +84,12 @@
       return InspectionGadgetsBundle.message("call.to.simple.setter.in.class.inline.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
index ea205c2..ada80c6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
@@ -54,6 +54,11 @@
   }
 
   private static class ConstantStringInternFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
index aac5783..f4c3a3072 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
@@ -54,6 +54,11 @@
   }
 
   private static class InnerClassMayBeStaticFix extends InspectionGadgetsFix {
+        @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
index e5a4623..9a001ed 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
@@ -64,6 +64,12 @@
         "instantiating.object.to.get.class.object.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
index 5cd9e76..053113b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
@@ -62,6 +62,11 @@
 
   private static class KeySetIterationMapUseEntrySetFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
index 28c12bf..3207f5b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
@@ -67,6 +67,11 @@
 
   private static class ReplaceStringsWithCharsFix
     extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
index ecd9193..b776bd5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
@@ -70,6 +70,12 @@
         "length.one.strings.in.concatenation.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
index f01ef60..cfb3199 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
@@ -77,6 +77,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("manual.array.copy.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
index 98b77797..2c26bd5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
@@ -70,6 +70,12 @@
         "manual.array.to.collection.copy.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
index 5cc2ec9..e904f47 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
@@ -67,6 +67,12 @@
         "random.double.for.random.integer.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RedundantStringFormatCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RedundantStringFormatCallInspection.java
index 957e987..855e584 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RedundantStringFormatCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RedundantStringFormatCallInspection.java
@@ -23,7 +23,6 @@
 import com.siyeh.ig.BaseInspection;
 import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.FormatUtils;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -56,6 +55,11 @@
       return InspectionGadgetsBundle.message(
         "redundant.string.format.call.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
index 693bb9e..40e3ccf 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
@@ -55,6 +55,11 @@
   }
 
   private static class StringBufferToStringFix extends InspectionGadgetsFix {
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInsideStringBufferAppendInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInsideStringBufferAppendInspection.java
index b36ffaa..242c60f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInsideStringBufferAppendInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInsideStringBufferAppendInspection.java
@@ -62,6 +62,11 @@
   }
 
   private static class ReplaceWithChainedAppendFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
index 9ab5e74..1390475 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
@@ -103,6 +103,12 @@
       return m_name;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
index ab59be4..8a87343 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
@@ -75,6 +75,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify empty string check";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiIdentifier name = (PsiIdentifier)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
index d955fd2..2376f75 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
@@ -71,6 +71,12 @@
         "constant.conditional.expression.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
index 2707170..7ed0a20 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
@@ -62,6 +62,12 @@
         "constant.conditional.expression.simplify.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TailRecursionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TailRecursionInspection.java
index 58f0b89..b9c8c4b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TailRecursionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TailRecursionInspection.java
@@ -78,6 +78,12 @@
         "tail.recursion.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
index 4b72244..43516f1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
@@ -148,6 +148,12 @@
       return m_name;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace concatenation";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiLiteralExpression expression = (PsiLiteralExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
index f37ccc7..6295e1b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
@@ -147,6 +147,13 @@
       return m_name;
     }
 
+
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
index 7e8a4af..d4e814a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
@@ -112,6 +112,12 @@
       return m_name;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
index 7a1530d6..8326614 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
@@ -56,6 +56,11 @@
   }
 
   private static class UnusedLabelFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ChannelResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ChannelResourceInspection.java
index e02e89d..c9dc2d8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ChannelResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ChannelResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2011 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.
@@ -15,22 +15,15 @@
  */
 package com.siyeh.ig.resources;
 
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.siyeh.HardcodedMethodConstants;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.TypeUtils;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-
 public class ChannelResourceInspection extends ResourceInspection {
 
-  @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
-
   @Override
   @NotNull
   public String getID() {
@@ -40,115 +33,58 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "channel.opened.not.closed.display.name");
+    return InspectionGadgetsBundle.message("channel.opened.not.closed.display.name");
   }
 
-  @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "channel.opened.not.closed.problem.descriptor", text);
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "allow.resource.to.be.opened.inside.a.try.block"),
-                                          this, "insideTryAllowed");
-  }
-
-  @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new ChannelResourceVisitor();
-  }
-
-  private class ChannelResourceVisitor extends BaseInspectionVisitor {
-
-    @Override
-    public void visitMethodCallExpression(
-      @NotNull PsiMethodCallExpression expression) {
-      super.visitMethodCallExpression(expression);
-      if (!isChannelFactoryMethod(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement ||
-          parent instanceof PsiResourceVariable) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isChannelFactoryClosedInFinally(expression)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
+  protected boolean isResourceCreation(PsiExpression expression) {
+    if (!(expression instanceof PsiMethodCallExpression)) {
+      return false;
     }
+    final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+    final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+    final String methodName = methodExpression.getReferenceName();
+    if (!HardcodedMethodConstants.GET_CHANNEL.equals(methodName)) {
+      return false;
+    }
+    final PsiExpression qualifier = methodExpression.getQualifierExpression();
+    if (qualifier == null ||
+        TypeUtils.expressionHasTypeOrSubtype(qualifier,
+                                             "java.net.Socket", "java.net.DatagramSocket", "java.net.ServerSocket",
+                                             "java.net.SocketInputStream", "java.net.SocketOutputStream", "java.io.FileInputStream",
+                                             "java.io.FileOutputStream", "java.io.RandomAccessFile",
+                                             "com.sun.corba.se.pept.transport.EventHandler", "sun.nio.ch.InheritedChannel") == null) {
+      return false;
+    }
+    return TypeUtils.expressionHasTypeOrSubtype(expression, "java.nio.channels.Channel");
+  }
 
-    private boolean isChannelFactoryClosedInFinally(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      final PsiExpression qualifier =
-        methodExpression.getQualifierExpression();
-      if (!(qualifier instanceof PsiReferenceExpression)) {
-        return false;
-      }
-      final PsiReferenceExpression referenceExpression =
-        (PsiReferenceExpression)qualifier;
-      final PsiElement target = referenceExpression.resolve();
-      if (!(target instanceof PsiVariable)) {
-        return false;
-      }
-      final PsiVariable variable = (PsiVariable)target;
-      PsiTryStatement tryStatement =
-        PsiTreeUtil.getParentOfType(expression,
-                                    PsiTryStatement.class, true, PsiMember.class);
+  @Override
+  protected boolean isResourceFactoryClosed(PsiExpression expression, boolean insideTryAllowed) {
+    if (!(expression instanceof PsiMethodCallExpression)) {
+      return false;
+    }
+    final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+    final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+    final PsiExpression qualifier = methodExpression.getQualifierExpression();
+    if (!(qualifier instanceof PsiReferenceExpression)) {
+      return false;
+    }
+    final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
+    final PsiElement target = referenceExpression.resolve();
+    if (!(target instanceof PsiVariable)) {
+      return false;
+    }
+    final PsiVariable variable = (PsiVariable)target;
+    PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(expression, PsiTryStatement.class, true, PsiMember.class);
+    if (tryStatement == null) {
+      return false;
+    }
+    while (!isResourceClosedInFinally(tryStatement, variable)) {
+      tryStatement = PsiTreeUtil.getParentOfType(tryStatement, PsiTryStatement.class, true, PsiMember.class);
       if (tryStatement == null) {
         return false;
       }
-      while (!isResourceClosedInFinally(tryStatement, variable)) {
-        tryStatement =
-          PsiTreeUtil.getParentOfType(tryStatement,
-                                      PsiTryStatement.class, true, PsiMember.class);
-        if (tryStatement == null) {
-          return false;
-        }
-      }
-      return true;
     }
-
-    private boolean isChannelFactoryMethod(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      final String methodName = methodExpression.getReferenceName();
-      if (!HardcodedMethodConstants.GET_CHANNEL.equals(methodName)) {
-        return false;
-      }
-      final PsiExpression qualifier =
-        methodExpression.getQualifierExpression();
-      if (qualifier == null) {
-        return false;
-      }
-      return TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                  "java.net.Socket",
-                                                  "java.net.DatagramSocket",
-                                                  "java.net.ServerSocket",
-                                                  "java.io.FileInputStream",
-                                                  "java.io.FileOutputStream",
-                                                  "java.io.RandomAccessFile",
-                                                  "com.sun.corba.se.pept.transport.EventHandler",
-                                                  "sun.nio.ch.InheritedChannel") != null;
-    }
+    return true;
   }
 }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/HibernateResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/HibernateResourceInspection.java
index 945e0e5..80a590d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/HibernateResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/HibernateResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2010 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.
@@ -15,21 +15,16 @@
  */
 package com.siyeh.ig.resources;
 
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiMethodCallExpression;
+import com.intellij.psi.PsiReferenceExpression;
 import com.siyeh.HardcodedMethodConstants;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.TypeUtils;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-
 public class HibernateResourceInspection extends ResourceInspection {
 
-  @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
-
   @Override
   @NotNull
   public String getID() {
@@ -39,72 +34,20 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "hibernate.resource.opened.not.closed.display.name");
+    return InspectionGadgetsBundle.message("hibernate.resource.opened.not.closed.display.name");
   }
 
-  @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "hibernate.resource.opened.not.closed.problem.descriptor",
-      text);
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "allow.resource.to.be.opened.inside.a.try.block"),
-                                          this, "insideTryAllowed");
-  }
-
-  @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new HibernateResourceVisitor();
-  }
-
-  private class HibernateResourceVisitor extends BaseInspectionVisitor {
-
-    @Override
-    public void visitMethodCallExpression(
-      @NotNull PsiMethodCallExpression expression) {
-      super.visitMethodCallExpression(expression);
-      if (!isHibernateFactoryMethod(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
+  protected boolean isResourceCreation(PsiExpression expression) {
+    if (!(expression instanceof PsiMethodCallExpression)) {
+      return false;
     }
-
-    private boolean isHibernateFactoryMethod(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      final String methodName = methodExpression.getReferenceName();
-      if (!HardcodedMethodConstants.OPEN_SESSION.equals(methodName)) {
-        return false;
-      }
-      final PsiExpression qualifier =
-        methodExpression.getQualifierExpression();
-      if (qualifier == null) {
-        return false;
-      }
-      return TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                  "org.hibernate.SessionFactory");
+    final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+    final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+    final String methodName = methodExpression.getReferenceName();
+    if (!HardcodedMethodConstants.OPEN_SESSION.equals(methodName)) {
+      return false;
     }
+    final PsiExpression qualifier = methodExpression.getQualifierExpression();
+    return qualifier != null && TypeUtils.expressionHasTypeOrSubtype(qualifier, "org.hibernate.SessionFactory");
   }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/IOResourceInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/IOResourceInspectionBase.java
index 36078e1..31ac244 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/IOResourceInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/IOResourceInspectionBase.java
@@ -18,9 +18,7 @@
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.TypeUtils;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
@@ -30,10 +28,11 @@
 import java.util.List;
 
 public class IOResourceInspectionBase extends ResourceInspection {
-  protected static final String[] IO_TYPES = {
-    "java.io.InputStream", "java.io.OutputStream",
-    "java.io.Reader", "java.io.Writer",
-    "java.io.RandomAccessFile", "java.util.zip.ZipFile"};
+  protected static final String[] IO_TYPES =
+    {
+      "java.io.InputStream", "java.io.OutputStream", "java.io.Reader", "java.io.Writer",
+      "java.io.RandomAccessFile", "java.util.zip.ZipFile"
+    };
   final List<String> ignoredTypes = new ArrayList();
 
   public IOResourceInspectionBase() {
@@ -50,18 +49,6 @@
                                      ',' + "java.io.StringWriter" +
                                      ',' + "java.io.StringReader";
   @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
-
-  public static boolean isIOResourceFactoryMethodCall(PsiMethodCallExpression expression) {
-    final PsiReferenceExpression methodExpression = expression.getMethodExpression();
-    @NonNls final String methodName = methodExpression.getReferenceName();
-    if (!"getResourceAsStream".equals(methodName)) {
-      return false;
-    }
-    final PsiExpression qualifier = methodExpression.getQualifierExpression();
-    return qualifier != null &&
-           TypeUtils.expressionHasTypeOrSubtype(qualifier, CommonClassNames.JAVA_LANG_CLASS, "java.lang.ClassLoader") != null;
-  }
 
   @Override
   @NotNull
@@ -72,19 +59,7 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "i.o.resource.opened.not.closed.display.name");
-  }
-
-  @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "resource.opened.not.closed.problem.descriptor", text);
+    return InspectionGadgetsBundle.message("i.o.resource.opened.not.closed.display.name");
   }
 
   @Override
@@ -100,122 +75,28 @@
   }
 
   @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new IOResourceVisitor();
-  }
-
-  public boolean isIOResource(PsiExpression expression) {
-    return TypeUtils.expressionHasTypeOrSubtype(expression, IO_TYPES) != null && !isIgnoredType(expression);
+  public boolean isResourceCreation(PsiExpression expression) {
+    if (expression instanceof PsiNewExpression) {
+      return TypeUtils.expressionHasTypeOrSubtype(expression, IO_TYPES) != null && !isIgnoredType(expression);
+    }
+    else if (expression instanceof PsiMethodCallExpression) {
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+      final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+      @NonNls final String methodName = methodExpression.getReferenceName();
+      if (!"getResourceAsStream".equals(methodName)) {
+        return false;
+      }
+      final PsiExpression qualifier = methodExpression.getQualifierExpression();
+      if (qualifier == null ||
+          TypeUtils.expressionHasTypeOrSubtype(qualifier, CommonClassNames.JAVA_LANG_CLASS, "java.lang.ClassLoader") == null) {
+        return false;
+      }
+      return TypeUtils.expressionHasTypeOrSubtype(expression, "java.io.InputStream");
+    }
+    return false;
   }
 
   private boolean isIgnoredType(PsiExpression expression) {
     return TypeUtils.expressionHasTypeOrSubtype(expression, ignoredTypes);
   }
-
-  private boolean isArgumentOfResourceCreation(
-    PsiVariable boundVariable, PsiElement scope) {
-    final UsedAsIOResourceArgumentVisitor visitor =
-      new UsedAsIOResourceArgumentVisitor(boundVariable);
-    scope.accept(visitor);
-    return visitor.isUsedAsArgumentToResourceCreation();
-  }
-
-  private class IOResourceVisitor extends BaseInspectionVisitor {
-
-    IOResourceVisitor() {
-    }
-
-    @Override
-    public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
-      if (!isIOResourceFactoryMethodCall(expression)) {
-        return;
-      }
-      checkExpression(expression);
-    }
-
-    @Override
-    public void visitNewExpression(@NotNull PsiNewExpression expression) {
-      super.visitNewExpression(expression);
-      if (!isIOResource(expression)) {
-        return;
-      }
-      checkExpression(expression);
-    }
-
-    private void checkExpression(PsiExpression expression) {
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement || parent instanceof PsiResourceVariable) {
-        return;
-      }
-      if (parent instanceof PsiExpressionList) {
-        PsiElement grandParent = parent.getParent();
-        if (grandParent instanceof PsiAnonymousClass) {
-          grandParent = grandParent.getParent();
-        }
-        if (grandParent instanceof PsiNewExpression && isIOResource((PsiNewExpression)grandParent)) {
-          return;
-        }
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      final PsiElement containingBlock = PsiTreeUtil.getParentOfType(expression, PsiCodeBlock.class);
-      if (containingBlock == null) {
-        return;
-      }
-      if (isArgumentOfResourceCreation(boundVariable, containingBlock)) {
-        return;
-      }
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-  }
-
-  private class UsedAsIOResourceArgumentVisitor
-    extends JavaRecursiveElementVisitor {
-
-    private boolean usedAsArgToResourceCreation = false;
-    private final PsiVariable ioResource;
-
-    UsedAsIOResourceArgumentVisitor(PsiVariable ioResource) {
-      this.ioResource = ioResource;
-    }
-
-    @Override
-    public void visitNewExpression(
-      @NotNull PsiNewExpression expression) {
-      if (usedAsArgToResourceCreation) {
-        return;
-      }
-      super.visitNewExpression(expression);
-      if (!isIOResource(expression)) {
-        return;
-      }
-      final PsiExpressionList argumentList = expression.getArgumentList();
-      if (argumentList == null) {
-        return;
-      }
-      final PsiExpression[] arguments = argumentList.getExpressions();
-      if (arguments.length == 0) {
-        return;
-      }
-      final PsiExpression argument = arguments[0];
-      if (!(argument instanceof PsiReferenceExpression)) {
-        return;
-      }
-      final PsiReference reference = (PsiReference)argument;
-      final PsiElement target = reference.resolve();
-      if (target == null || !target.equals(ioResource)) {
-        return;
-      }
-      usedAsArgToResourceCreation = true;
-    }
-
-    public boolean isUsedAsArgumentToResourceCreation() {
-      return usedAsArgToResourceCreation;
-    }
-  }
-}
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JDBCResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JDBCResourceInspection.java
index a14ee5c..cdbc528 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JDBCResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JDBCResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2011 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.
@@ -15,15 +15,12 @@
  */
 package com.siyeh.ig.resources;
 
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
 import com.intellij.psi.*;
 import com.intellij.util.containers.ContainerUtil;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -56,11 +53,7 @@
     };
 
   @SuppressWarnings({"StaticCollection"})
-  private static final Set<String> creationMethodNameSet =
-    new HashSet<String>(9);
-
-  @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
+  private static final Set<String> creationMethodNameSet = new HashSet<String>(9);
 
   static {
     ContainerUtil.addAll(creationMethodNameSet, creationMethodName);
@@ -75,89 +68,39 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "jdbc.resource.opened.not.closed.display.name");
+    return InspectionGadgetsBundle.message("jdbc.resource.opened.not.closed.display.name");
   }
 
-  @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "jdbc.resource.opened.not.closed.problem.descriptor", text);
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "allow.resource.to.be.opened.inside.a.try.block"),
-                                          this, "insideTryAllowed");
-  }
-
-  @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new JDBCResourceVisitor();
-  }
-
-  private class JDBCResourceVisitor extends BaseInspectionVisitor {
-
-    @Override
-    public void visitMethodCallExpression(
-      @NotNull PsiMethodCallExpression expression) {
-      super.visitMethodCallExpression(expression);
-      if (!isJDBCResourceCreation(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement ||
-          parent instanceof PsiResourceVariable) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-
-    private boolean isJDBCResourceCreation(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      final String name = methodExpression.getReferenceName();
-      if (name == null) {
-        return false;
-      }
-      if (!creationMethodNameSet.contains(name)) {
-        return false;
-      }
-      final PsiMethod method = expression.resolveMethod();
-      if (method == null) {
-        return false;
-      }
-      for (int i = 0; i < creationMethodName.length; i++) {
-        if (!name.equals(creationMethodName[i])) {
-          continue;
-        }
-        final PsiClass containingClass = method.getContainingClass();
-        if (containingClass == null) {
-          return false;
-        }
-        final String className = containingClass.getQualifiedName();
-        if (className == null) {
-          return false;
-        }
-        if (className.equals(creationMethodClassName[i])) {
-          return true;
-        }
-      }
+  protected boolean isResourceCreation(PsiExpression expression) {
+    if (!(expression instanceof PsiMethodCallExpression)) {
       return false;
     }
+    final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+    final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+    final String name = methodExpression.getReferenceName();
+    if (name == null || !creationMethodNameSet.contains(name)) {
+      return false;
+    }
+    final PsiMethod method = methodCallExpression.resolveMethod();
+    if (method == null) {
+      return false;
+    }
+    for (int i = 0; i < creationMethodName.length; i++) {
+      if (!name.equals(creationMethodName[i])) {
+        continue;
+      }
+      final PsiClass containingClass = method.getContainingClass();
+      if (containingClass == null) {
+        return false;
+      }
+      final String className = containingClass.getQualifiedName();
+      if (className == null) {
+        return false;
+      }
+      if (className.equals(creationMethodClassName[i])) {
+        return true;
+      }
+    }
+    return false;
   }
 }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JNDIResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JNDIResourceInspection.java
index dd4097c..54148b3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JNDIResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/JNDIResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2010 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.
@@ -15,21 +15,17 @@
  */
 package com.siyeh.ig.resources;
 
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiMethodCallExpression;
+import com.intellij.psi.PsiNewExpression;
+import com.intellij.psi.PsiReferenceExpression;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.TypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-
 public class JNDIResourceInspection extends ResourceInspection {
 
-  @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
-
   @Override
   @NotNull
   public String getID() {
@@ -39,118 +35,36 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "jndi.resource.opened.not.closed.display.name");
+    return InspectionGadgetsBundle.message("jndi.resource.opened.not.closed.display.name");
   }
 
-  @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "resource.opened.not.closed.problem.descriptor", text);
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "allow.resource.to.be.opened.inside.a.try.block"),
-                                          this, "insideTryAllowed");
-  }
-
-  @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new JNDIResourceVisitor();
-  }
-
-  private class JNDIResourceVisitor extends BaseInspectionVisitor {
-
-    @NonNls
-    private static final String LIST = "list";
-    @NonNls
-    private static final String LIST_BINDING = "listBindings";
-    @NonNls
-    private static final String GET_ALL = "getAll";
-
-    @Override
-    public void visitMethodCallExpression(
-      @NotNull PsiMethodCallExpression expression) {
-      super.visitMethodCallExpression(expression);
-      if (!isJNDIFactoryMethod(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-
-
-    @Override
-    public void visitNewExpression(
-      @NotNull PsiNewExpression expression) {
-      super.visitNewExpression(expression);
-      if (!isJNDIResource(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-
-    private boolean isJNDIResource(PsiNewExpression expression) {
-      return TypeUtils.expressionHasTypeOrSubtype(expression,
-                                                  "javax.naming.InitialContext");
-    }
-
-    private boolean isJNDIFactoryMethod(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      final String methodName = methodExpression.getReferenceName();
-      if (LIST.equals(methodName) || LIST_BINDING.equals(methodName)) {
-        final PsiExpression qualifier =
-          methodExpression.getQualifierExpression();
+  protected boolean isResourceCreation(PsiExpression expression) {
+    if (expression instanceof PsiMethodCallExpression) {
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+      final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+      @NonNls final String methodName = methodExpression.getReferenceName();
+      if ("list".equals(methodName) || "listBindings".equals(methodName)) {
+        final PsiExpression qualifier = methodExpression.getQualifierExpression();
         if (qualifier == null) {
           return false;
         }
-        return TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                    "javax.naming.Context");
+        return TypeUtils.expressionHasTypeOrSubtype(qualifier, "javax.naming.Context");
       }
-      else if (GET_ALL.equals(methodName)) {
-        final PsiExpression qualifier =
-          methodExpression.getQualifierExpression();
+      else if ("getAll".equals(methodName)) {
+        final PsiExpression qualifier = methodExpression.getQualifierExpression();
         if (qualifier == null) {
           return false;
         }
-        return TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                    "javax.naming.directory.Attribute") ||
-               TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                    "javax.naming.directory.Attributes");
+        return TypeUtils.expressionHasTypeOrSubtype(qualifier, "javax.naming.directory.Attribute", "javax.naming.directory.Attributes") !=
+               null;
       }
       else {
         return false;
       }
     }
+    else if (expression instanceof PsiNewExpression) {
+      return TypeUtils.expressionHasTypeOrSubtype(expression, "javax.naming.InitialContext");
+    }
+    return false;
   }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java
index 86f74e5..67f5c33 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2011 Bas Leijdekkers
+ * Copyright 2008-2013 Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,53 +15,109 @@
  */
 package com.siyeh.ig.resources;
 
+import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.siyeh.HardcodedMethodConstants;
+import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.swing.*;
+
 public abstract class ResourceInspection extends BaseInspection {
 
+  @SuppressWarnings({"PublicField"})
+  public boolean insideTryAllowed = false;
+
+  @Override
+  public JComponent createOptionsPanel() {
+    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("allow.resource.to.be.opened.inside.a.try.block"),
+                                          this, "insideTryAllowed");
+  }
+
+  @Override
+  @NotNull
+  public String buildErrorString(Object... infos) {
+    final PsiExpression expression = (PsiExpression)infos[0];
+    final PsiType type = expression.getType();
+    assert type != null;
+    final String text = type.getPresentableText();
+    return InspectionGadgetsBundle.message("resource.opened.not.closed.problem.descriptor", text);
+  }
+
+  @Override
+  public final BaseInspectionVisitor buildVisitor() {
+    return new ResourceVisitor();
+  }
+
+  private class ResourceVisitor extends BaseInspectionVisitor {
+    @Override
+    public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
+      super.visitMethodCallExpression(expression);
+      checkExpression(expression);
+    }
+
+    @Override
+    public void visitNewExpression(@NotNull PsiNewExpression expression) {
+      super.visitNewExpression(expression);
+      checkExpression(expression);
+    }
+
+    private void checkExpression(PsiExpression expression) {
+      if (!isResourceCreation(expression)) {
+        return;
+      }
+      final PsiVariable boundVariable = getVariable(expression);
+      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
+        return;
+      }
+      if (isResourceFactoryClosed(expression, insideTryAllowed)) {
+        return;
+      }
+      if (isResourceEscapingFromMethod(boundVariable, expression)) {
+        return;
+      }
+      registerError(expression, expression);
+    }
+  }
+
+  protected abstract boolean isResourceCreation(PsiExpression expression);
+
+  protected boolean isResourceFactoryClosed(PsiExpression expression, boolean insideTryAllowed) {
+    return false;
+  }
+
   @Nullable
-  protected static PsiVariable getVariable(
-    @NotNull PsiElement element) {
-    if (element instanceof PsiAssignmentExpression) {
-      final PsiAssignmentExpression assignment =
-        (PsiAssignmentExpression)element;
+  private static PsiVariable getVariable(@NotNull PsiExpression expression) {
+    final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(expression);
+    if (parent instanceof PsiAssignmentExpression) {
+      final PsiAssignmentExpression assignment = (PsiAssignmentExpression)parent;
       final PsiExpression lhs = assignment.getLExpression();
       if (!(lhs instanceof PsiReferenceExpression)) {
         return null;
       }
-      final PsiReferenceExpression referenceExpression =
-        (PsiReferenceExpression)lhs;
+      final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
       final PsiElement referent = referenceExpression.resolve();
       if (!(referent instanceof PsiVariable)) {
         return null;
       }
       return (PsiVariable)referent;
     }
-    else if (element instanceof PsiVariable) {
-      return (PsiVariable)element;
+    else if (parent instanceof PsiVariable) {
+      return (PsiVariable)parent;
     }
     else {
       return null;
     }
   }
 
-  protected static PsiElement getExpressionParent(PsiExpression expression) {
-    PsiElement parent = expression.getParent();
-    while (parent instanceof PsiParenthesizedExpression ||
-           parent instanceof PsiTypeCastExpression) {
-      parent = parent.getParent();
-    }
-    return parent;
-  }
-
-  protected static boolean isSafelyClosed(@Nullable PsiVariable variable, PsiElement context, boolean insideTryAllowed) {
+  private static boolean isSafelyClosed(@Nullable PsiVariable variable, PsiElement context, boolean insideTryAllowed) {
     if (variable == null) {
       return false;
     }
@@ -104,9 +160,7 @@
     return isResourceClose(nextStatement, variable);
   }
 
-  protected static boolean isResourceClosedInFinally(
-    @NotNull PsiTryStatement tryStatement,
-    @NotNull PsiVariable variable) {
+  protected static boolean isResourceClosedInFinally(@NotNull PsiTryStatement tryStatement, @NotNull PsiVariable variable) {
     final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
     if (finallyBlock == null) {
       return false;
@@ -120,18 +174,14 @@
     return visitor.containsClose();
   }
 
-  private static boolean isResourceClose(PsiStatement statement,
-                                         PsiVariable variable) {
+  private static boolean isResourceClose(PsiStatement statement, PsiVariable variable) {
     if (statement instanceof PsiExpressionStatement) {
-      final PsiExpressionStatement expressionStatement =
-        (PsiExpressionStatement)statement;
-      final PsiExpression expression =
-        expressionStatement.getExpression();
+      final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)statement;
+      final PsiExpression expression = expressionStatement.getExpression();
       if (!(expression instanceof PsiMethodCallExpression)) {
         return false;
       }
-      final PsiMethodCallExpression methodCallExpression =
-        (PsiMethodCallExpression)expression;
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
       return isResourceClose(methodCallExpression, variable);
     }
     else if (statement instanceof PsiTryStatement) {
@@ -154,10 +204,8 @@
       if (!(condition instanceof PsiBinaryExpression)) {
         return false;
       }
-      final PsiBinaryExpression binaryExpression =
-        (PsiBinaryExpression)condition;
-      final IElementType tokenType =
-        binaryExpression.getOperationTokenType();
+      final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)condition;
+      final IElementType tokenType = binaryExpression.getOperationTokenType();
       if (JavaTokenType.NE != tokenType) {
         return false;
       }
@@ -170,8 +218,7 @@
         if (!(rhs instanceof PsiReferenceExpression)) {
           return false;
         }
-        final PsiReferenceExpression referenceExpression =
-          (PsiReferenceExpression)rhs;
+        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)rhs;
         final PsiElement target = referenceExpression.resolve();
         if (!variable.equals(target)) {
           return false;
@@ -181,8 +228,7 @@
         if (!(lhs instanceof PsiReferenceExpression)) {
           return false;
         }
-        final PsiReferenceExpression referenceExpression =
-          (PsiReferenceExpression)lhs;
+        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
         final PsiElement target = referenceExpression.resolve();
         if (!variable.equals(target)) {
           return false;
@@ -192,44 +238,21 @@
       return isResourceClose(thenBranch, variable);
     }
     else if (statement instanceof PsiBlockStatement) {
-      final PsiBlockStatement blockStatement =
-        (PsiBlockStatement)statement;
+      final PsiBlockStatement blockStatement = (PsiBlockStatement)statement;
       final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
       final PsiStatement[] statements = codeBlock.getStatements();
-      return statements.length != 0 &&
-             isResourceClose(statements[0], variable);
+      return statements.length != 0 && isResourceClose(statements[0], variable);
     }
     return false;
   }
 
-  protected static boolean isResourceEscapedFromMethod(
-    PsiVariable boundVariable, PsiElement context) {
-    // poor man dataflow
-    final PsiMethod method =
-      PsiTreeUtil.getParentOfType(context, PsiMethod.class, true,
-                                  PsiMember.class);
-    if (method == null) {
-      return false;
-    }
-    final PsiCodeBlock body = method.getBody();
-    if (body == null) {
-      return false;
-    }
-    final EscapeVisitor visitor = new EscapeVisitor(boundVariable);
-    body.accept(visitor);
-    return visitor.isEscaped();
-  }
-
-  protected static boolean isResourceClose(PsiMethodCallExpression call,
-                                           PsiVariable resource) {
-    final PsiReferenceExpression methodExpression =
-      call.getMethodExpression();
+  private static boolean isResourceClose(PsiMethodCallExpression call, PsiVariable resource) {
+    final PsiReferenceExpression methodExpression = call.getMethodExpression();
     final String methodName = methodExpression.getReferenceName();
     if (!HardcodedMethodConstants.CLOSE.equals(methodName)) {
       return false;
     }
-    final PsiExpression qualifier =
-      methodExpression.getQualifierExpression();
+    final PsiExpression qualifier = methodExpression.getQualifierExpression();
     if (!(qualifier instanceof PsiReferenceExpression)) {
       return false;
     }
@@ -238,6 +261,46 @@
     return referent != null && referent.equals(resource);
   }
 
+  private static boolean isResourceEscapingFromMethod(PsiVariable boundVariable, PsiExpression resourceCreationExpression) {
+    final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(resourceCreationExpression);
+    if (parent instanceof PsiReturnStatement || parent instanceof PsiResourceVariable) {
+      return true;
+    }
+    else if (parent instanceof PsiAssignmentExpression) {
+      final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+      if (ParenthesesUtils.stripParentheses(assignmentExpression.getRExpression()) != resourceCreationExpression) {
+        return true; // non-sensical code
+      }
+      final PsiExpression lhs = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression());
+      if (lhs instanceof PsiReferenceExpression) {
+        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
+        final PsiElement target = referenceExpression.resolve();
+        if (target instanceof PsiField) {
+          return true;
+        }
+      }
+    }
+    else if (parent instanceof PsiExpressionList) {
+      PsiElement grandParent = parent.getParent();
+      if (grandParent instanceof PsiAnonymousClass) {
+        grandParent = grandParent.getParent();
+      }
+      if (grandParent instanceof PsiCallExpression) {
+        return true;
+      }
+    }
+    if (boundVariable == null) {
+      return false;
+    }
+    final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(resourceCreationExpression, PsiCodeBlock.class, true, PsiMember.class);
+    if (codeBlock == null) {
+      return false;
+    }
+    final EscapeVisitor visitor = new EscapeVisitor(boundVariable);
+    codeBlock.accept(visitor);
+    return visitor.isEscaped();
+  }
+
   private static class CloseVisitor extends JavaRecursiveElementVisitor {
 
     private boolean containsClose = false;
@@ -270,8 +333,7 @@
     }
 
     @Override
-    public void visitReferenceExpression(
-      PsiReferenceExpression referenceExpression) {
+    public void visitReferenceExpression(PsiReferenceExpression referenceExpression) {
       // check if resource is closed in a method like IOUtils.silentClose()
       super.visitReferenceExpression(referenceExpression);
       if (containsClose) {
@@ -294,8 +356,7 @@
       if (!(grandParent instanceof PsiMethodCallExpression)) {
         return;
       }
-      final PsiMethodCallExpression methodCallExpression =
-        (PsiMethodCallExpression)grandParent;
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
       final PsiElement target = referenceExpression.resolve();
       if (target == null || !target.equals(resource)) {
         return;
@@ -333,13 +394,12 @@
     private final PsiVariable boundVariable;
     private boolean escaped = false;
 
-    public EscapeVisitor(PsiVariable boundVariable) {
+    public EscapeVisitor(@NotNull PsiVariable boundVariable) {
       this.boundVariable = boundVariable;
     }
 
     @Override
-    public void visitAnonymousClass(PsiAnonymousClass aClass) {
-    }
+    public void visitAnonymousClass(PsiAnonymousClass aClass) {}
 
     @Override
     public void visitElement(PsiElement element) {
@@ -350,16 +410,57 @@
     }
 
     @Override
-    public void visitReturnStatement(
-      PsiReturnStatement statement) {
-      PsiExpression value = statement.getReturnValue();
-      value = PsiUtil.deparenthesizeExpression(value);
-      if (value instanceof PsiReferenceExpression) {
-        final PsiReferenceExpression referenceExpression =
-          (PsiReferenceExpression)value;
+    public void visitReturnStatement(PsiReturnStatement statement) {
+      final PsiExpression value = PsiUtil.deparenthesizeExpression(statement.getReturnValue());
+      if (!(value instanceof PsiReferenceExpression)) {
+        return;
+      }
+      final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)value;
+      final PsiElement target = referenceExpression.resolve();
+      if (boundVariable.equals(target)) {
+        escaped = true;
+      }
+    }
+
+    @Override
+    public void visitAssignmentExpression(PsiAssignmentExpression expression) {
+      final PsiExpression rhs = PsiUtil.deparenthesizeExpression(expression.getRExpression());
+      if (!(rhs instanceof PsiReferenceExpression)) {
+        return;
+      }
+      final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)rhs;
+      final PsiElement target = referenceExpression.resolve();
+      if (!boundVariable.equals(target)) {
+        return;
+      }
+      final PsiExpression lhs = PsiUtil.deparenthesizeExpression(expression.getLExpression());
+      if (!(lhs instanceof PsiReferenceExpression)) {
+        return;
+      }
+      final PsiReferenceExpression lReferenceExpression = (PsiReferenceExpression)lhs;
+      final PsiElement lTarget = lReferenceExpression.resolve();
+      if (lTarget instanceof PsiField) {
+        escaped = true;
+      }
+    }
+
+    @Override
+    public void visitCallExpression(PsiCallExpression callExpression) {
+      final PsiExpressionList argumentList = callExpression.getArgumentList();
+      if (argumentList == null) {
+        return;
+      }
+      final PsiExpression[] expressions = argumentList.getExpressions();
+      for (PsiExpression expression : expressions) {
+        final PsiExpression expression1 = PsiUtil.deparenthesizeExpression(expression);
+        if (!(expression1 instanceof PsiReferenceExpression)) {
+          continue;
+        }
+        final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression1;
         final PsiElement target = referenceExpression.resolve();
-        if (target != null && target.equals(boundVariable)) {
+        if (boundVariable.equals(target)) {
           escaped = true;
+          break;
         }
       }
     }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/SocketResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/SocketResourceInspection.java
index 48336cc..b5e2c73 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/SocketResourceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/SocketResourceInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2011 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.
@@ -15,21 +15,17 @@
  */
 package com.siyeh.ig.resources;
 
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiMethodCallExpression;
+import com.intellij.psi.PsiNewExpression;
+import com.intellij.psi.PsiReferenceExpression;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.psiutils.TypeUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-
 public class SocketResourceInspection extends ResourceInspection {
 
-  @SuppressWarnings({"PublicField"})
-  public boolean insideTryAllowed = false;
-
   @Override
   @NotNull
   public String getID() {
@@ -39,103 +35,27 @@
   @Override
   @NotNull
   public String getDisplayName() {
-    return InspectionGadgetsBundle.message(
-      "socket.opened.not.closed.display.name");
+    return InspectionGadgetsBundle.message("socket.opened.not.closed.display.name");
   }
 
   @Override
-  @NotNull
-  public String buildErrorString(Object... infos) {
-    final PsiExpression expression = (PsiExpression)infos[0];
-    final PsiType type = expression.getType();
-    assert type != null;
-    final String text = type.getPresentableText();
-    return InspectionGadgetsBundle.message(
-      "resource.opened.not.closed.problem.descriptor", text);
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
-      "allow.resource.to.be.opened.inside.a.try.block"),
-                                          this, "insideTryAllowed");
-  }
-
-
-  @Override
-  public BaseInspectionVisitor buildVisitor() {
-    return new SocketResourceVisitor();
-  }
-
-  private class SocketResourceVisitor extends BaseInspectionVisitor {
-
-    @Override
-    public void visitMethodCallExpression(
-      @NotNull PsiMethodCallExpression expression) {
-      super.visitMethodCallExpression(expression);
-      if (!isSocketFactoryMethod(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement ||
-          parent instanceof PsiResourceVariable) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-
-    @Override
-    public void visitNewExpression(
-      @NotNull PsiNewExpression expression) {
-      super.visitNewExpression(expression);
-      if (!isSocketResource(expression)) {
-        return;
-      }
-      final PsiElement parent = getExpressionParent(expression);
-      if (parent instanceof PsiReturnStatement ||
-          parent instanceof PsiResourceVariable) {
-        return;
-      }
-      final PsiVariable boundVariable = getVariable(parent);
-      if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) {
-        return;
-      }
-      if (isResourceEscapedFromMethod(boundVariable, expression)) {
-        return;
-      }
-      registerError(expression, expression);
-    }
-
-    private boolean isSocketResource(PsiNewExpression expression) {
-      return TypeUtils.expressionHasTypeOrSubtype(expression,
-                                                  "java.net.Socket",
-                                                  "java.net.DatagramSocket",
-                                                  "java.net.ServerSocket") != null;
-    }
-
-    private boolean isSocketFactoryMethod(
-      PsiMethodCallExpression expression) {
-      final PsiReferenceExpression methodExpression =
-        expression.getMethodExpression();
-      @NonNls final String methodName =
-        methodExpression.getReferenceName();
+  protected boolean isResourceCreation(PsiExpression expression) {
+    if (expression instanceof PsiMethodCallExpression) {
+      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+      final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+      @NonNls final String methodName = methodExpression.getReferenceName();
       if (!"accept".equals(methodName)) {
         return false;
       }
-      final PsiExpression qualifier =
-        methodExpression.getQualifierExpression();
-      if (qualifier == null) {
+      final PsiExpression qualifier = methodExpression.getQualifierExpression();
+      if (qualifier == null || !TypeUtils.expressionHasTypeOrSubtype(qualifier, "java.net.ServerSocket")) {
         return false;
       }
-      return TypeUtils.expressionHasTypeOrSubtype(qualifier,
-                                                  "java.net.ServerSocket");
+      return TypeUtils.expressionHasTypeOrSubtype(methodCallExpression, "java.net.Socket");
     }
+    else if (expression instanceof PsiNewExpression) {
+      return TypeUtils.expressionHasTypeOrSubtype(expression, "java.net.Socket", "java.net.DatagramSocket", "java.net.ServerSocket") != null;
+    }
+    return false;
   }
 }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/NonSerializableWithSerialVersionUIDFieldInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/NonSerializableWithSerialVersionUIDFieldInspection.java
index b6f45ec..9a1d7ca 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/NonSerializableWithSerialVersionUIDFieldInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/NonSerializableWithSerialVersionUIDFieldInspection.java
@@ -82,6 +82,11 @@
   }
 
   private static class RemoveSerialVersionUIDFix extends InspectionGadgetsFix {
+       @Override
+  @NotNull
+  public String getFamilyName() {
+    return getName();
+  }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/SerialVersionUIDNotStaticFinalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/SerialVersionUIDNotStaticFinalInspection.java
index 481f6a0..8edd146 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/SerialVersionUIDNotStaticFinalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/SerialVersionUIDNotStaticFinalInspection.java
@@ -66,6 +66,11 @@
       return InspectionGadgetsBundle.message(
         "serialversionuid.private.static.final.long.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/TransientFieldInNonSerializableClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/TransientFieldInNonSerializableClassInspection.java
index c593463..6ed5a82 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/TransientFieldInNonSerializableClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/serialization/TransientFieldInNonSerializableClassInspection.java
@@ -56,6 +56,11 @@
 
   private static class TransientFieldInNonSerializableClassFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java
index 1e3498d..e4e9168 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java
@@ -58,6 +58,11 @@
       return InspectionGadgetsBundle.message(
         "c.style.array.declaration.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
index f5ed627..5113ab2 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
@@ -67,6 +67,12 @@
       return InspectionGadgetsBundle.message("call.to.string.concat.can.be.replaced.by.operator.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
index 858d5a8..d983cda 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
@@ -67,6 +67,12 @@
       return InspectionGadgetsBundle.message("flip.comparison.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiBinaryExpression expression = (PsiBinaryExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
index 4528fef..b0814a5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
@@ -60,6 +60,11 @@
   }
 
   private static class SwapComparisonFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
index 605430c..e4ea3d0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
@@ -56,6 +56,11 @@
       return InspectionGadgetsBundle.message(
         "control.flow.statement.without.braces.add.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
index a134ce56..ca343d0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
@@ -55,6 +55,11 @@
   }
 
   private static class EqualsCalledOnEnumValueFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ExtendsObjectInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ExtendsObjectInspection.java
index c3c5955..a87a6c8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ExtendsObjectInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ExtendsObjectInspection.java
@@ -57,6 +57,11 @@
   }
 
   private static class ExtendsObjectFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ImplicitCallToSuperInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ImplicitCallToSuperInspection.java
index f89babe..46195aa 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ImplicitCallToSuperInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ImplicitCallToSuperInspection.java
@@ -70,6 +70,12 @@
         "implicit.call.to.super.make.explicit.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
index 63db6c4c..ba1ae8d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
@@ -73,6 +73,11 @@
 
   private static class IndexOfReplaceableByContainsFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
index 04a654b..3da1133 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
@@ -59,6 +59,11 @@
   }
 
   private static class SwapEqualsFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/MissortedModifiersInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/MissortedModifiersInspection.java
index 37a7698..4708886 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/MissortedModifiersInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/MissortedModifiersInspection.java
@@ -71,6 +71,11 @@
   }
 
   private static class SortModifiersFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantFieldInitializationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantFieldInitializationInspection.java
index 2f3cae8..4bd27f0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantFieldInitializationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantFieldInitializationInspection.java
@@ -67,6 +67,12 @@
       return InspectionGadgetsBundle.message("redundant.field.initialization.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       descriptor.getPsiElement().delete();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantImplementsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantImplementsInspection.java
index a54717a..f5281c3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantImplementsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/RedundantImplementsInspection.java
@@ -72,6 +72,11 @@
   }
 
   private static class RedundantImplementsFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
index 8028686..0018131 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
@@ -63,6 +63,11 @@
       return InspectionGadgetsBundle.message(
         "simplifiable.annotation.quickfix");
     }
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
index 6f21ec2..0d08682 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
@@ -78,6 +78,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with 'String'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/TypeParameterExtendsObjectInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/TypeParameterExtendsObjectInspection.java
index 58e0661..b80a74a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/TypeParameterExtendsObjectInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/TypeParameterExtendsObjectInspection.java
@@ -75,6 +75,12 @@
         "extends.object.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(@NotNull Project project,
                       ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
index 9f6d515..dd81762 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
@@ -51,6 +51,11 @@
   }
 
   private static class UnclearBinaryExpressionFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @NotNull
     @Override
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java
index dfa79a4..226a745 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedInnerClassAccessInspection.java
@@ -70,6 +70,11 @@
 
   private static class UnnecessarilyQualifiedInnerClassAccessFix
     extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticUsageInspection.java
index a103093..1339a6d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticUsageInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticUsageInspection.java
@@ -93,6 +93,12 @@
       return InspectionGadgetsBundle.message("unnecessary.qualifier.for.this.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
index 8f6f9e7..09bcd89 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
@@ -58,6 +58,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("unnecessarily.qualified.statically.imported.element.quickfix");
     }
+  @Override
+  @NotNull
+  public String getFamilyName() {
+    return getName();
+  }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java
index 5af4d22..cd22119 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java
@@ -81,6 +81,12 @@
         "unnecessary.code.block.unwrap.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
index 62a4ac7..8b6091e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
@@ -80,6 +80,12 @@
       return InspectionGadgetsBundle.message("unnecessary.call.to.string.valueof.quickfix", replacementText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstantArrayCreationExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstantArrayCreationExpressionInspection.java
index 3051092..f14138f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstantArrayCreationExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstantArrayCreationExpressionInspection.java
@@ -51,6 +51,11 @@
 
   private static class UnnecessaryConstantArrayCreationExpressionFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
index 615195a..6416656 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
@@ -84,6 +84,12 @@
         "unnecessary.constructor.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
index 59df48e..f4bf9ea 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
@@ -70,6 +70,12 @@
       return m_name;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Remove unnecessary modifiers";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
index 0b905ee..880d3dd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
@@ -100,6 +100,12 @@
       return InspectionGadgetsBundle.message("smth.unnecessary.remove.quickfix", modifiersText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Remove unnecessary modifiers";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
index 2d31641..16dcce5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
@@ -73,6 +73,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("unnecessary.parentheses.remove.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
index 75abe2a..ae6faa9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
@@ -64,6 +64,12 @@
         "unnecessary.qualifier.for.this.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
index 9612996..5c01490 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
@@ -20,6 +20,7 @@
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.BaseInspection;
@@ -60,6 +61,11 @@
   }
 
   private static class UnnecessarySemicolonFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
@@ -88,30 +94,28 @@
     }
   }
 
-  private static class UnnecessarySemicolonVisitor
-    extends BaseInspectionVisitor {
-
-    /**
-     * Finds semicolons between the top level classes in a java file.
-     */
+  private static class UnnecessarySemicolonVisitor extends BaseInspectionVisitor {
     @Override
     public void visitFile(PsiFile file) {
-      final PsiElement firstChild = file.getFirstChild();
-      PsiElement sibling = skipForwardWhiteSpacesAndComments(firstChild);
-      while (sibling != null) {
-        if (sibling instanceof PsiJavaToken) {
-          final PsiJavaToken token = (PsiJavaToken)sibling;
-          final IElementType tokenType = token.getTokenType();
-          if (tokenType.equals(JavaTokenType.SEMICOLON)) {
-            registerError(sibling);
-          }
-        }
-        sibling = skipForwardWhiteSpacesAndComments(sibling);
-      }
+      findTopLevelSemicolons(file);
       super.visitFile(file);
     }
 
     @Override
+    public void visitImportList(PsiImportList list) {
+      findTopLevelSemicolons(list);
+      super.visitImportList(list);
+    }
+
+    private void findTopLevelSemicolons(PsiElement element) {
+      for (PsiElement sibling = element.getFirstChild(); sibling != null; sibling = skipForwardWhiteSpacesAndComments(sibling)) {
+        if (PsiUtil.isJavaToken(sibling, JavaTokenType.SEMICOLON)) {
+          registerError(sibling);
+        }
+      }
+    }
+
+    @Override
     public void visitClass(@NotNull PsiClass aClass) {
       super.visitClass(aClass);
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java
index 8cfac92..83c70a1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperConstructorInspection.java
@@ -56,6 +56,11 @@
 
   private static class UnnecessarySuperConstructorFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java
index 1a86985..fea9d87 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySuperQualifierInspection.java
@@ -57,6 +57,11 @@
     extends InspectionGadgetsFix {
     @Override
     @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+    @Override
+    @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message(
         "unnecessary.super.qualifier.quickfix");
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
index e7413de..b5a4f53 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
@@ -70,6 +70,12 @@
       return InspectionGadgetsBundle.message("unnecessary.this.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement thisToken = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
index d8831d7..1d2a26d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
@@ -74,6 +74,12 @@
       return InspectionGadgetsBundle.message("unnecessary.call.to.string.valueof.quickfix", replacementText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Simplify";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)descriptor.getPsiElement().getParent().getParent();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
index 65b863d..5a7d421 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
@@ -118,6 +118,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Qualify static access";
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
index ebef230..290aefe 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
@@ -67,6 +67,12 @@
         "condition.signal.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/DoubleCheckedLockingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/DoubleCheckedLockingInspection.java
index f65b176..0036f4a4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/DoubleCheckedLockingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/DoubleCheckedLockingInspection.java
@@ -87,6 +87,12 @@
         "double.checked.locking.quickfix", field.getName());
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make field volatile";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/MethodMayBeSynchronizedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/MethodMayBeSynchronizedInspection.java
index a8846a7..ba20b19 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/MethodMayBeSynchronizedInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/MethodMayBeSynchronizedInspection.java
@@ -64,6 +64,12 @@
         "method.may.be.synchronized.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
index 3468a3a..d7127fc 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
@@ -58,6 +58,11 @@
   }
 
   private static class ObjectNotifyFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SynchronizedMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SynchronizedMethodInspection.java
index 993073b..6c916b7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SynchronizedMethodInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SynchronizedMethodInspection.java
@@ -86,6 +86,11 @@
       return InspectionGadgetsBundle.message(
         "synchronized.method.move.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
index 47707b4..c25a23b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
@@ -62,6 +62,12 @@
         "thread.run.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(@NotNull Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
index 504f71d..26d6684 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
@@ -68,6 +68,12 @@
       return InspectionGadgetsBundle.message("ambiguous.field.access.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
index 5e072c3..c2f335f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
@@ -56,6 +56,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("ambiguous.method.call.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspection.java
index 0688918..c59f7e5 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspection.java
@@ -54,6 +54,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("static.method.only.used.in.one.class.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(@NotNull final Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ProtectedMemberInFinalClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ProtectedMemberInFinalClassInspection.java
index 02562bb..7eeeaee 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ProtectedMemberInFinalClassInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/ProtectedMemberInFinalClassInspection.java
@@ -70,6 +70,11 @@
   }
 
   private static class MakePrivateFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/PublicConstructorInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/PublicConstructorInspection.java
index 9ef67e9..400dc80 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/PublicConstructorInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/PublicConstructorInspection.java
@@ -77,6 +77,12 @@
       return InspectionGadgetsBundle.message("public.constructor.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(final Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiClass.class, PsiMethod.class);
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/UtilityClassWithoutPrivateConstructorInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/UtilityClassWithoutPrivateConstructorInspection.java
index d524ae2..277192e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/UtilityClassWithoutPrivateConstructorInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/UtilityClassWithoutPrivateConstructorInspection.java
@@ -106,6 +106,12 @@
       return InspectionGadgetsBundle.message("utility.class.without.private.constructor.create.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement classNameIdentifier = descriptor.getPsiElement();
@@ -145,6 +151,11 @@
   }
 
   private static class MakeConstructorPrivateFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/BooleanVariableAlwaysNegatedInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/BooleanVariableAlwaysNegatedInspection.java
index 575f65d..1a69c90 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/BooleanVariableAlwaysNegatedInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/BooleanVariableAlwaysNegatedInspection.java
@@ -18,16 +18,11 @@
 import com.intellij.codeInspection.ProblemDescriptor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.refactoring.invertBoolean.InvertBooleanDialog;
 import com.intellij.util.IncorrectOperationException;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
-import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
 
 public class BooleanVariableAlwaysNegatedInspection extends BooleanVariableAlwaysNegatedInspectionBase {
@@ -54,6 +49,12 @@
         "boolean.variable.always.inverted.quickfix", name);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Invert";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/ReuseOfLocalVariableInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/ReuseOfLocalVariableInspection.java
index 89a3762..024c0df 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/ReuseOfLocalVariableInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/ReuseOfLocalVariableInspection.java
@@ -23,19 +23,14 @@
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
-import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.Query;
 import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
 import com.siyeh.ig.InspectionGadgetsFix;
 import com.siyeh.ig.psiutils.HighlightUtils;
-import com.siyeh.ig.psiutils.VariableAccessUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -57,6 +52,12 @@
         "reuse.of.local.variable.split.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java
index 404e2b7..b4a6699 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java
@@ -54,6 +54,12 @@
       return InspectionGadgetsBundle.message("too.broad.scope.narrow.quickfix", variableName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Narrow scope";
+    }
+
     @Override
     protected void doFix(@NotNull Project project, ProblemDescriptor descriptor) {
       final PsiElement variableIdentifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
index b2845eb..50923d3 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
@@ -68,6 +68,12 @@
       myQualifiedClassName = qualifiedClassName;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make return collection 'unmodifiable'";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/ThrowsRuntimeExceptionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/ThrowsRuntimeExceptionInspection.java
index e09265b..c35f3ee 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/ThrowsRuntimeExceptionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/ThrowsRuntimeExceptionInspection.java
@@ -75,6 +75,12 @@
       return InspectionGadgetsBundle.message("throws.runtime.exception.move.quickfix", myExceptionName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Move to Javadoc '@throws'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
@@ -166,6 +172,12 @@
       return InspectionGadgetsBundle.message("throws.runtime.exception.quickfix", myClassName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Remove from \"throws\" clause";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       descriptor.getPsiElement().delete();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
index 2df05e5..2fba528 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
@@ -116,6 +116,12 @@
       return InspectionGadgetsBundle.message("too.broad.catch.quickfix", myText);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Add 'catch' clause";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement typeElement = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/EncapsulateVariableFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/EncapsulateVariableFix.java
index 3e32290..59461ca 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/EncapsulateVariableFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/EncapsulateVariableFix.java
@@ -42,6 +42,12 @@
                                            fieldName);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Encapsulate field";
+  }
+
   @Override
   public void doFix(final Project project, ProblemDescriptor descriptor) {
     final PsiElement nameElement = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractMethodFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractMethodFix.java
index fe23fd7..8d09ff2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractMethodFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractMethodFix.java
@@ -36,6 +36,12 @@
     return InspectionGadgetsBundle.message("extract.method.quickfix");
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return getName();
+  }
+
   @Override
   public void doFix(final Project project, ProblemDescriptor descriptor) {
     final PsiExpression expression =
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineCallFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineCallFix.java
index dcdb958..43e5774 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineCallFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineCallFix.java
@@ -28,6 +28,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class InlineCallFix extends InspectionGadgetsFix {
+      @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java
index 5bdf57b..79fa474 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java
@@ -29,6 +29,11 @@
 import java.util.Collection;
 
 public class InlineVariableFix extends InspectionGadgetsFix {
+       @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceConstantFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceConstantFix.java
index bb0692b..c4d4df5 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceConstantFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceConstantFix.java
@@ -29,6 +29,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class IntroduceConstantFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceVariableFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceVariableFix.java
index 36ba905..34980b7 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceVariableFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/IntroduceVariableFix.java
@@ -53,6 +53,12 @@
     }
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return InspectionGadgetsBundle.message("introduce.variable.quickfix");
+  }
+
   @Nullable
   public PsiExpression getExpressionToExtract(PsiElement element) {
     return PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class, false);
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
index 9691da4..6181adc 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
@@ -53,6 +53,12 @@
       "make.class.final.fix.name", className);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Make class final";
+  }
+
   @Override
   protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
     final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveAnonymousToInnerClassFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveAnonymousToInnerClassFix.java
index bd41131..e6e98a4 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveAnonymousToInnerClassFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveAnonymousToInnerClassFix.java
@@ -30,6 +30,8 @@
 
 public class MoveAnonymousToInnerClassFix extends InspectionGadgetsFix {
 
+  public static final String NAME = InspectionGadgetsBundle.message(
+    "move.anonymous.to.inner.quickfix");
   private final String name;
 
   public MoveAnonymousToInnerClassFix(String name) {
@@ -37,8 +39,13 @@
   }
 
   public MoveAnonymousToInnerClassFix() {
-    name = InspectionGadgetsBundle.message(
-      "move.anonymous.to.inner.quickfix");
+    name = NAME;
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return NAME;
   }
 
   @Override
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveClassFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveClassFix.java
index 2e56487..101a6c6 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveClassFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MoveClassFix.java
@@ -30,6 +30,11 @@
 import org.jetbrains.annotations.NotNull;
 
 public class MoveClassFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameFix.java
index 009dc19..30889e5 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameFix.java
@@ -51,6 +51,12 @@
     m_searchInNonJavaFiles = searchInNonJavaFiles;
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return InspectionGadgetsBundle.message("rename.quickfix");
+  }
+
   @Override
   @NotNull
   public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameParameterFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameParameterFix.java
index 1a99ce0..4397030 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameParameterFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/RenameParameterFix.java
@@ -39,6 +39,12 @@
     return InspectionGadgetsBundle.message("renameto.quickfix", m_targetName);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Rename";
+  }
+
   @Override
   public void doFix(Project project, ProblemDescriptor descriptor) {
     final PsiElement nameIdentifier = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ReplaceInheritanceWithDelegationFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ReplaceInheritanceWithDelegationFix.java
index 9538ded..df1a2e4 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ReplaceInheritanceWithDelegationFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ReplaceInheritanceWithDelegationFix.java
@@ -37,6 +37,11 @@
     return InspectionGadgetsBundle.message(
       "replace.inheritance.with.delegation.quickfix");
   }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
   @Override
   public void doFix(@NotNull final Project project, ProblemDescriptor descriptor) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
index 167e800..5defb34 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
@@ -106,6 +106,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("static.import.replace.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java
index e1a0320..ce49dd8 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/inheritance/StaticInheritanceFix.java
@@ -62,6 +62,12 @@
     return InspectionGadgetsBundle.message("static.inheritance.replace.quickfix", scope);
   }
 
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Replace inheritance with qualified reference";
+  }
+
   @Override
   public void doFix(final Project project, final ProblemDescriptor descriptor) throws IncorrectOperationException {
     ApplicationManager.getApplication().invokeLater(new Runnable() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverridableMethodCallDuringObjectConstructionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverridableMethodCallDuringObjectConstructionInspection.java
index a7ee6cd..f1b36bf 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverridableMethodCallDuringObjectConstructionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverridableMethodCallDuringObjectConstructionInspection.java
@@ -79,6 +79,12 @@
       return InspectionGadgetsBundle.message("make.method.final.fix.name", methodName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make method final";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement methodName = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/javadoc/PackageDotHtmlMayBePackageInfoInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/javadoc/PackageDotHtmlMayBePackageInfoInspection.java
index 2b8b78a..e7ac10a 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/javadoc/PackageDotHtmlMayBePackageInfoInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/javadoc/PackageDotHtmlMayBePackageInfoInspection.java
@@ -79,6 +79,12 @@
       return InspectionGadgetsBundle.message("package.dot.html.may.be.package.info.delete.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
@@ -107,6 +113,11 @@
     public PackageDotHtmlMayBePackageInfoFix(String aPackage) {
       this.aPackage = aPackage;
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java
index 261947b..261f1a9 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java
@@ -131,6 +131,12 @@
       }
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Fix modifiers";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java
index 3a20613..be71c41 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java
@@ -126,6 +126,12 @@
       return InspectionGadgetsBundle.message("convert.junit3.test.class.quickfix", className);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Convert JUnit 3 class to JUnit 4";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
@@ -254,6 +260,11 @@
   }
 
   private static class RemoveTestAnnotationFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/ParameterizedParametersStaticCollectionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/ParameterizedParametersStaticCollectionInspection.java
index 94b3d3d..dc7fc4c 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/ParameterizedParametersStaticCollectionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/ParameterizedParametersStaticCollectionInspection.java
@@ -149,6 +149,12 @@
       public String getName() {
         return infos.length > 0 ? (String)infos[0] : "Create @Parameterized.Parameters data provider";
       }
+
+      @NotNull
+      @Override
+      public String getFamilyName() {
+        return "Fix data provider signature";
+      }
     };
   }
 
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UseOfObsoleteAssertInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UseOfObsoleteAssertInspection.java
index 1e1140e..fda763f 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UseOfObsoleteAssertInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UseOfObsoleteAssertInspection.java
@@ -225,5 +225,12 @@
     public String getName() {
       return InspectionGadgetsBundle.message("use.of.obsolete.assert.quickfix");
     }
+
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
   }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
index b73b3406..c99f05b 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
@@ -102,6 +102,12 @@
 
   private class LogStatementGuardedByLogConditionFix extends InspectionGadgetsFix {
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java
index 18d5932..37619fe 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java
@@ -97,6 +97,12 @@
         newClassName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace foreign class";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
index 5169392..40925af 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
@@ -83,6 +83,11 @@
     public String getName() {
       return InspectionGadgetsBundle.message("string.concatenation.argument.to.log.call.quickfix");
     }
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
index bae94a9..a8b5918 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
@@ -69,6 +69,12 @@
       replacementText = getCollectionsMethodCallText(referenceName);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace Collections.EMPTY_* with call";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java
index c2f2797..8c371e6 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/EnumerationCanBeIterationInspection.java
@@ -78,6 +78,11 @@
 
   private static class EnumerationCanBeIterationFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
index e2fadba..edfc882 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
@@ -90,6 +90,12 @@
 
     @Override
     @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
+    @Override
+    @NotNull
     public String getName() {
       return InspectionGadgetsBundle.message("foreach.replace.quickfix");
     }
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
index c367688..08ea823 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
@@ -151,6 +151,12 @@
       myMinimumBranches = minimumBranches;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
index 0b7d10c..bd7acc8 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
@@ -118,6 +118,13 @@
       return InspectionGadgetsBundle.message(
         "replace.indexof.with.contains.quickfix");
     }
+
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
+
   }
 
   static String createContainsExpressionText(
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
index f4ea3c7..175b0ef 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
@@ -68,6 +68,11 @@
   }
 
   private static class MethodCanBeVariableArityMethodFix extends InspectionGadgetsFix {
+       @Override
+  @NotNull
+  public String getFamilyName() {
+    return getName();
+  }
 
     @NotNull
     @Override
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java
index d5a3e81..33b1a94 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java
@@ -94,6 +94,12 @@
       return InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.builder.replace.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiElement element = descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
index f7691a0..804a290 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
@@ -66,6 +66,11 @@
   private static class TryFinallyCanBeTryWithResourcesFix extends InspectionGadgetsFix {
 
     public TryFinallyCanBeTryWithResourcesFix() {}
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryWithIdenticalCatchesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryWithIdenticalCatchesInspection.java
index 84dfad8..865e229 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryWithIdenticalCatchesInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryWithIdenticalCatchesInspection.java
@@ -171,6 +171,12 @@
       return InspectionGadgetsBundle.message("try.with.identical.catches.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
       final PsiCatchSection section = (PsiCatchSection)descriptor.getPsiElement();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
index 62cfc32ed..2b1551e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
@@ -72,6 +72,11 @@
   }
 
   private static class UnnecessaryBoxingFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
index 47f47e9..d3acf7d 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
@@ -89,6 +89,12 @@
         "unnecessary.unboxing.remove.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
index b659021e..676ab05 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
@@ -69,6 +69,11 @@
   }
 
   private static class WhileCanBeForeachFix extends InspectionGadgetsFix {
+     @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/MethodNameSameAsClassNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/MethodNameSameAsClassNameInspection.java
index b3a17c1..09896b6 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/MethodNameSameAsClassNameInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/MethodNameSameAsClassNameInspection.java
@@ -74,6 +74,12 @@
       return InspectionGadgetsBundle.message("make.method.ctr.quickfix");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/NonExceptionNameEndsWithExceptionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/NonExceptionNameEndsWithExceptionInspection.java
index 76586bb..fdd4c99 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/NonExceptionNameEndsWithExceptionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/NonExceptionNameEndsWithExceptionInspection.java
@@ -76,6 +76,12 @@
         "non.exception.name.ends.with.exception.quickfix", name);
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Make class extend 'Exception'";
+    }
+
     @Override
     protected void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java
index 8cbe625..213c92e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/DynamicRegexReplaceableByCompiledPatternInspection.java
@@ -72,6 +72,11 @@
   }
 
   private static class DynamicRegexReplaceableByCompiledPatternFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
index ed3f5bf..7a85f27 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
@@ -65,6 +65,11 @@
 
   private static class ToArrayCallWithZeroLengthArrayArgumentFix extends InspectionGadgetsFix {
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/ExternalizableWithoutPublicNoArgConstructorInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/ExternalizableWithoutPublicNoArgConstructorInspection.java
index b46228a..9aa0753 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/ExternalizableWithoutPublicNoArgConstructorInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/ExternalizableWithoutPublicNoArgConstructorInspection.java
@@ -84,6 +84,12 @@
       return InspectionGadgetsBundle.message("make.constructor.public");
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return getName();
+    }
+
     @Override
     public void doFix(Project project, ProblemDescriptor descriptor)
       throws IncorrectOperationException {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspection.java
index 2a0ff2c0..e2c4270 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspection.java
@@ -84,6 +84,11 @@
 
   private static class SizeReplaceableByIsEmptyFix
     extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
index 17e8ea6..7f8c724 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
@@ -84,6 +84,12 @@
       this.inSameFile = inSameFile;
     }
 
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace fully qualified name";
+    }
+
     @Override
     @NotNull
     public String getName() {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
index f005ed0..0308ac4 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
@@ -64,6 +64,11 @@
   }
 
   private static class UnqualifiedInnerClassAccessFix extends InspectionGadgetsFix {
+    @Override
+    @NotNull
+    public String getFamilyName() {
+      return getName();
+    }
 
     @Override
     @NotNull
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html
new file mode 100644
index 0000000..5653cda
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BooleanParameter.html
@@ -0,0 +1,14 @@
+<html>
+<body>
+It's almost always a mistake to add a <b>boolean</b> parameter to a public method (part of an API) if that method is not a setter.
+When reading code using such a method, it can be difficult to decipher what the <b>boolean</b> stands for without looking at
+the source or documentation.
+This problem is also known as <a href="http://ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html">the boolean trap</a>.
+The <b>boolean</b> parameter can often be profitably replaced with an <b>enum</b>
+<!-- tooltip end -->
+<p>
+Use the option below to only warn when a method contains more than one boolean parameter.
+<p>
+<small>New in 13</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/ChannelResourceInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/ChannelResourceInspection.java
deleted file mode 100644
index c11d447..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/ChannelResourceInspection.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.siyeh.igtest.resources;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.io.*;
-import java.net.Socket;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.net.ServerSocket;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.FileChannel;
-
-public class ChannelResourceInspection {
-
-    public void foo2() throws IOException {
-        ServerSocket serverSocket = new ServerSocket(1, 1);
-        serverSocket.getChannel();
-        try {
-
-        } finally {
-            serverSocket.close();
-        }
-    }
-
-    public void foo3() throws IOException {
-        ServerSocket serverSocket = null;
-        serverSocket = new ServerSocket(1, 1);
-        ServerSocketChannel channel = serverSocket.getChannel();
-        try {
-        } finally {
-            serverSocket.close();
-        }
-    }
-
-    public void foo4() throws IOException {
-        ServerSocket serverSocket = null;
-        serverSocket = new ServerSocket(1, 1);
-        ServerSocketChannel channel = serverSocket.getChannel();
-        try {
-            channel.close();
-        } finally {
-            serverSocket.close();
-        }
-    }
-
-    public void foo5() throws IOException {
-        ServerSocket serverSocket = null;
-        ServerSocketChannel channel = null;
-        serverSocket = new ServerSocket(1, 1);
-        channel = serverSocket.getChannel();
-        try {
-            // do stuff
-        } finally {
-            channel.close();
-            serverSocket.close();
-        }
-    }
-
-    public static void copyFile(@NotNull File from, @NotNull File to)
-            throws IOException {
-        if (from.getCanonicalPath().equals(to.getCanonicalPath()))
-            return;
-        final FileInputStream inStream = new FileInputStream(from);
-        try {
-            boolean success = false;
-            try {
-                final FileOutputStream outStream = new FileOutputStream(to);
-                try {
-                    final FileChannel inChannel = inStream.getChannel();
-                    try {
-                        final FileChannel outChannel = outStream.getChannel();
-                        try {
-                            inChannel.transferTo(0, inChannel.size(), outChannel);
-                        }
-                        finally {
-                            outChannel.close();
-                        }
-                    }
-                    finally {
-                        inChannel.close();
-                    }
-                }
-                finally {
-                    outStream.close();
-                }
-                //copyLastModifiedDate( from, to );
-                success = true;
-            }
-            finally {
-                if (!success)
-                    to.delete();
-            }
-        }
-        finally {
-            inStream.close();
-        }
-    }
-
-    public static void copy(FileInputStream source,
-                            FileOutputStream target)
-            throws IOException {
-        FileChannel sourceChannel = source.getChannel(); // line 4
-        FileChannel targetChannel = target.getChannel(); // line 5
-        try {
-            sourceChannel.transferTo(0, sourceChannel.size(),
-                    targetChannel);
-        }
-        finally {
-            try {
-                targetChannel.close();
-            }
-            finally {
-                sourceChannel.close();
-            }
-        }
-    }
-
-    public static void copyFile2(File source, File target)
-            throws IOException {
-        final FileInputStream sourceStream = new FileInputStream(source);
-        try {
-            final FileOutputStream targetStream =
-                    new FileOutputStream(target);
-            try {
-                copy(sourceStream, targetStream);
-            }
-            finally {
-                targetStream.close();
-            }
-        }
-        finally {
-            sourceStream.close();
-        }
-    }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java
deleted file mode 100644
index c00cf70..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package com.siyeh.igtest.resources;
-
-import java.sql.*;
-
-public class JDBCResourceInspection {
-    private Driver driver;
-
-    public void foo() throws SQLException {
-        Connection connection = null;
-        try {
-            connection = driver.connect("foo", null);
-        } finally {
-            connection.close();
-        }
-
-    }
-
-    public void foo2() throws SQLException {
-        Connection connection = null;
-        try {
-            connection = driver.connect("foo", null);
-        } finally {
-        }
-    }
-
-
-    public void foo3() throws SQLException {
-        Connection connection = null;
-        try {
-            connection = driver.connect("foo", null);
-            connection.createStatement();
-        } finally {
-            connection.close();
-        }
-
-    }
-
-    public void foo4() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.createStatement();
-        } finally {
-            connection.close();
-        }
-
-    }
-
-    public void foo5() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.createStatement();
-        } finally {
-            statement.close();
-            connection.close();
-        }
-
-    }
-
-    public void foo6() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareStatement("foo");
-        } finally {
-            connection.close();
-        }
-
-    }
-
-    public void foo7() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareStatement("foo");
-        } finally {
-            statement.close();
-            connection.close();
-        }
-
-    }
-
-    public void foo8() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareCall("foo");
-        } finally {
-            connection.close();
-        }
-
-    }
-
-    public void foo9() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareCall("foo");
-        } finally {
-            statement.close();
-            connection.close();
-        }
-
-    }
-
-    public void foo10() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        ResultSet resultSet = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareCall("foo");
-            resultSet = statement.executeQuery("foo");
-        } finally {
-            statement.close();
-            connection.close();
-        }
-
-    }
-
-    public void foo11() throws SQLException {
-        Connection connection = null;
-        Statement statement = null;
-        ResultSet resultSet = null;
-        try {
-            connection = driver.connect("foo", null);
-            statement = connection.prepareCall("foo");
-            resultSet = statement.executeQuery("foo");
-        } finally {
-            resultSet.close();
-            statement.close();
-            connection.close();
-        }
-
-    }
-
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/SocketResourceInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/SocketResourceInspection.java
deleted file mode 100644
index a1097c1..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/SocketResourceInspection.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.siyeh.igtest.resources;
-
-import java.io.*;
-import java.net.Socket;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.net.ServerSocket;
-
-public class SocketResourceInspection {
-    public void foo() throws IOException, UnknownHostException {
-       new Socket( InetAddress.getLocalHost(), 1);
-    }
-
-    public void foo2() throws IOException, UnknownHostException {
-        final Socket socket = new Socket(InetAddress.getLocalHost(), 1);
-    }
-
-    public void foo25() throws IOException, UnknownHostException {
-        try {
-            final Socket socket = new Socket(InetAddress.getLocalHost(), 1);
-        } finally {
-        }
-
-    }
-
-
-    public void foo3() throws IOException {
-        final Socket socket = new Socket(InetAddress.getLocalHost(), 1);
-        socket.close();
-    }
-
-    public void foo4() throws IOException {
-        Socket socket = null;
-        try {
-            socket = new Socket(InetAddress.getLocalHost(), 1);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        socket.close();
-    }
-
-    public void foo5() throws IOException {
-        Socket socket = null;
-        try {
-            socket = new Socket(InetAddress.getLocalHost(), 1);
-        } finally {
-            socket.close();
-        }
-    }
-    public void foo6() throws IOException {
-        ServerSocket socket = null;
-        try{
-            socket = new ServerSocket(1, 1);
-        } finally{
-        }
-    }
-    public void foo7() throws IOException {
-        ServerSocket serverSocket = null;
-        try{
-            serverSocket = new ServerSocket(1, 1);
-            Socket socket = serverSocket.accept();
-        } finally{
-            serverSocket.close();
-        }
-    }
-
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/io/plain/IOResourceInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/io/plain/IOResourceInspection.java
index 74481e3..dacea83 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/io/plain/IOResourceInspection.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/io/plain/IOResourceInspection.java
@@ -158,4 +158,24 @@
       writer.close();
     }
   }
+
+  void escaper(InputStream in) {}
+
+  void escaped3() throws FileNotFoundException {
+    escaper(new FileInputStream(""));
+  }
+
+  void escaped4() throws FileNotFoundException {
+    class X {
+      X(InputStream s) {}
+    }
+    new X(new FileInputStream("")) {};
+    InputStream s = new FileInputStream("");
+    new X(s) {};
+  }
+
+  void escaped5() throws FileNotFoundException {
+    InputStream in = new FileInputStream("");
+    escaper(in);
+  }
 }
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_semicolon/UnnecessarySemicolonInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_semicolon/UnnecessarySemicolonInspection.java
index 13d978b4..67524e4 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_semicolon/UnnecessarySemicolonInspection.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_semicolon/UnnecessarySemicolonInspection.java
@@ -1,6 +1,6 @@
 
 package com.siyeh.igtest.style.unnecessary_semicolon;;
-;
+import java.util.List;;
 public class UnnecessarySemicolonInspection
 {
     int i;
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
index a76eb23..6f56e02 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
@@ -47,6 +47,14 @@
     myFixture.addClass(classText);
   }
 
+  protected final void doStatementTest(@Language(value="JAVA", prefix="class X { void m() {", suffix="}}") @NotNull @NonNls String statementText) {
+    doTest("class X { void m() {" + statementText + "}}");
+  }
+
+  protected final void doMemberTest(@Language(value="JAVA", prefix="class X {", suffix="}") @NotNull @NonNls String memberText) {
+    doTest("class X {" + memberText + "}");
+  }
+
   protected final void doTest(@Language("JAVA") @NotNull @NonNls String classText) {
     @NonNls final StringBuilder newText = new StringBuilder();
     int start = 0;
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java
new file mode 100644
index 0000000..4860377
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.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.siyeh.ig.abstraction;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class BooleanParameterInspectionTest extends LightInspectionTestCase {
+
+  public void testSimple() {
+    doTest("class X {" +
+           "  public void /*'public' method 'm' with 'boolean' parameter*/m/**/(boolean b) {}" +
+           "  public void n() {}" +
+           "  public void o(int i) {}" +
+           "  void p(boolean b) {}" +
+           "}");
+  }
+
+  @Override
+  protected LocalInspectionTool getInspection() {
+    return new BooleanParameterInspection();
+  }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspectionTest.java
new file mode 100644
index 0000000..71af30e
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ForLoopWithMissingComponentInspectionTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.controlflow;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ForLoopWithMissingComponentInspectionTest extends LightInspectionTestCase {
+
+  public void testMissingAllComponents() {
+    doStatementTest("/*'for' statement lacks initializer, condition and update*/for/**/ (;;) {}");
+  }
+
+  public void testMissingConditionAndUpdate() {
+    doStatementTest("/*'for' statement lacks condition and update*/for/**/ (int i = 0;;);");
+  }
+
+  public void testMissingInitializationAndUpdate() {
+    doStatementTest("/*'for' statement lacks initializer and update*/for/**/ (;true;);");
+  }
+
+  public void testMissingCondition() {
+    doStatementTest("/*'for' statement lacks condition*/for/**/ (int i = 0;;i++);");
+  }
+
+  public void testCorrect() {
+    doStatementTest("for(int i = 0;true;i++);");
+  }
+
+  public void testIterator() {
+    doMemberTest("void m(java.util.List l) {" +
+                 "  for (java.util.ListIterator it = l.listIterator(); it.hasNext();) {" +
+                 "    System.out.println(it.next());" +
+                 "  }" +
+                 "}");
+  }
+
+  @Override
+  protected LocalInspectionTool getInspection() {
+    final ForLoopWithMissingComponentInspection inspection = new ForLoopWithMissingComponentInspection();
+    inspection.ignoreCollectionLoops = true;
+    return inspection;
+  }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/ChannelResourceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/ChannelResourceInspectionTest.java
new file mode 100644
index 0000000..af6ade7
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/ChannelResourceInspectionTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.resources;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ChannelResourceInspectionTest extends LightInspectionTestCase {
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    addEnvironmentClass("package java.nio.channels;" +
+                        "public interface Channel extends java.io.Closeable {}");
+    addEnvironmentClass("package java.nio.channels;" +
+                        "public interface FileChannel extends Channel {}");
+    addEnvironmentClass("package java.net;" +
+                        "import java.nio.channels.FileChannel;" +
+                        "public class SocketInputStream implements java.io.Closeable {" +
+                        "  public FileChannel getChannel() {" +
+                        "    return null;" +
+                        "  }" +
+                        "  public void close() throws IOException {}" +
+                        "}");
+  }
+
+  public void testFactoryClosed() {
+    doTest("import java.net.*;" +
+           "import java.io.*;" +
+           "class X {" +
+           "  void m() throws IOException {" +
+           "    SocketInputStream ss = new SocketInputStream();" +
+           "    try {" +
+           "      ss.getChannel();" +
+           "    } finally {" +
+           "      ss.close();" +
+           "    }" +
+           "  }" +
+           "}");
+  }
+
+  public void testSimple() {
+    doTest("import java.net.*;" +
+           "import java.io.*;" +
+           "class X {" +
+           "  void m(SocketInputStream ss) throws IOException {" +
+           "    /*'FileChannel' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/ss.getChannel()/**/;" +
+           "  }" +
+           "}");
+  }
+
+  public void testChannelClosed() {
+    doTest("import java.net.*;" +
+           "import java.io.*;" +
+           "class X {" +
+           "  void m(SocketInputStream ss) throws IOException {" +
+           "    final Closeable channel = ss.getChannel();" +
+           "    try {" +
+           "      System.out.println();" +
+           "    } finally {" +
+           "      channel.close();" +
+           "    }" +
+           "  }" +
+           "}");
+  }
+
+  @Override
+  protected LocalInspectionTool getInspection() {
+    return new ChannelResourceInspection();
+  }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java
new file mode 100644
index 0000000..d834557
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.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.siyeh.ig.resources;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class JDBCResourceInspectionTest extends LightInspectionTestCase {
+
+  public void testCorrectClose() {
+    doTest("import java.sql.*;" +
+           "class X {" +
+           "    public void m(Driver driver) throws SQLException {" +
+           "        Connection connection = connection = driver.connect(\"foo\", null);\n" +
+           "        try {" +
+           "            System.out.println(connection);" +
+           "        } finally {" +
+           "            connection.close();" +
+           "        }" +
+           "    }" +
+           "}");
+  }
+
+  public void testARM() {
+    // doesn't work with mock jdk
+    /*doTest("import java.sql.*;" +
+           "class X {" +
+           "  void m(Driver driver) throws SQLException {" +
+           "    try (Connection connection = driver.connect(\"asdf\", null);" +
+           "      PreparedStatement statement = connection.prepareStatement(\"SELECT *\");" +
+           "      ResultSet resultSet = statement.executeQuery()) {" +
+           "      while (resultSet.next()) {" +
+           "      }" +
+           "    }" +
+           "  }" +
+           "}");*/
+  }
+
+  public void testSimple() {
+    doTest("import java.sql.*;" +
+           "class X {" +
+           "  void m(Driver driver) throws SQLException {" +
+           "    /*'Connection' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/driver.connect(\"asdf\", null)/**/;" +
+           "  }" +
+           "}");
+  }
+
+  @Override
+  protected LocalInspectionTool getInspection() {
+    return new JDBCResourceInspection();
+  }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/SocketResourceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/SocketResourceInspectionTest.java
new file mode 100644
index 0000000..4e3c856
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/SocketResourceInspectionTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.resources;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SocketResourceInspectionTest extends LightInspectionTestCase {
+
+  public void testNoCloseNoVar() {
+    doTest("import java.io.*;" +
+           "import java.net.*;" +
+           "class X {" +
+           "    public void m() throws IOException, UnknownHostException {" +
+           "       /*'Socket' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/new Socket( InetAddress.getLocalHost(), 1)/**/;" +
+           "    }" +
+           "}");
+  }
+
+  public void testNoClose() {
+    doTest("import java.io.*;" +
+           "import java.net.*;" +
+           "class X {" +
+           "    public void m() throws IOException, UnknownHostException {" +
+           "        final Socket socket = /*'Socket' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/new Socket(InetAddress.getLocalHost(), 1)/**/;" +
+           "    }" +
+           "}");
+  }
+
+  public void testTryNoClose() {
+    doTest("import java.io.*;" +
+           "import java.net.*;" +
+           "class X {" +
+           "    public void m() throws IOException, UnknownHostException {" +
+           "        try {" +
+           "            final Socket socket = /*'Socket' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/new Socket(InetAddress.getLocalHost(), 1)/**/;" +
+           "        } finally {" +
+           "        }" +
+           "    }" +
+           "}");
+  }
+
+  public void testImmediateClose() {
+    doTest("import java.io.*;" +
+           "import java.net.*;" +
+           "class X {" +
+           "    public void m() throws IOException {" +
+           "        final Socket socket = new Socket(InetAddress.getLocalHost(), 1);" +
+           "        socket.close();" +
+           "    }" +
+           "}");
+  }
+
+  public void testCorrectClose() {
+    doTest("import java.io.*;" +
+           "import java.net.*;" +
+           "class X {" +
+           "    public void m() throws IOException {" +
+           "        Socket socket = new Socket(InetAddress.getLocalHost(), 1);" +
+           "        try {" +
+           "        } finally {" +
+           "            socket.close();" +
+           "        }" +
+           "    }" +
+           "}");
+  }
+
+  @Override
+  protected LocalInspectionTool getInspection() {
+    return new SocketResourceInspection();
+  }
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/quickfix/AntUnresolvedRefsFixProvider.java b/plugins/ant/src/com/intellij/lang/ant/quickfix/AntUnresolvedRefsFixProvider.java
index 5df91b5..cf04053 100644
--- a/plugins/ant/src/com/intellij/lang/ant/quickfix/AntUnresolvedRefsFixProvider.java
+++ b/plugins/ant/src/com/intellij/lang/ant/quickfix/AntUnresolvedRefsFixProvider.java
@@ -28,7 +28,7 @@
  */
 public class AntUnresolvedRefsFixProvider extends UnresolvedReferenceQuickFixProvider<PsiReference> {
 
-  public void registerFixes(PsiReference ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull PsiReference ref, @NotNull QuickFixActionRegistrar registrar) {
     if (ref instanceof TagNameReference || ref instanceof AntDomReference) {
       registrar.register(new AntChangeContextFix());
     }
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java
index 4905c5b..21bf3e4 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java
@@ -121,6 +121,7 @@
     final Runnable[] resultRunnable = new Runnable[1];
 
     execute(new Runnable() {
+      @Override
       public void run() {
         try {
           resultRunnable[0] = preprocessFile(file);
@@ -130,6 +131,7 @@
         }
       }
     }, new Runnable() {
+      @Override
       public void run() {
         if (resultRunnable[0] != null) {
           resultRunnable[0].run();
@@ -182,6 +184,7 @@
     }
 
     return new Runnable() {
+      @Override
       public void run() {
         ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
         String msg = null;
@@ -219,10 +222,12 @@
   private void process(final PsiFile[] files) {
     final Runnable[] resultRunnable = new Runnable[1];
     execute(new Runnable() {
+      @Override
       public void run() {
         resultRunnable[0] = prepareFiles(new ArrayList<PsiFile>(Arrays.asList(files)));
       }
     }, new Runnable() {
+      @Override
       public void run() {
         if (resultRunnable[0] != null) {
           resultRunnable[0].run();
@@ -234,6 +239,7 @@
   private void process(final PsiDirectory dir, final boolean subdirs) {
     final List<PsiFile> pfiles = new ArrayList<PsiFile>();
     ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+      @Override
       public void run() {
         findFiles(pfiles, dir, subdirs);
       }
@@ -244,6 +250,7 @@
   private void process(final Project project) {
     final List<PsiFile> pfiles = new ArrayList<PsiFile>();
     ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+      @Override
       public void run() {
         findFiles(project, pfiles);
       }
@@ -254,6 +261,7 @@
   private void process(final Module module) {
     final List<PsiFile> pfiles = new ArrayList<PsiFile>();
     ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+      @Override
       public void run() {
         findFiles(module, pfiles);
       }
@@ -276,6 +284,7 @@
 
     for (VirtualFile root : roots) {
       idx.iterateContentUnderDirectory(root, new ContentIterator() {
+        @Override
         public boolean processFile(final VirtualFile dir) {
           if (dir.isDirectory()) {
             final PsiDirectory psiDir = PsiManager.getInstance(module.getProject()).findDirectory(dir);
@@ -299,10 +308,12 @@
       if (!files.isEmpty()) {
         final Runnable[] resultRunnable = new Runnable[1];
         execute(new Runnable() {
+          @Override
           public void run() {
             resultRunnable[0] = prepareFiles(files);
           }
         }, new Runnable() {
+          @Override
           public void run() {
             if (resultRunnable[0] != null) {
               resultRunnable[0].run();
@@ -335,11 +346,13 @@
 
   private void execute(final Runnable readAction, final Runnable writeAction) {
     ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+      @Override
       public void run() {
         readAction.run();
       }
     }, title, true, myProject);
     new WriteCommandAction(myProject, title) {
+      @Override
       protected void run(Result result) throws Throwable {
         writeAction.run();
       }
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java
index 2391a49..e147f35 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.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.
@@ -106,12 +106,14 @@
     myScopesLink.addHyperlinkListener(new HyperlinkListener() {
       public void hyperlinkUpdate(final HyperlinkEvent e) {
         if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
-          final DataContext dataContext = DataManager.getInstance().getDataContextFromFocus().getResult();
-          final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(dataContext);
-          if (optionsEditor != null) {
-            Configurable configurable = optionsEditor.findConfigurableById(ScopeChooserConfigurable.PROJECT_SCOPES);
-            if (configurable != null) {
-              optionsEditor.clearSearchAndSelect(configurable);
+          DataContext context = DataManager.getInstance().getDataContextFromFocus().getResult();
+          if (context != null) {
+            OptionsEditor optionsEditor = OptionsEditor.KEY.getData(context);
+            if (optionsEditor != null) {
+              Configurable configurable = optionsEditor.findConfigurableById(ScopeChooserConfigurable.PROJECT_SCOPES);
+              if (configurable != null) {
+                optionsEditor.clearSearchAndSelect(configurable);
+              }
             }
           }
         }
diff --git a/plugins/devkit/src/dom/impl/IdeaPluginConverter.java b/plugins/devkit/src/dom/impl/IdeaPluginConverter.java
index 94c6d83..60f72ac 100644
--- a/plugins/devkit/src/dom/impl/IdeaPluginConverter.java
+++ b/plugins/devkit/src/dom/impl/IdeaPluginConverter.java
@@ -22,6 +22,7 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.GlobalSearchScopesCore;
 import com.intellij.util.Function;
+import com.intellij.util.PlatformUtils;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.xml.ConvertContext;
 import com.intellij.util.xml.DomFileElement;
@@ -107,7 +108,8 @@
 
   public static Collection<IdeaPlugin> getAllPlugins(final Project project) {
     if (DumbService.isDumb(project)) return Collections.emptyList();
-    GlobalSearchScope scope = GlobalSearchScopesCore.projectProductionScope(project);
+    GlobalSearchScope scope = PlatformUtils.isIdeaProject(project) ?
+                              GlobalSearchScopesCore.projectProductionScope(project) : GlobalSearchScope.allScope(project);
     List<DomFileElement<IdeaPlugin>> files = DomService.getInstance().getFileElements(IdeaPlugin.class, project, scope);
     return ContainerUtil.map(files, new Function<DomFileElement<IdeaPlugin>, IdeaPlugin>() {
       public IdeaPlugin fun(DomFileElement<IdeaPlugin> ideaPluginDomFileElement) {
diff --git a/plugins/github/github.iml b/plugins/github/github.iml
index ea922cf..50d0f79 100644
--- a/plugins/github/github.iml
+++ b/plugins/github/github.iml
@@ -20,6 +20,8 @@
     <orderEntry type="library" name="gson" level="project" />
     <orderEntry type="module" module-name="dvcs" />
     <orderEntry type="module" module-name="testFramework" scope="TEST" />
+    <orderEntry type="module" module-name="xml-openapi" />
+    <orderEntry type="module" module-name="xml" />
   </component>
 </module>
 
diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml
index 86240aa..4af448e 100644
--- a/plugins/github/src/META-INF/plugin.xml
+++ b/plugins/github/src/META-INF/plugin.xml
@@ -19,6 +19,7 @@
 
     <applicationService serviceInterface="org.jetbrains.plugins.github.util.GithubSslSupport"
                         serviceImplementation="org.jetbrains.plugins.github.util.GithubSslSupport"/>
+    <webBrowserUrlProvider implementation="org.jetbrains.plugins.github.extensions.GithubWebBrowserUrlProvider"/>
   </extensions>
 
   <extensions defaultExtensionNs="Git4Idea">
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
index 4399bae..a633c5f 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
@@ -49,7 +49,7 @@
   public static final String CANNOT_OPEN_IN_BROWSER = "Cannot open in browser";
 
   protected GithubOpenInBrowserAction() {
-    super("Open in browser", "Open corresponding GitHub link in browser", GithubIcons.Github_icon);
+    super("Open on GitHub", "Open corresponding link in browser", GithubIcons.Github_icon);
   }
 
   @Override
@@ -92,51 +92,65 @@
   public void actionPerformed(final AnActionEvent e) {
     final Project project = e.getData(PlatformDataKeys.PROJECT);
     final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
+    final Editor editor = e.getData(PlatformDataKeys.EDITOR);
     if (virtualFile == null || project == null || project.isDisposed()) {
       return;
     }
 
+    String urlToOpen = getGithubUrl(project, virtualFile, editor, false);
+    if (urlToOpen != null) {
+      BrowserUtil.launchBrowser(urlToOpen);
+    }
+  }
+
+  @Nullable
+  public static String getGithubUrl(@NotNull Project project, @NotNull VirtualFile virtualFile, @Nullable Editor editor, boolean quiet) {
+
     GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
     final GitRepository repository = manager.getRepositoryForFile(virtualFile);
     if (repository == null) {
-      StringBuilder details = new StringBuilder("file: " + virtualFile.getPresentableUrl() + "; Git repositories: ");
-      for (GitRepository repo : manager.getRepositories()) {
-        details.append(repo.getPresentableUrl()).append("; ");
+      if (!quiet) {
+        StringBuilder details = new StringBuilder("file: " + virtualFile.getPresentableUrl() + "; Git repositories: ");
+        for (GitRepository repo : manager.getRepositories()) {
+          details.append(repo.getPresentableUrl()).append("; ");
+        }
+        showError(project, "Can't find git repository", details.toString(), quiet);
       }
-      GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find git repository", details.toString());
-      return;
+      return null;
     }
 
     final String githubRemoteUrl = GithubUtil.findGithubRemoteUrl(repository);
     if (githubRemoteUrl == null) {
-      GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find github remote");
-      return;
+      showError(project, "Can't find github remote", null, quiet);
+      return null;
     }
 
     final String rootPath = repository.getRoot().getPath();
     final String path = virtualFile.getPath();
     if (!path.startsWith(rootPath)) {
-      GithubNotifications
-        .showError(project, CANNOT_OPEN_IN_BROWSER, "File is not under repository root", "Root: " + rootPath + ", file: " + path);
-      return;
+      showError(project, "File is not under repository root", "Root: " + rootPath + ", file: " + path, quiet);
+      return null;
     }
 
-    String branch = getBranchNameOnRemote(project, repository);
+    String branch = getBranchNameOnRemote(project, repository, quiet);
     if (branch == null) {
-      return;
+      return null;
     }
 
     String relativePath = path.substring(rootPath.length());
-    String urlToOpen = makeUrlToOpen(e, relativePath, branch, githubRemoteUrl);
+    String urlToOpen = makeUrlToOpen(editor, relativePath, branch, githubRemoteUrl);
     if (urlToOpen == null) {
-      GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, "Can't create properly url", githubRemoteUrl);
-      return;
+      showError(project, "Can't create properly url", githubRemoteUrl, quiet);
+      return null;
     }
-    BrowserUtil.launchBrowser(urlToOpen);
+
+    return urlToOpen;
   }
 
   @Nullable
-  private static String makeUrlToOpen(@NotNull AnActionEvent e, @NotNull String relativePath, @NotNull String branch,
+  private static String makeUrlToOpen(@Nullable Editor editor,
+                                      @NotNull String relativePath,
+                                      @NotNull String branch,
                                       @NotNull String githubRemoteUrl) {
     final StringBuilder builder = new StringBuilder();
     final String githubRepoUrl = GithubUrlUtil.makeGithubRepoUrlFromRemoteUrl(githubRemoteUrl);
@@ -145,7 +159,6 @@
     }
     builder.append(githubRepoUrl).append("/blob/").append(branch).append(relativePath);
 
-    final Editor editor = e.getData(PlatformDataKeys.EDITOR);
     if (editor != null && editor.getDocument().getLineCount() >= 1) {
       // lines are counted internally from 0, but from 1 on github
       SelectionModel selectionModel = editor.getSelectionModel();
@@ -162,23 +175,31 @@
   }
 
   @Nullable
-  public static String getBranchNameOnRemote(@NotNull Project project, @NotNull GitRepository repository) {
+  public static String getBranchNameOnRemote(@NotNull Project project, @NotNull GitRepository repository, boolean quiet) {
     GitLocalBranch currentBranch = repository.getCurrentBranch();
     if (currentBranch == null) {
-      GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER,
-                                    "Can't open the file on GitHub when repository is on detached HEAD. Please checkout a branch.");
+      showError(project, "Can't open the file on GitHub when repository is on detached HEAD. Please checkout a branch.", null, quiet);
       return null;
     }
 
     GitRemoteBranch tracked = currentBranch.findTrackedBranch(repository);
     if (tracked == null) {
-      GithubNotifications
-        .showError(project, CANNOT_OPEN_IN_BROWSER, "Can't open the file on GitHub when current branch doesn't have a tracked branch.",
-                   "Current branch: " + currentBranch + ", tracked info: " + repository.getBranchTrackInfos());
+      showError(project, "Can't open the file on GitHub when current branch doesn't have a tracked branch.",
+                "Current branch: " + currentBranch + ", tracked info: " + repository.getBranchTrackInfos(), quiet);
       return null;
     }
 
     return tracked.getNameForRemoteOperations();
   }
 
+  private static void showError(@NotNull Project project, @NotNull String message, @Nullable String details, boolean quiet) {
+    if (!quiet) {
+      if (details == null) {
+        GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, message);
+      }
+      else {
+        GithubNotifications.showError(project, CANNOT_OPEN_IN_BROWSER, message, details);
+      }
+    }
+  }
 }
\ No newline at end of file
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
index 1dc7aad..607d9d9 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
@@ -32,7 +32,7 @@
 abstract class GithubShowCommitInBrowserAction extends DumbAwareAction {
 
   public GithubShowCommitInBrowserAction() {
-    super("Open in Browser", "Open the selected commit in browser", GithubIcons.Github_icon);
+    super("Open on GitHub", "Open the selected commit in browser", GithubIcons.Github_icon);
   }
 
   protected static void openInBrowser(Project project, GitRepository repository, String revisionHash) {
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 ba7a8cd..2f634d0 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
@@ -135,7 +135,7 @@
                                    @Nullable final String requestBody,
                                    @NotNull final Collection<Header> headers,
                                    @NotNull final HttpVerb verb) throws IOException {
-    HttpClient client = getHttpClient(auth.getBasicAuth());
+    HttpClient client = getHttpClient(auth.getBasicAuth(), auth.isUseProxy());
     return GithubSslSupport.getInstance()
       .executeSelfSignedCertificateAwareRequest(client, uri, new ThrowableConvertor<String, HttpMethod, IOException>() {
         @Override
@@ -173,7 +173,7 @@
   }
 
   @NotNull
-  private static HttpClient getHttpClient(@Nullable GithubAuthData.BasicAuth basicAuth) {
+  private static HttpClient getHttpClient(@Nullable GithubAuthData.BasicAuth basicAuth, boolean useProxy) {
     final HttpClient client = new HttpClient();
     HttpConnectionManagerParams params = client.getHttpConnectionManager().getParams();
     params.setConnectionTimeout(CONNECTION_TIMEOUT); //set connection timeout (how long it takes to connect to remote host)
@@ -182,7 +182,7 @@
     client.getParams().setContentCharset("UTF-8");
     // Configure proxySettings if it is required
     final HttpConfigurable proxySettings = HttpConfigurable.getInstance();
-    if (proxySettings.USE_HTTP_PROXY && !StringUtil.isEmptyOrSpaces(proxySettings.PROXY_HOST)) {
+    if (useProxy && proxySettings.USE_HTTP_PROXY && !StringUtil.isEmptyOrSpaces(proxySettings.PROXY_HOST)) {
       client.getHostConfiguration().setProxy(proxySettings.PROXY_HOST, proxySettings.PROXY_PORT);
       if (proxySettings.PROXY_AUTHENTICATION) {
         client.getState().setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxySettings.PROXY_LOGIN,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java
index d970771..ad34cbd 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java
@@ -23,8 +23,8 @@
  * @author Aleksey Pivovarov
  */
 public class GithubAuthorization {
-  @NotNull private String myToken;
-  @NotNull private List<String> myScopes;
+  @NotNull private final String myToken;
+  @NotNull private final List<String> myScopes;
 
   public GithubAuthorization(@NotNull String token, @NotNull List<String> scopes) {
     myToken = token;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java
index 1639862..705cdbd 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java
@@ -25,10 +25,10 @@
  */
 @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
 class GithubAuthorizationRequest {
-  @NotNull List<String> scopes;
+  @NotNull private final List<String> scopes;
 
-  @Nullable String note;
-  @Nullable String noteUrl;
+  @Nullable private final String note;
+  @Nullable private final String noteUrl;
 
   public GithubAuthorizationRequest(@NotNull List<String> scopes, @Nullable String note, @Nullable String noteUrl) {
     this.scopes = scopes;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubBranch.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubBranch.java
index 792303f..cffb740 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubBranch.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubBranch.java
@@ -21,7 +21,7 @@
  * @author Aleksey Pivovarov
  */
 public class GithubBranch {
-  @NotNull private String name;
+  @NotNull private final String name;
 
   public GithubBranch(@NotNull String name) {
     this.name = name;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommit.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommit.java
index 30b2c1c..5504406 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommit.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommit.java
@@ -26,18 +26,18 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubCommit extends GithubCommitSha {
-  @Nullable private GithubUser myAuthor;
-  @Nullable private GithubUser myCommitter;
+  @Nullable private final GithubUser myAuthor;
+  @Nullable private final GithubUser myCommitter;
 
-  @NotNull private List<GithubCommitSha> myParents;
+  @NotNull private final List<GithubCommitSha> myParents;
 
-  @NotNull private GitCommit myCommit;
+  @NotNull private final GitCommit myCommit;
 
   public static class GitCommit {
-    @NotNull private String myMessage;
+    @NotNull private final String myMessage;
 
-    @NotNull private GitUser myAuthor;
-    @NotNull private GitUser myCommitter;
+    @NotNull private final GitUser myAuthor;
+    @NotNull private final GitUser myCommitter;
 
     public GitCommit(@NotNull String message, @NotNull GitUser author, @NotNull GitUser committer) {
       myMessage = message;
@@ -62,9 +62,9 @@
   }
 
   public static class GitUser {
-    @NotNull private String myName;
-    @NotNull private String myEmail;
-    @NotNull private Date myDate;
+    @NotNull private final String myName;
+    @NotNull private final String myEmail;
+    @NotNull private final Date myDate;
 
     public GitUser(@NotNull String name, @NotNull String email, @NotNull Date date) {
       myName = name;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitDetailed.java
index 1e56225..92cd674 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitDetailed.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitDetailed.java
@@ -25,13 +25,13 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubCommitDetailed extends GithubCommit {
-  @NotNull private CommitStats myStats;
-  @NotNull private List<GithubFile> myFiles;
+  @NotNull private final CommitStats myStats;
+  @NotNull private final List<GithubFile> myFiles;
 
   public static class CommitStats {
-    private int myAdditions;
-    private int myDeletions;
-    private int myTotal;
+    private final int myAdditions;
+    private final int myDeletions;
+    private final int myTotal;
 
     public CommitStats(int additions, int deletions, int total) {
       myAdditions = additions;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitSha.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitSha.java
index 83b89df..f79e6bc 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitSha.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubCommitSha.java
@@ -22,8 +22,8 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubCommitSha {
-  @NotNull private String myUrl;
-  @NotNull private String mySha;
+  @NotNull private final String myUrl;
+  @NotNull private final String mySha;
 
   public GithubCommitSha(@NotNull String url, @NotNull String sha) {
     myUrl = url;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubFile.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubFile.java
index ea91051..73efe26 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubFile.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubFile.java
@@ -22,15 +22,15 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubFile {
-  @NotNull private String myFilename;
+  @NotNull private final String myFilename;
 
-  private int myAdditions;
-  private int myDeletions;
-  private int myChanges;
-  @NotNull private String myStatus;
+  private final int myAdditions;
+  private final int myDeletions;
+  private final int myChanges;
+  @NotNull private final String myStatus;
 
-  @NotNull private String myRawUrl;
-  @NotNull private String myPatch;
+  @NotNull private final String myRawUrl;
+  @NotNull private final String myPatch;
 
   public GithubFile(@NotNull String filename, int additions,
                      int deletions,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubFullPath.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubFullPath.java
index fb7d6e6..7488c17 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubFullPath.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubFullPath.java
@@ -21,8 +21,8 @@
 * @author Aleksey Pivovarov
 */
 public class GithubFullPath {
-  @NotNull final private String myUserName;
-  @NotNull final private String myRepositoryName;
+  @NotNull private final String myUserName;
+  @NotNull private final String myRepositoryName;
 
   public GithubFullPath(@NotNull String userName, @NotNull String repositoryName) {
     myUserName = userName;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubGist.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubGist.java
index 5ff4d35..4f2deb9 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubGist.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubGist.java
@@ -26,22 +26,22 @@
  * @author Aleksey Pivovarov
  */
 public class GithubGist {
-  @NotNull private String myId;
-  @NotNull private String myDescription;
+  @NotNull private final String myId;
+  @NotNull private final String myDescription;
 
-  private boolean myIsPublic;
+  private final boolean myIsPublic;
 
-  @NotNull private String myHtmlUrl;
+  @NotNull private final String myHtmlUrl;
 
-  @NotNull private List<GistFile> myFiles;
+  @NotNull private final List<GistFile> myFiles;
 
-  @Nullable private GithubUser myUser;
+  @Nullable private final GithubUser myUser;
 
   public static class GistFile {
-    @NotNull private String myFilename;
-    @NotNull private String myContent;
+    @NotNull private final String myFilename;
+    @NotNull private final String myContent;
 
-    @NotNull private String myRawUrl;
+    @NotNull private final String myRawUrl;
 
     public GistFile(@NotNull String filename, @NotNull String content, @NotNull String rawUrl) {
       myFilename = filename;
@@ -118,8 +118,8 @@
   }
 
   public static class FileContent {
-    @NotNull private String myFileName;
-    @NotNull private String myContent;
+    @NotNull private final String myFileName;
+    @NotNull private final String myContent;
 
     public FileContent(@NotNull String fileName, @NotNull String content) {
       myFileName = fileName;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubGistRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubGistRequest.java
index 23bd291..fe0f49b 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubGistRequest.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubGistRequest.java
@@ -25,16 +25,16 @@
 /**
  * @author Aleksey Pivovarov
  */
-@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration", "MismatchedQueryAndUpdateOfCollection"})
 class GithubGistRequest {
-  @NotNull private String description;
-  @NotNull private Map<String, GistFile> files;
+  @NotNull private final String description;
+  @NotNull private final Map<String, GistFile> files;
 
   @SerializedName("public")
-  private boolean isPublic;
+  private final boolean isPublic;
 
   public static class GistFile {
-    @NotNull private String content;
+    @NotNull private final String content;
 
     public GistFile(@NotNull String content) {
       this.content = content;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssue.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssue.java
index 771dc5c..f521548 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssue.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssue.java
@@ -25,18 +25,18 @@
  * @author Aleksey Pivovarov
  */
 public class GithubIssue {
-  @NotNull private String myHtmlUrl;
-  private long myNumber;
-  @NotNull private String myState;
-  @NotNull private String myTitle;
-  @NotNull private String myBody;
+  @NotNull private final String myHtmlUrl;
+  private final long myNumber;
+  @NotNull private final String myState;
+  @NotNull private final String myTitle;
+  @NotNull private final String myBody;
 
-  @NotNull private GithubUser myUser;
-  @Nullable private GithubUser myAssignee;
+  @NotNull private final GithubUser myUser;
+  @Nullable private final GithubUser myAssignee;
 
-  @Nullable Date myClosedAt;
-  @NotNull Date myCreatedAt;
-  @NotNull Date myUpdatedAt;
+  @Nullable private final Date myClosedAt;
+  @NotNull private final Date myCreatedAt;
+  @NotNull private final Date myUpdatedAt;
 
   public GithubIssue(@NotNull String htmlUrl,
                      long number,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssueComment.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssueComment.java
index 5faf9a4..da17175 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssueComment.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssueComment.java
@@ -23,15 +23,15 @@
  * @author Aleksey Pivovarov
  */
 public class GithubIssueComment {
-  private long myId;
+  private final long myId;
 
-  @NotNull private String myHtmlUrl;
-  @NotNull private String myBodyHtml;
+  @NotNull private final String myHtmlUrl;
+  @NotNull private final String myBodyHtml;
 
-  @NotNull private Date myCreatedAt;
-  @NotNull private Date myUpdatedAt;
+  @NotNull private final Date myCreatedAt;
+  @NotNull private final Date myUpdatedAt;
 
-  @NotNull private GithubUser myUser;
+  @NotNull private final GithubUser myUser;
 
   public GithubIssueComment(long id,
                             @NotNull String htmlUrl,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResult.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResult.java
index b129b2c..d79be87 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResult.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResult.java
@@ -24,7 +24,7 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubIssuesSearchResult {
-  @NotNull private List<GithubIssue> issues;
+  @NotNull private final List<GithubIssue> issues;
 
   public GithubIssuesSearchResult(@NotNull List<GithubIssue> issues) {
     this.issues = issues;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResultRaw.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResultRaw.java
index 7656832c..ebe816c 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResultRaw.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubIssuesSearchResultRaw.java
@@ -16,6 +16,7 @@
 package org.jetbrains.plugins.github.api;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -23,9 +24,9 @@
 /**
  * @author Aleksey Pivovarov
  */
-@SuppressWarnings("UnusedDeclaration")
+@SuppressWarnings({"UnusedDeclaration", "ConstantConditions"})
 class GithubIssuesSearchResultRaw implements DataConstructor {
-  List<GithubIssueRaw> items;
+  @Nullable public List<GithubIssueRaw> items;
 
   @NotNull
   GithubIssuesSearchResult createIssueSearchResult() {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubOrg.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubOrg.java
index 7a691fb..029c8aa5 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubOrg.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubOrg.java
@@ -21,7 +21,7 @@
  * @author Aleksey Pivovarov
  */
 public class GithubOrg {
-  @NotNull String myLogin;
+  @NotNull private final String myLogin;
 
   public GithubOrg(@NotNull String login) {
     myLogin = login;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequest.java
index 1a8facb..66794de 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequest.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequest.java
@@ -26,33 +26,33 @@
  */
 @SuppressWarnings("UnusedDeclaration")
 public class GithubPullRequest {
-  private long myNumber;
-  @NotNull private String myState;
-  @NotNull private String myTitle;
-  @NotNull private String myBodyHtml;
+  private final long myNumber;
+  @NotNull private final String myState;
+  @NotNull private final String myTitle;
+  @NotNull private final String myBodyHtml;
 
-  @NotNull private String myHtmlUrl;
-  @NotNull private String myDiffUrl;
-  @NotNull private String myPatchUrl;
-  @NotNull private String myIssueUrl;
+  @NotNull private final String myHtmlUrl;
+  @NotNull private final String myDiffUrl;
+  @NotNull private final String myPatchUrl;
+  @NotNull private final String myIssueUrl;
 
-  @NotNull private Date myCreatedAt;
-  @NotNull private Date myUpdatedAt;
-  @Nullable private Date myClosedAt;
-  @Nullable private Date myMergedAt;
+  @NotNull private final Date myCreatedAt;
+  @NotNull private final Date myUpdatedAt;
+  @Nullable private final Date myClosedAt;
+  @Nullable private final Date myMergedAt;
 
-  @NotNull private GithubUser myUser;
+  @NotNull private final GithubUser myUser;
 
-  @NotNull private Link myHead;
-  @NotNull private Link myBase;
+  @NotNull private final Link myHead;
+  @NotNull private final Link myBase;
 
   public static class Link {
-    @NotNull private String myLabel;
-    @NotNull private String myRef;
-    @NotNull private String mySha;
+    @NotNull private final String myLabel;
+    @NotNull private final String myRef;
+    @NotNull private final String mySha;
 
-    @NotNull private GithubRepo myRepo;
-    @NotNull private GithubUser myUser;
+    @NotNull private final GithubRepo myRepo;
+    @NotNull private final GithubUser myUser;
 
     public Link(@NotNull String label, @NotNull String ref, @NotNull String sha, @NotNull GithubRepo repo, @NotNull GithubUser user) {
       myLabel = label;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequestRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequestRequest.java
index 4465f08..845e743 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequestRequest.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubPullRequestRequest.java
@@ -20,11 +20,12 @@
 /**
  * @author Aleksey Pivovarov
  */
+@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
 class GithubPullRequestRequest {
-  @NotNull String title;
-  @NotNull String body;
-  @NotNull String head; // branch with changes
-  @NotNull String base; // branch requested to
+  @NotNull private final String title;
+  @NotNull private final String body;
+  @NotNull private final String head; // branch with changes
+  @NotNull private final String base; // branch requested to
 
   public GithubPullRequestRequest(@NotNull String title, @NotNull String description, @NotNull String head, @NotNull String base) {
     this.title = title;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepo.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepo.java
index 047562d..867079b 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepo.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepo.java
@@ -23,18 +23,18 @@
  * @author Aleksey Pivovarov
  */
 public class GithubRepo {
-  @NotNull private String myName;
-  @NotNull private String myDescription;
+  @NotNull private final String myName;
+  @NotNull private final String myDescription;
 
-  private boolean myIsPrivate;
-  private boolean myIsFork;
+  private final boolean myIsPrivate;
+  private final boolean myIsFork;
 
-  @NotNull private String myHtmlUrl;
-  @NotNull private String myCloneUrl;
+  @NotNull private final String myHtmlUrl;
+  @NotNull private final String myCloneUrl;
 
-  @Nullable private String myDefaultBranch;
+  @Nullable private final String myDefaultBranch;
 
-  @NotNull private GithubUser myOwner;
+  @NotNull private final GithubUser myOwner;
 
   public GithubRepo(@NotNull String name,
                     @Nullable String description,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoDetailed.java
index a9e1a69..16f73ca 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoDetailed.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoDetailed.java
@@ -22,8 +22,8 @@
  * @author Aleksey Pivovarov
  */
 public class GithubRepoDetailed extends GithubRepo {
-  @Nullable private GithubRepo myParent;
-  @Nullable private GithubRepo mySource;
+  @Nullable private final GithubRepo myParent;
+  @Nullable private final GithubRepo mySource;
 
   public GithubRepoDetailed(@NotNull String name,
                             @Nullable String description,
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoOrg.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoOrg.java
index fda0462..5a317b2e 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoOrg.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoOrg.java
@@ -21,13 +21,14 @@
 /**
  * @author Aleksey Pivovarov
  */
+@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
 public class GithubRepoOrg extends GithubRepo {
-  @NotNull Permissions myPermissions;
+  @NotNull private final Permissions myPermissions;
 
   public static class Permissions {
-    private boolean myAdmin;
-    private boolean myPull;
-    private boolean myPush;
+    private final boolean myAdmin;
+    private final boolean myPull;
+    private final boolean myPush;
 
     public Permissions(boolean admin, boolean pull, boolean push) {
       myAdmin = admin;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoRequest.java
index fbd0377..9eb5cc45 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoRequest.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubRepoRequest.java
@@ -23,10 +23,10 @@
  */
 @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
 class GithubRepoRequest {
-  @NotNull String name;
-  @NotNull String description;
+  @NotNull private final String name;
+  @NotNull private final String description;
 
-  @SerializedName("public") boolean isPublic;
+  @SerializedName("public") private final boolean isPublic;
 
   GithubRepoRequest(@NotNull String name, @NotNull String description, boolean aPublic) {
     this.name = name;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java
index 07624a1..29ef1ac 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java
@@ -22,11 +22,11 @@
  * @author Aleksey Pivovarov
  */
 public class GithubUser {
-  @NotNull private String myLogin;
+  @NotNull private final String myLogin;
 
-  @NotNull private String myHtmlUrl;
+  @NotNull private final String myHtmlUrl;
 
-  @Nullable private String myGravatarId;
+  @Nullable private final String myGravatarId;
 
   public GithubUser(@NotNull String login, @NotNull String htmlUrl, @Nullable String gravatarId) {
     myLogin = login;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
index 74ab021..c56bb44 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
@@ -22,17 +22,17 @@
  * @author Aleksey Pivovarov
  */
 public class GithubUserDetailed extends GithubUser {
-  @Nullable private String myName;
-  @Nullable private String myEmail;
+  @Nullable private final String myName;
+  @Nullable private final String myEmail;
 
-  private int myOwnedPrivateRepos;
+  private final int myOwnedPrivateRepos;
 
-  @NotNull private String myType;
-  @NotNull private UserPlan myPlan;
+  @NotNull private final String myType;
+  @NotNull private final UserPlan myPlan;
 
   public static class UserPlan {
-    @NotNull private String myName;
-    private long myPrivateRepos;
+    @NotNull private final String myName;
+    private final long myPrivateRepos;
 
     public UserPlan(@NotNull String name, long privateRepos) {
       myName = name;
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java
new file mode 100644
index 0000000..bd3b42e
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubWebBrowserUrlProvider.java
@@ -0,0 +1,47 @@
+/*
+ * 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.extensions;
+
+import com.intellij.ide.browsers.Url;
+import com.intellij.ide.browsers.UrlImpl;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.github.GithubOpenInBrowserAction;
+
+/**
+ * @author Aleksey Pivovarov
+ */
+public class GithubWebBrowserUrlProvider extends WebBrowserUrlProvider {
+  @Nullable
+  @Override
+  public Url getUrl(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull VirtualFile virtualFile) throws BrowserException {
+    String url = GithubOpenInBrowserAction.getGithubUrl(element.getProject(), virtualFile, null, true);
+    if (url == null) {
+      return null;
+    }
+    return new UrlImpl(url, "https", null, null, null);
+  }
+
+  @Nullable
+  @Override
+  public String getOpenInBrowserActionText(@NotNull PsiFile file) {
+    return "Open on GitHub";
+  }
+}
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 4f46266..f4e4554 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java
@@ -18,6 +18,9 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 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.GithubStatusCodeException;
 import org.jetbrains.plugins.github.util.GithubAuthData;
 import org.jetbrains.plugins.github.util.GithubUtil;
 import org.jetbrains.plugins.github.api.GithubIssue;
@@ -81,7 +84,18 @@
 
   @Override
   public Task[] getIssues(@Nullable String query, int max, long since) throws Exception {
-    return getIssues(query);
+    try {
+      return getIssues(query);
+    }
+    catch (GithubAuthenticationException e) {
+      throw new Exception(e.getMessage(), e);
+    }
+    catch (GithubStatusCodeException e) {
+      throw new Exception(e.getMessage(), e);
+    }
+    catch (GithubJsonException e) {
+      throw new Exception("Bad response format", e);
+    }
   }
 
   @NotNull
@@ -269,7 +283,7 @@
   }
 
   private GithubAuthData getAuthData() {
-      return GithubAuthData.createTokenAuth(getUrl(), getToken());
+      return GithubAuthData.createTokenAuth(getUrl(), getToken(), isUseProxy());
   }
 
   @Override
@@ -287,6 +301,6 @@
 
   @Override
   protected int getFeatures() {
-    return BASIC_HTTP_AUTHORIZATION;
+    return super.getFeatures() | BASIC_HTTP_AUTHORIZATION;
   }
 }
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 fe63449..2a83c85 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -1,16 +1,16 @@
 package org.jetbrains.plugins.github.tasks;
 
 import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.tasks.config.BaseRepositoryEditor;
 import com.intellij.ui.DocumentAdapter;
 import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.components.JBTextField;
 import com.intellij.util.Consumer;
 import com.intellij.util.ThrowableConvertor;
 import com.intellij.util.ui.FormBuilder;
+import com.intellij.util.ui.GridBag;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.github.util.GithubAuthData;
@@ -31,25 +31,29 @@
  * @author Dennis.Ushakov
  */
 public class GithubRepositoryEditor extends BaseRepositoryEditor<GithubRepository> {
-  private JTextField myToken;
-  private JTextField myRepoName;
-  private JTextField myRepoAuthor;
+  private MyTextField myHost;
+  private MyTextField myRepoAuthor;
+  private MyTextField myRepoName;
+  private MyTextField myToken;
   private JButton myTokenButton;
-  private JBLabel myRepoAuthorLabel;
-  private JBLabel myRepoLabel;
+  private JBLabel myHostLabel;
+  private JBLabel myRepositoryLabel;
   private JBLabel myTokenLabel;
 
   public GithubRepositoryEditor(final Project project, final GithubRepository repository, Consumer<GithubRepository> changeListener) {
     super(project, repository, changeListener);
-    myUserNameText.setVisible(false);
+    myUrlLabel.setVisible(false);
+    myURLText.setVisible(false);
     myUsernameLabel.setVisible(false);
-    myPasswordText.setVisible(false);
+    myUserNameText.setVisible(false);
     myPasswordLabel.setVisible(false);
+    myPasswordText.setVisible(false);
     myUseHttpAuthenticationCheckBox.setVisible(false);
 
-    myToken.setText(repository.getToken());
+    myHost.setText(repository.getUrl());
     myRepoAuthor.setText(repository.getRepoAuthor());
     myRepoName.setText(repository.getRepoName());
+    myToken.setText(repository.getToken());
 
     DocumentListener buttonUpdater = new DocumentAdapter() {
       @Override
@@ -58,29 +62,36 @@
       }
     };
 
+    myHost.getDocument().addDocumentListener(buttonUpdater);
     myRepoAuthor.getDocument().addDocumentListener(buttonUpdater);
     myRepoName.getDocument().addDocumentListener(buttonUpdater);
     myURLText.getDocument().addDocumentListener(buttonUpdater);
-
-    setAnchor(myRepoAuthorLabel);
   }
 
   @Nullable
   @Override
   protected JComponent createCustomPanel() {
-    myUrlLabel.setText("Host:");
+    myHostLabel = new JBLabel("Host:", SwingConstants.RIGHT);
+    myHost = new MyTextField("Github host");
 
-    myRepoAuthorLabel = new JBLabel("Repository Owner:", SwingConstants.RIGHT);
-    myRepoAuthor = new JTextField();
-    installListener(myRepoAuthor);
+    JPanel myHostPanel = new JPanel(new BorderLayout(5, 0));
+    myHostPanel.add(myHost, BorderLayout.CENTER);
+    myHostPanel.add(myShareUrlCheckBox, BorderLayout.EAST);
 
-    myRepoLabel = new JBLabel("Repository:", SwingConstants.RIGHT);
-    myRepoName = new JTextField();
-    installListener(myRepoName);
+    myRepositoryLabel = new JBLabel("Repository:", SwingConstants.RIGHT);
+    myRepoAuthor = new MyTextField("Repository Owner");
+    myRepoName = new MyTextField("Repository Name");
+    myRepoAuthor.setPreferredSize("SomelongNickname");
+    myRepoName.setPreferredSize("SomelongReponame-with-suffixes");
+
+    JPanel myRepoPanel = new JPanel(new GridBagLayout());
+    GridBag bag = new GridBag().setDefaultWeightX(1).setDefaultFill(GridBagConstraints.HORIZONTAL);
+    myRepoPanel.add(myRepoAuthor, bag.nextLine().next());
+    myRepoPanel.add(new JLabel("/"), bag.next().fillCellNone().insets(0, 5, 0, 5).weightx(0));
+    myRepoPanel.add(myRepoName, bag.next());
 
     myTokenLabel = new JBLabel("API Token:", SwingConstants.RIGHT);
-    myToken = new JTextField();
-    installListener(myToken);
+    myToken = new MyTextField("OAuth2 token");
     myTokenButton = new JButton("Create API token");
     myTokenButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
@@ -94,8 +105,13 @@
     myTokenPanel.add(myToken, BorderLayout.CENTER);
     myTokenPanel.add(myTokenButton, BorderLayout.EAST);
 
-    return FormBuilder.createFormBuilder().setAlignLabelOnRight(true).addLabeledComponent(myRepoAuthorLabel, myRepoAuthor)
-      .addLabeledComponent(myRepoLabel, myRepoName).addLabeledComponent(myTokenLabel, myTokenPanel).getPanel();
+    installListener(myHost);
+    installListener(myRepoAuthor);
+    installListener(myRepoName);
+    installListener(myToken);
+
+    return FormBuilder.createFormBuilder().setAlignLabelOnRight(true).addLabeledComponent(myHostLabel, myHostPanel)
+      .addLabeledComponent(myRepositoryLabel, myRepoPanel).addLabeledComponent(myTokenLabel, myTokenPanel).getPanel();
   }
 
   @Override
@@ -133,8 +149,8 @@
   @Override
   public void setAnchor(@Nullable final JComponent anchor) {
     super.setAnchor(anchor);
-    myRepoAuthorLabel.setAnchor(anchor);
-    myRepoLabel.setAnchor(anchor);
+    myHostLabel.setAnchor(anchor);
+    myRepositoryLabel.setAnchor(anchor);
     myTokenLabel.setAnchor(anchor);
   }
 
@@ -149,9 +165,14 @@
     }
   }
 
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return myHost;
+  }
+
   @NotNull
   private String getHost() {
-    return myURLText.getText().trim();
+    return myHost.getText().trim();
   }
 
   @NotNull
@@ -168,4 +189,25 @@
   private String getToken() {
     return myToken.getText().trim();
   }
+
+  public static class MyTextField extends JBTextField {
+    private int myWidth = -1;
+
+    public MyTextField(@NotNull String hintCaption) {
+      getEmptyText().setText(hintCaption);
+    }
+
+    public void setPreferredSize(@NotNull String sampleSizeString) {
+      myWidth = getFontMetrics(getFont()).stringWidth(sampleSizeString);
+    }
+
+    @Override
+    public Dimension getPreferredSize() {
+      Dimension size = super.getPreferredSize();
+      if (myWidth != -1) {
+        size.width = myWidth;
+      }
+      return size;
+    }
+  }
 }
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 c0d2af8..b540bd9 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.github.ui.GithubSettingsPanel">
-  <grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+  <grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="4" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
       <xy x="20" y="20" width="563" height="400"/>
@@ -8,25 +8,9 @@
     <properties/>
     <border type="none"/>
     <children>
-      <component id="e76ec" class="javax.swing.JTextField" binding="myLoginTextField">
-        <constraints>
-          <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
-            <preferred-size width="150" height="-1"/>
-          </grid>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="c0234" class="javax.swing.JLabel" binding="myLoginLabel">
-        <constraints>
-          <grid row="1" 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="Login:"/>
-        </properties>
-      </component>
       <component id="28ddd" class="javax.swing.JTextPane" binding="mySignupTextField">
         <constraints>
-          <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
+          <grid row="2" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
             <preferred-size width="150" height="10"/>
           </grid>
         </constraints>
@@ -39,38 +23,23 @@
           <JEditorPane.honorDisplayProperties class="java.lang.Boolean" value="true"/>
         </clientProperties>
       </component>
-      <component id="9edbd" class="javax.swing.JPasswordField" binding="myPasswordField">
-        <constraints>
-          <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
-            <preferred-size width="150" height="-1"/>
-          </grid>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="8a6dd" class="javax.swing.JButton" binding="myTestButton" default-binding="true">
-        <constraints>
-          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text value="Test"/>
-        </properties>
-      </component>
       <vspacer id="6ace">
         <constraints>
-          <grid row="4" column="0" row-span="1" col-span="1" 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="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
-      <component id="45bab" class="javax.swing.JLabel">
+      <component id="45bab" class="com.intellij.ui.components.JBLabel">
         <constraints>
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
+          <anchor value="e4416"/>
           <text value="Host:"/>
         </properties>
       </component>
       <component id="3352a" class="javax.swing.JTextField" binding="myHostTextField">
         <constraints>
-          <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
             <preferred-size width="150" height="-1"/>
           </grid>
         </constraints>
@@ -78,10 +47,110 @@
       </component>
       <component id="5a680" class="com.intellij.openapi.ui.ComboBox" binding="myAuthTypeComboBox">
         <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" 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"/>
         </constraints>
         <properties/>
       </component>
+      <grid id="bda15" binding="myCardPanel" layout-manager="CardLayout" hgap="0" vgap="0">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <grid id="e4354" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <card name="Password"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="c0234" class="com.intellij.ui.components.JBLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <anchor value="e4416"/>
+                  <text value="Login:"/>
+                </properties>
+              </component>
+              <component id="e76ec" class="javax.swing.JTextField" binding="myLoginTextField">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+              <component id="e4416" class="com.intellij.ui.components.JBLabel">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Password:"/>
+                </properties>
+              </component>
+              <component id="9edbd" class="javax.swing.JPasswordField" binding="myPasswordField" custom-create="true">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+            </children>
+          </grid>
+          <grid id="6d9fb" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <card name="Token"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="3cdb8" class="com.intellij.ui.components.JBLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <anchor value="e4416"/>
+                  <text value="Token:"/>
+                </properties>
+              </component>
+              <component id="dd543" class="javax.swing.JPasswordField" binding="myTokenField" custom-create="true">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+              <vspacer id="21b9e">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </vspacer>
+            </children>
+          </grid>
+        </children>
+      </grid>
+      <component id="8a6dd" class="javax.swing.JButton" binding="myTestButton" default-binding="true">
+        <constraints>
+          <grid row="2" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="Test"/>
+        </properties>
+      </component>
+      <component id="b276a" class="com.intellij.ui.components.JBLabel">
+        <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>
+        <properties>
+          <text value="Auth Type:"/>
+        </properties>
+      </component>
     </children>
   </grid>
 </form>
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 b1f08bc..365fa2f 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.ui.DocumentAdapter;
 import com.intellij.ui.HyperlinkAdapter;
+import com.intellij.ui.components.JBLabel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.github.util.GithubAuthData;
@@ -35,6 +36,8 @@
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import javax.swing.event.HyperlinkEvent;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
 import java.awt.*;
 import java.awt.event.*;
 import java.io.IOException;
@@ -54,12 +57,13 @@
 
   private JTextField myLoginTextField;
   private JPasswordField myPasswordField;
+  private JPasswordField myTokenField;
   private JTextPane mySignupTextField;
   private JPanel myPane;
   private JButton myTestButton;
   private JTextField myHostTextField;
   private ComboBox myAuthTypeComboBox;
-  private JLabel myLoginLabel;
+  private JPanel myCardPanel;
 
   private boolean myCredentialsModified;
 
@@ -84,18 +88,18 @@
         try {
           GithubUser user = GithubUtil.checkAuthData(getAuthData());
           if (GithubAuthData.AuthType.TOKEN.equals(getAuthType())) {
-            GithubNotifications.showInfoDialog(myPane, "Connection successful for user " + user.getLogin(), "Success");
+            GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful for user " + user.getLogin());
           }
           else {
-            GithubNotifications.showInfoDialog(myPane, "Connection successful", "Success");
+            GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful");
           }
         }
         catch (GithubAuthenticationException ex) {
-          GithubNotifications.showErrorDialog(myPane, "Can't login using given credentials: " + ex.getMessage(), "Login Failure");
+          GithubNotifications.showErrorDialog(myPane, "Login Failure", "Can't login using given credentials: " + ex.getMessage());
         }
         catch (IOException ex) {
           LOG.info(ex);
-          GithubNotifications.showErrorDialog(myPane, "Can't login: " + GithubUtil.getErrorTextFromException(ex), "Login Failure");
+          GithubNotifications.showErrorDialog(myPane, "Login Failure", "Can't login: " + GithubUtil.getErrorTextFromException(ex));
         }
       }
     });
@@ -137,14 +141,11 @@
         if (e.getStateChange() == ItemEvent.SELECTED) {
           String item = e.getItem().toString();
           if (AUTH_PASSWORD.equals(item)) {
-            myLoginLabel.setVisible(true);
-            myLoginTextField.setVisible(true);
+            ((CardLayout)myCardPanel.getLayout()).show(myCardPanel, AUTH_PASSWORD);
           }
           else if (AUTH_TOKEN.equals(item)) {
-            myLoginLabel.setVisible(false);
-            myLoginTextField.setVisible(false);
+            ((CardLayout)myCardPanel.getLayout()).show(myCardPanel, AUTH_TOKEN);
           }
-          myPane.validate();
           erasePassword();
         }
       }
@@ -240,5 +241,10 @@
   public void resetCredentialsModification() {
     myCredentialsModified = false;
   }
-}
 
+  private void createUIComponents() {
+    Document doc = new PlainDocument();
+    myPasswordField = new JPasswordField(doc, null, 0);
+    myTokenField = new JPasswordField(doc, null, 0);
+  }
+}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
index 5de9a65..63e93a6 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
@@ -36,15 +36,19 @@
   @NotNull private final String myHost;
   @Nullable private final BasicAuth myBasicAuth;
   @Nullable private final TokenAuth myTokenAuth;
+  private final boolean myUseProxy;
+
 
   private GithubAuthData(@NotNull AuthType authType,
                          @NotNull String host,
                          @Nullable BasicAuth basicAuth,
-                         @Nullable TokenAuth tokenAuth) {
+                         @Nullable TokenAuth tokenAuth,
+                         boolean useProxy) {
     myAuthType = authType;
     myHost = host;
     myBasicAuth = basicAuth;
     myTokenAuth = tokenAuth;
+    myUseProxy = useProxy;
   }
 
   public static GithubAuthData createAnonymous() {
@@ -52,15 +56,19 @@
   }
 
   public static GithubAuthData createAnonymous(@NotNull String host) {
-    return new GithubAuthData(AuthType.ANONYMOUS, host, null, null);
+    return new GithubAuthData(AuthType.ANONYMOUS, host, null, null, true);
   }
 
   public static GithubAuthData createBasicAuth(@NotNull String host, @NotNull String login, @NotNull String password) {
-    return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password), null);
+    return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password), null, true);
   }
 
   public static GithubAuthData createTokenAuth(@NotNull String host, @NotNull String token) {
-    return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token));
+    return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token), true);
+  }
+
+  public static GithubAuthData createTokenAuth(@NotNull String host, @NotNull String token, boolean useProxy) {
+    return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token), useProxy);
   }
 
   @NotNull
@@ -83,6 +91,10 @@
     return myTokenAuth;
   }
 
+  public boolean isUseProxy() {
+    return myUseProxy;
+  }
+
   public static class BasicAuth {
     @NotNull private final String myLogin;
     @NotNull private final String myPassword;
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTest.java
index 0d24130..f8c9087 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTest.java
@@ -26,15 +26,9 @@
   public void testSimple() throws Exception {
     registerDefaultCreatePullRequestDialogHandler(myLogin1 + ":master");
 
-    cd(myProjectRoot.getPath());
-    cloneRepo();
-    createBranch();
-    createChanges();
-
     GithubCreatePullRequestAction.createPullRequest(myProject, myProjectRoot);
 
     checkNotification(NotificationType.INFORMATION, "Successfully created pull request", null);
-    initGitChecks();
     checkRemoteConfigured();
     checkLastCommitPushed();
   }
@@ -42,15 +36,9 @@
   public void testParent() throws Exception {
     registerDefaultCreatePullRequestDialogHandler(myLogin2 + ":file2");
 
-    cd(myProjectRoot.getPath());
-    cloneRepo();
-    createBranch();
-    createChanges();
-
     GithubCreatePullRequestAction.createPullRequest(myProject, myProjectRoot);
 
     checkNotification(NotificationType.INFORMATION, "Successfully created pull request", null);
-    initGitChecks();
     checkRemoteConfigured();
     checkLastCommitPushed();
   }
@@ -58,15 +46,9 @@
   public void testCommitRef1() throws Exception {
     registerDefaultCreatePullRequestDialogHandler(myLogin1 + ":refs/heads/master");
 
-    cd(myProjectRoot.getPath());
-    cloneRepo();
-    createBranch();
-    createChanges();
-
     GithubCreatePullRequestAction.createPullRequest(myProject, myProjectRoot);
 
     checkNotification(NotificationType.INFORMATION, "Successfully created pull request", null);
-    initGitChecks();
     checkRemoteConfigured();
     checkLastCommitPushed();
   }
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
index 5058513..24bb780 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java
@@ -30,6 +30,7 @@
 
 import java.util.Random;
 
+import static com.intellij.dvcs.test.Executor.cd;
 import static git4idea.test.GitExecutor.git;
 
 /**
@@ -48,6 +49,12 @@
     BRANCH_NAME = "branch_" + getTestName(false) + "_" + DateFormatUtil.formatDate(time).replace('/', '-') + "_" + rnd.nextLong();
 
     registerHttpAuthService();
+
+    cd(myProjectRoot.getPath());
+    cloneRepo();
+    createBranch();
+    createChanges();
+    initGitChecks();
   }
 
   @Override
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 a710fc8..37f38ea 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
@@ -246,18 +246,21 @@
 
   public void updateWrapperControls(@Nullable String linkedProjectPath) {
     if (linkedProjectPath != null && GradleUtil.isGradleWrapperDefined(linkedProjectPath)) {
-      myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper"));
       myUseWrapperButton.setEnabled(true);
+      myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper"));
       if (getInitialSettings().isPreferLocalInstallationToWrapper()) {
+        myGradleHomePathField.setEnabled(true);
         myUseLocalDistributionButton.setSelected(true);
       }
       else {
+        myGradleHomePathField.setEnabled(false);
         myUseWrapperButton.setSelected(true);
       }
     }
     else {
       myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.wrapper.disabled"));
       myUseWrapperButton.setEnabled(false);
+      myGradleHomePathField.setEnabled(true);
       myUseLocalDistributionButton.setSelected(true);
     }
   }
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
index bdf44b6..5fa7ca4 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
@@ -15,13 +15,15 @@
  */
 package org.jetbrains.plugins.gradle.service.task;
 
-import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
 import com.intellij.openapi.externalSystem.model.ExternalSystemException;
 import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
 import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
+import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.Function;
+import com.intellij.util.SystemProperties;
 import org.gradle.tooling.BuildLauncher;
 import org.gradle.tooling.ProjectConnection;
 import org.jetbrains.annotations.NotNull;
@@ -29,6 +31,8 @@
 import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper;
 import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -36,7 +40,7 @@
  * @since 3/14/13 5:09 PM
  */
 public class GradleTaskManager implements ExternalSystemTaskManager<GradleExecutionSettings> {
-  
+
   private final GradleExecutionHelper myHelper = new GradleExecutionHelper();
 
   @Override
@@ -45,21 +49,33 @@
                            @NotNull String projectPath,
                            @Nullable final GradleExecutionSettings settings,
                            @Nullable final String vmOptions,
-                           @NotNull final ExternalSystemTaskNotificationListener listener) throws ExternalSystemException
-  {
+                           @NotNull final ExternalSystemTaskNotificationListener listener) throws ExternalSystemException {
     Function<ProjectConnection, Void> f = new Function<ProjectConnection, Void>() {
       @Override
       public Void fun(ProjectConnection connection) {
         BuildLauncher launcher = myHelper.getBuildLauncher(id, connection, settings, listener);
         if (!StringUtil.isEmpty(vmOptions)) {
-          assert vmOptions != null;
-          launcher.setJvmArguments(vmOptions.trim());
+          try {
+            final File tempFile = FileUtil.createTempFile("init", ".gradle");
+            tempFile.deleteOnExit();
+            final String[] lines = {
+              "gradle.taskGraph.beforeTask { Task task ->",
+              "    if (task instanceof JavaForkOptions) {",
+              "        task.jvmArgs '" + vmOptions.trim() + '\'',
+              "}}",
+            };
+            FileUtil.writeToFile(tempFile, StringUtil.join(lines, SystemProperties.getLineSeparator()));
+            launcher.withArguments("--init-script", tempFile.getAbsolutePath());
+          }
+          catch (IOException e) {
+            throw new ExternalSystemException(e);
+          }
         }
         launcher.forTasks(ArrayUtil.toStringArray(taskNames));
         launcher.run();
         return null;
       }
     };
-    myHelper.execute(projectPath, settings, f); 
+    myHelper.execute(projectPath, settings, f);
   }
 }
diff --git a/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.ft b/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.ft
new file mode 100644
index 0000000..51bce14
--- /dev/null
+++ b/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.ft
@@ -0,0 +1 @@
+#if ( $RETURN_TYPE != "void" )$DEFAULT_RETURN_VALUE#end
\ No newline at end of file
diff --git a/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.html b/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.html
new file mode 100644
index 0000000..3dc9210
--- /dev/null
+++ b/plugins/groovy/resources/fileTemplates/code/New Method Body.groovy.html
@@ -0,0 +1,43 @@
+<html>
+<body>
+<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
+  <tr>
+    <td colspan="3"><font face="verdana" size="-1">This is a built-in template used for filling the body of a Groovy method
+      each time it is generated by the program, e.g. when using the <b>Create Method from Usage</b> intention action.<br>
+      The template is editable. Along with Groovy expressions and comments, you can also use the predefined variables
+      that will be then expanded into the corresponding values.</font>
+    </td>
+  </tr>
+</table>
+<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
+  <tr>
+    <td colspan="3"><font face="verdana" size="-1">Predefined variables will take the following values:</font></td>
+  </tr>
+  <tr>
+    <td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${RETURN_TYPE}</i></b></font></nobr></td>
+    <td width="10">&nbsp;</td>
+    <td valign="top"><font face="verdana" size="-1">a return type of a created method</font></td>
+  </tr>
+  <tr>
+    <td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${DEFAULT_RETURN_VALUE}</i></b></font></nobr></td>
+    <td width="10">&nbsp;</td>
+    <td valign="top"><font face="verdana" size="-1">a value returned by the method by default</font></td>
+  </tr>
+  <tr>
+    <td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${METHOD_NAME}</i></b></font></nobr></td>
+    <td width="10">&nbsp;</td>
+    <td valign="top"><font face="verdana" size="-1">name of the created method</font></td>
+  </tr>
+  <tr>
+    <td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${CLASS_NAME}</i></b></font></nobr></td>
+    <td width="10">&nbsp;</td>
+    <td valign="top"><font face="verdana" size="-1">qualified name of the class where method is created</font></td>
+  </tr>
+  <tr>
+    <td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${SIMPLE_CLASS_NAME}</i></b></font></nobr></td>
+    <td width="10">&nbsp;</td>
+    <td valign="top"><font face="verdana" size="-1">non-qualified name of the class where method is implemented</font></td>
+  </tr>
+</table>
+</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 1be7e595..65180b9 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -97,6 +97,7 @@
     <membersContributor implementation="org.jetbrains.plugins.groovy.geb.GebModuleMemberContributor"/>
 
     <membersContributor implementation="org.jetbrains.plugins.groovy.geb.GebJUnitTestMemberContributor"/>
+    <membersContributor implementation="org.jetbrains.plugins.groovy.geb.GebTestNGTestMemberContributor"/>
     <membersContributor implementation="org.jetbrains.plugins.groovy.geb.GebBrowserMemberContributor"/>
 
     <membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
@@ -433,6 +434,7 @@
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyLiteralSelectioner"/>
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyMembersWithDocSelectioner"/>
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyBlockStatementsSelectioner"/>
+    <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyTypeDefinitionBodySelectioner"/>
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyTypeCastSelectioner"/>
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyDocParamsSelectioner"/>
     <extendWordSelectionHandler implementation="org.jetbrains.plugins.groovy.editor.selection.GroovyArgListSelectioner"/>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GroovyTemplates.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GroovyTemplates.java
index 8f6d087..49875ce 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GroovyTemplates.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GroovyTemplates.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.
@@ -15,16 +15,22 @@
  */
 package org.jetbrains.plugins.groovy.actions;
 
+import org.jetbrains.annotations.NonNls;
+
 /**
  * @author Max Medvedev
  */
-public class GroovyTemplates {
-  public static final String GROOVY_CLASS = "GroovyClass.groovy";
-  public static final String GROOVY_INTERFACE = "GroovyInterface.groovy";
-  public static final String GROOVY_ENUM = "GroovyEnum.groovy";
-  public static final String GROOVY_ANNOTATION = "GroovyAnnotation.groovy";
-  public static final String GROOVY_SCRIPT = "GroovyScript.groovy";
-  public static final String GROOVY_DSL_SCRIPT = "GroovyDslScript.gdsl";
-  public static final String GANT_SCRIPT = "GantScript.gant";
-  public static final String GROOVY_SERVER_PAGE = "GroovyServerPage.gsp";
+public interface GroovyTemplates {
+  @NonNls String GROOVY_CLASS = "GroovyClass.groovy";
+  @NonNls String GROOVY_INTERFACE = "GroovyInterface.groovy";
+  @NonNls String GROOVY_ENUM = "GroovyEnum.groovy";
+  @NonNls String GROOVY_ANNOTATION = "GroovyAnnotation.groovy";
+  @NonNls String GROOVY_SCRIPT = "GroovyScript.groovy";
+  @NonNls String GROOVY_DSL_SCRIPT = "GroovyDslScript.gdsl";
+  @NonNls String GANT_SCRIPT = "GantScript.gant";
+  @NonNls String GROOVY_SERVER_PAGE = "GroovyServerPage.gsp";
+  @NonNls String GROOVY_FROM_USAGE_METHOD_BODY = "New Method Body.groovy";
+  @NonNls String GROOVY_JUNIT_TEST_METHOD_GROOVY = "Groovy JUnit Test Method.groovy";
+  @NonNls String GROOVY_JUNIT_SET_UP_METHOD_GROOVY = "Groovy JUnit SetUp Method.groovy";
+  @NonNls String GROOVY_JUNIT_TEAR_DOWN_METHOD_GROOVY = "Groovy JUnit TearDown Method.groovy";
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java
index fc1071d..d970970 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java
@@ -16,6 +16,7 @@
 package org.jetbrains.plugins.groovy.annotator;
 
 import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.psi.PsiAnnotation;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -39,7 +40,7 @@
 
   @Override
   public boolean checkApplicability(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) {
-    final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
+    final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
     if (annotationCollector == null) {
       return false;
     }
@@ -62,7 +63,7 @@
 
   @Override
   public boolean checkArgumentList(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) {
-    final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
+    final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
     if (annotationCollector == null) {
       return false;
     }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java
index c86109e..edf4bf6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.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.
@@ -56,7 +56,7 @@
     if (myImplicitMethod != null) return myImplicitMethod;
 
     Boolean aStatic = isStatic();
-    myImplicitMethod = new GrDynamicImplicitMethod(manager, getName(), containingClassName, aStatic != null && aStatic.booleanValue(), myPairs);
+    myImplicitMethod = new GrDynamicImplicitMethod(manager, getName(), containingClassName, aStatic != null && aStatic.booleanValue(), myPairs, getType());
     return myImplicitMethod;
   }
 }
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicMethodDialog.java
index 62dc064..5883cfe 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicMethodDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/ui/DynamicMethodDialog.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.
@@ -103,7 +103,7 @@
 
   private class TypeColumnInfo extends ColumnInfo<ParamInfo, String> {
     public TypeColumnInfo() {
-      super(GroovyBundle.message("dynamic.name"));
+      super(GroovyBundle.message("dynamic.type"));
     }
 
     public String valueOf(ParamInfo pair) {
@@ -123,14 +123,13 @@
         return;
       }
 
-      if (type == null) return;
-      pair.type =type.getCanonicalText();
+      pair.type = type.getCanonicalText();
     }
   }
 
   private static class NameColumnInfo extends ColumnInfo<ParamInfo, String> {
     public NameColumnInfo() {
-      super(GroovyBundle.message("dynamic.type"));
+      super(GroovyBundle.message("dynamic.name"));
     }
 
     public boolean isCellEditable(ParamInfo myPair) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
index d0a1fb4..634d32e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
@@ -64,6 +65,7 @@
            setter != null && PsiUtil.isAccessible(place, setter);
   }
 
+  @NotNull
   @Override
   protected BaseInspectionVisitor buildVisitor() {
     return new MyVisitor();
@@ -89,7 +91,7 @@
   }
 
   @Override
-  protected GroovyFix[] buildFixes(PsiElement location) {
+  protected GroovyFix[] buildFixes(@NotNull PsiElement location) {
     if (!(location instanceof GrReferenceElement || location instanceof GrConstructorCall)) {
       location = location.getParent();
     }
@@ -116,6 +118,7 @@
       Project project = refElement.getProject();
       JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
       PsiModifierList modifierListCopy = facade.getElementFactory().createFieldFromText("int a;", null).getModifierList();
+      assert modifierListCopy != null;
       modifierListCopy.setModifierProperty(PsiModifier.STATIC, modifierList.hasModifierProperty(PsiModifier.STATIC));
       String minModifier = PsiModifier.PROTECTED;
       if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) {
@@ -188,11 +191,11 @@
 
         registerError(refElement,
                       PsiFormatUtil.formatMethod((PsiMethod)constructor, PsiSubstitutor.EMPTY,
-                                                 PsiFormatUtil.SHOW_NAME |
-                                                 PsiFormatUtil.SHOW_TYPE |
-                                                 PsiFormatUtil.TYPE_AFTER |
-                                                 PsiFormatUtil.SHOW_PARAMETERS,
-                                                 PsiFormatUtil.SHOW_TYPE
+                                                 PsiFormatUtilBase.SHOW_NAME |
+                                                 PsiFormatUtilBase.SHOW_TYPE |
+                                                 PsiFormatUtilBase.TYPE_AFTER |
+                                                 PsiFormatUtilBase.SHOW_PARAMETERS,
+                                                 PsiFormatUtilBase.SHOW_TYPE
                       ));
       }
     }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java
index f988749..c86790d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java
@@ -27,6 +27,7 @@
 import org.jetbrains.plugins.groovy.GroovyBundle;
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
+import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
 import org.jetbrains.plugins.groovy.lang.psi.*;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
 import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
@@ -102,14 +103,29 @@
         super.visitReferenceExpression(ref);
 
         final PsiElement resolved = ref.resolve();
-        if (resolved instanceof GrField && ((GrField)resolved).hasModifierProperty(FINAL) && PsiUtil.isLValue(ref)) {
+        if (resolved instanceof GrField && ((GrField)resolved).hasModifierProperty(FINAL)) {
           final GrField field = (GrField)resolved;
-
           final PsiClass containingClass = field.getContainingClass();
-          if (containingClass == null || !PsiTreeUtil.isAncestor(containingClass, ref, true)) {
-            registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.field.0", field.getName()), LocalQuickFix.EMPTY_ARRAY,
-                          ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+
+          if (PsiUtil.isLValue(ref)) {
+            if (containingClass == null || !PsiTreeUtil.isAncestor(containingClass, ref, true)) {
+              registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.field.0", field.getName()), LocalQuickFix.EMPTY_ARRAY,
+                            ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+            }
           }
+          else if (PsiUtil.isUsedInIncOrDec(ref)) {
+            if (containingClass == null || !isInsideConstructorOrInitializer(containingClass, ref, field.hasModifierProperty(PsiModifier.STATIC))) {
+              registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.field.0", field.getName()), LocalQuickFix.EMPTY_ARRAY,
+                            ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+            }
+          }
+        }
+        else if (resolved instanceof GrParameter &&
+                 ((GrParameter)resolved).getDeclarationScope() instanceof GrMethod &&
+                 ((GrParameter)resolved).hasModifierProperty(FINAL) &&
+                 PsiUtil.isUsedInIncOrDec(ref)) {
+          registerError(ref, GroovyBundle.message("cannot.assign.a.value.to.final.parameter.0", ((GrParameter)resolved).getName()),
+                        LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
         }
       }
 
@@ -200,6 +216,19 @@
     };
   }
 
+  private static boolean isInsideConstructorOrInitializer(@NotNull PsiClass containingClass, @NotNull GrReferenceExpression place, boolean isStatic) {
+    PsiElement container = ControlFlowUtils.findControlFlowOwner(place);
+
+    PsiClass aClass = null;
+    if (!isStatic && container instanceof GrMethod && ((GrMethod)container).isConstructor()) {
+      aClass = ((GrMethod)container).getContainingClass();
+    }
+    else if (container instanceof GrClassInitializer && ((GrClassInitializer)container).isStatic() == isStatic) {
+      aClass = ((GrClassInitializer)container).getContainingClass();
+    }
+    return aClass != null && containingClass.getManager().areElementsEquivalent(aClass, containingClass);
+  }
+
   @NotNull
   private static List<GrField> getFinalFields(@NotNull GrTypeDefinition clazz) {
     final GrField[] fields = clazz.getCodeFields();
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 e5621b7..985632a 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
@@ -682,18 +682,18 @@
     }
 
     @Override
-    public void register(IntentionAction action) {
+    public void register(@NotNull IntentionAction action) {
       myKey = HighlightDisplayKey.find(SHORT_NAME);
       QuickFixAction.registerQuickFixAction(myInfo, action, myKey);
     }
 
     @Override
-    public void register(TextRange fixRange, IntentionAction action, HighlightDisplayKey key) {
+    public void register(@NotNull TextRange fixRange, @NotNull IntentionAction action, HighlightDisplayKey key) {
       QuickFixAction.registerQuickFixAction(myInfo, fixRange, action, key);
     }
 
     @Override
-    public void unregister(Condition<IntentionAction> condition) {
+    public void unregister(@NotNull Condition<IntentionAction> condition) {
       if (myInfo != null) {
         QuickFixAction.unregisterQuickFixAction(myInfo, condition);
       }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java
new file mode 100644
index 0000000..3125606
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.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 org.jetbrains.plugins.groovy.editor.selection;
+
+import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 8/19/13
+ */
+public class GroovyTypeDefinitionBodySelectioner extends ExtendWordSelectionHandlerBase {
+  public boolean canSelect(PsiElement e) {
+    return e instanceof GrTypeDefinitionBody;
+  }
+
+  public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+    List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+
+    if (e instanceof GrTypeDefinitionBody) {
+      GrTypeDefinitionBody block = ((GrTypeDefinitionBody)e);
+      int startOffset = findOpeningBrace(block);
+      int endOffset = findClosingBrace(block, startOffset);
+      TextRange range = new TextRange(startOffset, endOffset);
+      result.addAll(expandToWholeLine(editorText, range));
+    }
+    return result;
+  }
+
+  private static int findOpeningBrace(GrTypeDefinitionBody block) {
+    PsiElement lbrace = block.getLBrace();
+    if (lbrace == null) return block.getTextRange().getStartOffset();
+
+    while (PsiImplUtil.isWhiteSpace(lbrace.getNextSibling())) {
+      lbrace = lbrace.getNextSibling();
+    }
+    return lbrace.getTextRange().getEndOffset();
+  }
+
+  private static int findClosingBrace(GrTypeDefinitionBody block, int startOffset) {
+    PsiElement rbrace = block.getRBrace();
+    if (rbrace == null) return block.getTextRange().getEndOffset();
+
+    while (PsiImplUtil.isWhiteSpace(rbrace.getPrevSibling()) && rbrace.getPrevSibling().getTextRange().getStartOffset() > startOffset) {
+      rbrace = rbrace.getPrevSibling();
+    }
+
+    return rbrace.getTextRange().getStartOffset();
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.java
new file mode 100644
index 0000000..627197e
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/geb/GebTestNGTestMemberContributor.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 org.jetbrains.plugins.groovy.geb;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.ResolveState;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor;
+
+/**
+ * @author zolotov
+ */
+public class GebTestNGTestMemberContributor extends NonCodeMembersContributor {
+
+  @Override
+  protected String getParentClassName() {
+    return "geb.testng.GebTest";
+  }
+
+  @Override
+  public void processDynamicElements(@NotNull PsiType qualifierType,
+                                     PsiClass aClass,
+                                     PsiScopeProcessor processor,
+                                     PsiElement place,
+                                     ResolveState state) {
+    GebUtil.contributeMembersInsideTest(processor, place, state);
+  }
+
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
index f97bfeb..5c66f97 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
@@ -19,6 +19,8 @@
 import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils;
 import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromUsageFix;
 import com.intellij.codeInsight.template.*;
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
@@ -30,6 +32,7 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.actions.GroovyTemplates;
 import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
@@ -140,7 +143,9 @@
                   ((GrMethod)method).setReturnType(PsiType.VOID);
                 }
                 if (method.getBody() != null) {
-                  CreateFromUsageUtils.setupMethodBody(method);
+                  FileTemplateManager templateManager = FileTemplateManager.getInstance();
+                  FileTemplate fileTemplate = templateManager.getCodeTemplate(GroovyTemplates.GROOVY_FROM_USAGE_METHOD_BODY);
+                  CreateFromUsageUtils.setupMethodBody(method, method.getContainingClass(), fileTemplate);
                 }
                 if (hasNoReturnType) {
                   ((GrMethod)method).setReturnType(null);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/jarFinder/GroovyFindJarQuickFixProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/jarFinder/GroovyFindJarQuickFixProvider.java
index 15021e8..d2398de 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/jarFinder/GroovyFindJarQuickFixProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/jarFinder/GroovyFindJarQuickFixProvider.java
@@ -12,7 +12,7 @@
  */
 public class GroovyFindJarQuickFixProvider extends UnresolvedReferenceQuickFixProvider<GrReferenceElement> {
   @Override
-  public void registerFixes(GrReferenceElement ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull GrReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new GroovyFindJarFix(ref));
   }
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
index 275ae14..257aec4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
@@ -591,7 +591,7 @@
       PsiElement resolved = ref.resolve();
 
       if (resolved instanceof PsiClass) {
-        final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
+        final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
 
         if (annotationCollector != null) {
           final ArrayList<GrAnnotation> annotations = ContainerUtil.newArrayList();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrReferenceListWeigher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrReferenceListWeigher.java
index c7f0b61..2205867 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrReferenceListWeigher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrReferenceListWeigher.java
@@ -16,6 +16,7 @@
 package org.jetbrains.plugins.groovy.lang.completion.weighers;
 
 import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.PsiElementPattern;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.util.ProximityLocation;
 import com.intellij.psi.util.proximity.ReferenceListWeigher;
@@ -29,10 +30,13 @@
  * @author peter
  */
 public class GrReferenceListWeigher extends ReferenceListWeigher {
+  private static final PsiElementPattern.Capture<PsiElement> INSIDE_REFERENCE_LIST =
+    PlatformPatterns.psiElement().withParents(GrCodeReferenceElement.class, GrReferenceList.class);
+
   @Override
   protected Preference getPreferredCondition(@NotNull ProximityLocation location) {
     PsiElement position = location.getPosition();
-    if (PlatformPatterns.psiElement().withParents(GrCodeReferenceElement.class, GrReferenceList.class).accepts(position)) {
+    if (INSIDE_REFERENCE_LIST.accepts(position)) {
       assert position != null;
       GrReferenceList list = (GrReferenceList)position.getParent().getParent();
       PsiElement parent = list.getParent();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
index 6e4028d..967330d4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
@@ -180,7 +180,7 @@
       String name = declaredName == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : declaredName;
 
       if (resolved instanceof PsiClass) {
-        final GrAnnotation collector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
+        final PsiAnnotation collector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
         if (collector != null) {
           return multiResolveFromAlias(annotation, name, collector);
         }
@@ -205,7 +205,7 @@
     return results;
   }
 
-  private static GroovyResolveResult[] multiResolveFromAlias(@NotNull GrAnnotation alias, @NotNull String name, @NotNull GrAnnotation annotationCollector) {
+  private static GroovyResolveResult[] multiResolveFromAlias(@NotNull GrAnnotation alias, @NotNull String name, @NotNull PsiAnnotation annotationCollector) {
     List<GroovyResolveResult> result = ContainerUtilRt.newArrayList();
 
     List<GrAnnotation> annotations = ContainerUtilRt.newArrayList();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java
index 8b8a825..2ddb1ef 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java
@@ -19,13 +19,13 @@
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightAnnotation;
 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -36,6 +36,7 @@
 import java.util.Set;
 
 public class GrAnnotationCollector {
+
   @NotNull
   public static GrAnnotation[] getResolvedAnnotations(@NotNull GrModifierList modifierList) {
     final GrAnnotation[] rawAnnotations = modifierList.getRawAnnotations();
@@ -44,7 +45,7 @@
 
     List<GrAnnotation> result = ContainerUtil.newArrayList();
     for (GrAnnotation annotation : rawAnnotations) {
-      final GrAnnotation annotationCollector = findAnnotationCollector(annotation);
+      final PsiAnnotation annotationCollector = findAnnotationCollector(annotation);
       if (annotationCollector != null) {
         collectAnnotations(result, annotation, annotationCollector);
       }
@@ -59,7 +60,7 @@
 
   private static boolean hasAliases(@NotNull GrAnnotation[] rawAnnotations) {
     for (GrAnnotation annotation : rawAnnotations) {
-      final GrAnnotation annotationCollector = findAnnotationCollector(annotation);
+      final PsiAnnotation annotationCollector = findAnnotationCollector(annotation);
       if (annotationCollector != null) {
         return true;
       }
@@ -78,21 +79,19 @@
   @NotNull
   public static Set<String> collectAnnotations(@NotNull List<GrAnnotation> list,
                                                @NotNull GrAnnotation alias,
-                                               @NotNull GrAnnotation annotationCollector) {
+                                               @NotNull PsiAnnotation annotationCollector) {
 
-    final GrModifierList modifierList = (GrModifierList)annotationCollector.getParent();
+    final PsiModifierList modifierList = (PsiModifierList)annotationCollector.getParent();
 
-    Map<String, Map<String, GrAnnotationNameValuePair>> annotations = ContainerUtil.newHashMap();
-    collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(annotationCollector,
-                                                                   (HashMap<String, Map<String, GrAnnotationNameValuePair>>)annotations);
-    collectAliasedAnnotationsFromAnnotationCollectorAnnotations(modifierList,
-                                                                (HashMap<String, Map<String, GrAnnotationNameValuePair>>)annotations);
+    Map<String, Map<String, PsiNameValuePair>> annotations = ContainerUtil.newHashMap();
+    collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(annotationCollector, (HashMap<String, Map<String, PsiNameValuePair>>)annotations);
+    collectAliasedAnnotationsFromAnnotationCollectorAnnotations(modifierList, (HashMap<String, Map<String, PsiNameValuePair>>)annotations);
 
     final PsiManager manager = alias.getManager();
     final GrAnnotationNameValuePair[] attributes = alias.getParameterList().getAttributes();
 
     Set<String> allUsedAttrs = ContainerUtil.newHashSet();
-    for (Map.Entry<String, Map<String, GrAnnotationNameValuePair>> entry : annotations.entrySet()) {
+    for (Map.Entry<String, Map<String, PsiNameValuePair>> entry : annotations.entrySet()) {
       final String qname = entry.getKey();
       final PsiClass resolved = JavaPsiFacade.getInstance(alias.getProject()).findClass(qname, alias.getResolveScope());
       if (resolved == null) continue;
@@ -110,8 +109,8 @@
       }
 
 
-      final Map<String, GrAnnotationNameValuePair> defaults = entry.getValue();
-      for (Map.Entry<String, GrAnnotationNameValuePair> defa : defaults.entrySet()) {
+      final Map<String, PsiNameValuePair> defaults = entry.getValue();
+      for (Map.Entry<String, PsiNameValuePair> defa : defaults.entrySet()) {
         if (!usedAttrs.contains(defa.getKey())) {
           annotation.addAttribute(defa.getValue());
         }
@@ -124,16 +123,29 @@
     return allUsedAttrs;
   }
 
-  private static void collectAliasedAnnotationsFromAnnotationCollectorAnnotations(@NotNull GrModifierList modifierList,
-                                                                                  @NotNull HashMap<String, Map<String, GrAnnotationNameValuePair>> annotations) {
-    for (GrAnnotation annotation : modifierList.getRawAnnotations()) {
+  private static void collectAliasedAnnotationsFromAnnotationCollectorAnnotations(@NotNull PsiModifierList modifierList,
+                                                                                  @NotNull HashMap<String, Map<String, PsiNameValuePair>> annotations) {
+    PsiElement parent = modifierList.getParent();
+    if (parent instanceof PsiClass &&
+        GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_DYNAMIC.equals(((PsiClass)parent).getQualifiedName())) {
+      HashMap<String, PsiNameValuePair> params = ContainerUtil.newHashMap();
+      annotations.put(GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC, params);
+      GrAnnotation annotation =
+        GroovyPsiElementFactory.getInstance(modifierList.getProject()).createAnnotationFromText("@CompileStatic(TypeCheckingMode.SKIP)");
+      params.put("value", annotation.getParameterList().getAttributes()[0]);
+      return;
+    }
+
+    PsiAnnotation[] rawAnnotations =
+      modifierList instanceof GrModifierList ? ((GrModifierList)modifierList).getRawAnnotations() : modifierList.getAnnotations();
+    for (PsiAnnotation annotation : rawAnnotations) {
       final String qname = annotation.getQualifiedName();
 
       if (qname == null || qname.equals(GroovyCommonClassNames.GROOVY_TRANSFORM_ANNOTATION_COLLECTOR)) continue;
 
-      final GrAnnotationNameValuePair[] attributes = annotation.getParameterList().getAttributes();
-      for (GrAnnotationNameValuePair pair : attributes) {
-        Map<String, GrAnnotationNameValuePair> map = annotations.get(qname);
+      final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
+      for (PsiNameValuePair pair : attributes) {
+        Map<String, PsiNameValuePair> map = annotations.get(qname);
         if (map == null) {
           map = ContainerUtil.newHashMap();
           annotations.put(qname, map);
@@ -142,14 +154,14 @@
         map.put(pair.getName() != null ? pair.getName() : "value", pair);
       }
       if (attributes.length == 0 && !annotations.containsKey(qname)) {
-        annotations.put(qname, ContainerUtil.<String, GrAnnotationNameValuePair>newHashMap());
+        annotations.put(qname, ContainerUtil.<String, PsiNameValuePair>newHashMap());
       }
     }
 
   }
 
-  private static void collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(@NotNull GrAnnotation annotationCollector,
-                                                                                     @NotNull HashMap<String, Map<String, GrAnnotationNameValuePair>> annotations) {
+  private static void collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(@NotNull PsiAnnotation annotationCollector,
+                                                                                     @NotNull HashMap<String, Map<String, PsiNameValuePair>> annotations) {
     final PsiAnnotationMemberValue annotationsFromValue = annotationCollector.findAttributeValue("value");
 
     if (annotationsFromValue instanceof GrAnnotationArrayInitializer) {
@@ -157,7 +169,7 @@
         if (member instanceof GrReferenceExpression) {
           final PsiElement resolved = ((GrReferenceExpression)member).resolve();
           if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) {
-            annotations.put(((PsiClass)resolved).getQualifiedName(), ContainerUtil.<String, GrAnnotationNameValuePair>newHashMap());
+            annotations.put(((PsiClass)resolved).getQualifiedName(), ContainerUtil.<String, PsiNameValuePair>newHashMap());
           }
         }
       }
@@ -165,11 +177,12 @@
   }
 
   @Nullable
-  public static GrAnnotation findAnnotationCollector(@Nullable PsiClass clazz) {
-    if (clazz instanceof GrTypeDefinition) {
-      final GrModifierList modifierList = ((GrTypeDefinition)clazz).getModifierList();
+  public static PsiAnnotation findAnnotationCollector(@Nullable PsiClass clazz) {
+    if (clazz != null) {
+      final PsiModifierList modifierList = clazz.getModifierList();
       if (modifierList != null) {
-        for (GrAnnotation annotation : modifierList.getRawAnnotations()) {
+        PsiAnnotation[] annotations = modifierList instanceof GrModifierList ? ((GrModifierList)modifierList).getRawAnnotations() : modifierList.getAnnotations();
+        for (PsiAnnotation annotation : annotations) {
           if (GroovyCommonClassNames.GROOVY_TRANSFORM_ANNOTATION_COLLECTOR.equals(annotation.getQualifiedName())) {
             return annotation;
           }
@@ -182,7 +195,7 @@
 
 
   @Nullable
-  public static GrAnnotation findAnnotationCollector(@NotNull GrAnnotation annotation) {
+  public static PsiAnnotation findAnnotationCollector(@NotNull GrAnnotation annotation) {
     final GrCodeReferenceElement ref = annotation.getClassReference();
 
     final PsiElement resolved = ref.resolve();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrDynamicImplicitMethod.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrDynamicImplicitMethod.java
index 0045c4c..d0ef1ca 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrDynamicImplicitMethod.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrDynamicImplicitMethod.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.
@@ -57,12 +57,14 @@
 
   private final String myContainingClassName;
   private final List<ParamInfo> myParamInfos;
+  private final String myReturnType;
 
   public GrDynamicImplicitMethod(PsiManager manager,
                                  String name,
                                  String containingClassName,
                                  boolean isStatic,
-                                 List<ParamInfo> paramInfos) {
+                                 List<ParamInfo> paramInfos,
+                                 String returnType) {
     super(manager, name);
     myContainingClassName = containingClassName;
     myParamInfos = paramInfos;
@@ -75,6 +77,9 @@
     for (ParamInfo pair : paramInfos) {
       addParameter(pair.name, pair.type, false);
     }
+
+    setReturnType(returnType, getResolveScope());
+    myReturnType = returnType;
   }
 
   public String getContainingClassName() {
@@ -95,7 +100,7 @@
   }
 
   public GrDynamicImplicitMethod copy() {
-    return new GrDynamicImplicitMethod(myManager, getName(), getContainingClassName(), hasModifierProperty(PsiModifier.STATIC), ContainerUtil.newArrayList(myParamInfos));
+    return new GrDynamicImplicitMethod(myManager, getName(), getContainingClassName(), hasModifierProperty(PsiModifier.STATIC), ContainerUtil.newArrayList(myParamInfos), myReturnType);
   }
 
   public boolean isValid() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightAnnotation.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightAnnotation.java
index bbf33c3..ebf4312 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightAnnotation.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightAnnotation.java
@@ -27,11 +27,14 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.refactoring.convertJavaToGroovy.AnnotationArgConverter;
 
 import java.util.List;
 
@@ -89,11 +92,7 @@
 
   @Override
   public String getText() {
-    StringBuilder buffer = new StringBuilder();
-    buffer.append('@').append(myQualifiedName);
-    buffer.append(myAnnotationArgList.getText());
-
-    return buffer.toString();
+    return "@" + myQualifiedName + myAnnotationArgList.getText();
   }
 
   @Override
@@ -139,8 +138,22 @@
     return null;
   }
 
-  public void addAttribute(GrAnnotationNameValuePair attribute) {
-    myAnnotationArgList.addAttribute(attribute);
+  public void addAttribute(PsiNameValuePair pair) {
+    if (pair instanceof GrAnnotationNameValuePair) {
+      myAnnotationArgList.addAttribute((GrAnnotationNameValuePair)pair);
+    }
+    else {
+      GrAnnotationMemberValue newValue = new AnnotationArgConverter().convert(pair.getValue());
+      if (newValue == null) return;
+
+      String name = pair.getName();
+      GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(pair.getProject());
+      String annotationText;
+      annotationText = name != null ? "@A(" + name + "=" + newValue.getText() + ")"
+                                    : "@A(" + newValue.getText() + ")";
+      GrAnnotation annotation = factory.createAnnotationFromText(annotationText);
+      myAnnotationArgList.addAttribute(annotation.getParameterList().getAttributes()[0]);
+    }
   }
 
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java
index 6466f7d..27f597b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java
@@ -63,6 +63,7 @@
   @NonNls public static final String GROOVY_LANG_NEWIFY = "groovy.lang.Newify";
   @NonNls public static final String GROOVY_LANG_DELEGATES_TO = "groovy.lang.DelegatesTo";
   @NonNls public static final String GROOVY_LANG_DELEGATES_TO_TARGET = "groovy.lang.DelegatesTo.Target";
+  @NonNls public static final String GROOVY_TRANSFORM_COMPILE_DYNAMIC = "groovy.transform.CompileDynamic";
 
 
   private GroovyCommonClassNames() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java
index 5a1b66d..0c8f5ba 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.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.
@@ -22,7 +22,6 @@
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.codeStyle.VariableKind;
-import com.intellij.psi.util.PropertyUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
@@ -74,8 +73,7 @@
   @Nullable
   public static PsiMethod findSetterForField(PsiField field) {
     final PsiClass containingClass = field.getContainingClass();
-    final Project project = field.getProject();
-    final String propertyName = PropertyUtil.suggestPropertyName(project, field);
+    final String propertyName = field.getName();
     final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
     return findPropertySetter(containingClass, propertyName, isStatic, true);
   }
@@ -83,8 +81,7 @@
   @Nullable
   public static PsiMethod findGetterForField(PsiField field) {
     final PsiClass containingClass = field.getContainingClass();
-    final Project project = field.getProject();
-    final String propertyName = PropertyUtil.suggestPropertyName(project, field);
+    final String propertyName = field.getName();
     final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
     return findPropertyGetter(containingClass, propertyName, isStatic, true);
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
index 64f8314..57d2be7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
@@ -836,8 +836,10 @@
   }
 
   public static boolean isAccessedForWriting(GrExpression expr) {
-    if (isLValue(expr)) return true;
+    return isLValue(expr) || isUsedInIncOrDec(expr);
+  }
 
+  public static boolean isUsedInIncOrDec(GrExpression expr) {
     PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, GrParenthesizedExpression.class);
 
     if (parent instanceof GrUnaryExpression) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java
index bfac2aa..5e2e2af 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java
@@ -25,6 +25,7 @@
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.RefactoringActionHandler;
 import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
@@ -48,7 +49,7 @@
 
   public static final GroovyRefactoringSupportProvider INSTANCE = new GroovyRefactoringSupportProvider();
 
-  public boolean isSafeDeleteAvailable(PsiElement element) {
+  public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
     return element instanceof GrTypeDefinition ||
            element instanceof GrField ||
            element instanceof GrMethod;
@@ -73,7 +74,7 @@
   }
 
   @Override
-  public boolean isInplaceRenameAvailable(PsiElement elementToRename, PsiElement nameSuggestionContext) {
+  public boolean isInplaceRenameAvailable(@NotNull PsiElement elementToRename, PsiElement nameSuggestionContext) {
     //local vars & params renames GrVariableInplaceRenameHandler
 
     if (nameSuggestionContext != null && nameSuggestionContext.getContainingFile() != elementToRename.getContainingFile()) return false;
@@ -93,13 +94,14 @@
   }
 
   @Override
-  public boolean isInplaceIntroduceAvailable(PsiElement element, PsiElement context) {
+  public boolean isInplaceIntroduceAvailable(@NotNull PsiElement element, PsiElement context) {
     if (context == null || context.getContainingFile() != element.getContainingFile()) return false;
     return true;
   }
 
   @Override
-  public boolean isMemberInplaceRenameAvailable(PsiElement element, PsiElement context) {
+  public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement element, @Nullable PsiElement context) {
+    if (context == null) return false;
     PsiElement parent = context.getParent();
 
     //don't try to inplace rename aliased imported references
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/AnnotationArgConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/AnnotationArgConverter.java
new file mode 100644
index 0000000..7163c2f
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/AnnotationArgConverter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.refactoring.convertJavaToGroovy;
+
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
+
+/**
+ * Created by Max Medvedev on 8/19/13
+ */
+public class AnnotationArgConverter {
+  @Nullable
+  public GrAnnotationMemberValue convert(PsiAnnotationMemberValue value) {
+    final StringBuilder buffer = new StringBuilder();
+
+    buffer.append("@A(");
+    generateText(value, buffer);
+    buffer.append(")");
+
+    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(value.getProject());
+    try {
+      return factory.createAnnotationFromText(buffer.toString()).getParameterList().getAttributes()[0].getValue();
+    }
+    catch (IncorrectOperationException e) {
+      return null;
+    }
+  }
+
+  private void generateText(PsiAnnotationMemberValue value, final StringBuilder buffer) {
+    value.accept(new JavaElementVisitor() {
+      @Override
+      public void visitAnnotation(PsiAnnotation annotation) {
+        buffer.append("@");
+        PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
+        if (ref == null) return;
+
+        PsiElement resolved = ref.resolve();
+
+        if (resolved instanceof PsiClass && ((PsiClass)resolved).getQualifiedName() != null) {
+          buffer.append(((PsiClass)resolved).getQualifiedName());
+        }
+        else {
+          buffer.append(ref.getText());
+        }
+
+        PsiAnnotationParameterList parameterList = annotation.getParameterList();
+        parameterList.accept(this);
+      }
+
+      @Override
+      public void visitAnnotationParameterList(PsiAnnotationParameterList list) {
+        PsiNameValuePair[] attributes = list.getAttributes();
+        if (attributes.length > 0) {
+          buffer.append('(');
+          for (PsiNameValuePair attribute : attributes) {
+            attribute.accept(this);
+            buffer.append(',');
+          }
+          buffer.replace(buffer.length() - 1, buffer.length(), ")");
+        }
+      }
+
+      @Override
+      public void visitNameValuePair(PsiNameValuePair pair) {
+        String name = pair.getName();
+        PsiAnnotationMemberValue value = pair.getValue();
+
+        if (name != null) {
+          buffer.append(name);
+          buffer.append('=');
+        }
+
+        if (value != null) {
+          value.accept(this);
+        }
+      }
+
+      @Override
+      public void visitExpression(PsiExpression expression) {
+        buffer.append(expression.getText());
+      }
+
+      @Override
+      public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) {
+        PsiAnnotationMemberValue[] initializers = initializer.getInitializers();
+        processInitializers(initializers);
+      }
+
+      @Override
+      public void visitNewExpression(PsiNewExpression expression) {
+        PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
+        if (arrayInitializer == null) {
+          super.visitNewExpression(expression);
+        }
+        else {
+          PsiType type = expression.getType();
+          if (type == null) {
+            type = PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope()).createArrayType();
+          }
+          buffer.append('(');
+          arrayInitializer.accept(this);
+          buffer.append(" as ");
+          buffer.append(type.getCanonicalText());
+          buffer.append(")");
+        }
+      }
+
+      @Override
+      public void visitArrayInitializerExpression(PsiArrayInitializerExpression arrayInitializer) {
+        processInitializers(arrayInitializer.getInitializers());
+      }
+
+      private void processInitializers(PsiAnnotationMemberValue[] initializers) {
+        buffer.append('[');
+        for (PsiAnnotationMemberValue initializer : initializers) {
+          initializer.accept(this);
+          buffer.append(',');
+        }
+        if (initializers.length > 0) {
+          buffer.delete(buffer.length() - 1, buffer.length());
+        }
+        buffer.append(']');
+      }
+    });
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java
index d765525..e915604 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java
@@ -89,7 +89,7 @@
     if (success) {
       final GrVariable field = getVariable();
       assert field != null;
-      GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings()) {
+      GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings(), false) {
         @NotNull
         @Override
         protected GrExpression getInitializer() {
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 39413af..1081b61 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
@@ -111,7 +111,7 @@
 
   @Override
   public GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings) {
-    return new GrIntroduceFieldProcessor(context, settings).run();
+    return new GrIntroduceFieldProcessor(context, settings, isInplace(context)).run();
   }
 
   @Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java
index 53d3d5b..3efe8f6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java
@@ -28,6 +28,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
@@ -41,6 +42,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
 import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -60,10 +62,12 @@
 
   private final GrIntroduceContext context;
   private final GrIntroduceFieldSettings settings;
+  private boolean myForInplacePrepare;
 
-  public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings) {
+  public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings, boolean forInplacePrepare) {
     this.context = context;
     this.settings = settings;
+    myForInplacePrepare = forInplacePrepare;
   }
 
   public GrVariable run() {
@@ -115,7 +119,7 @@
       else {
         final GrExpression expression = context.getExpression();
         assert expression != null;
-        if (PsiUtil.isExpressionStatement(expression)) {
+        if (!myForInplacePrepare && PsiUtil.isExpressionStatement(expression)) {
           expression.delete();
         }
         else {
@@ -181,10 +185,10 @@
     final PsiElement place = context.getPlace();
 
     final GrMember member = GrIntroduceFieldHandler.getContainer(place, scope);
-    LOG.assertTrue(member != null);
-    GrOpenBlock container = member instanceof GrMethod? ((GrMethod)member).getBlock():
-                            member instanceof GrClassInitializer ? ((GrClassInitializer)member).getBlock():
-                            null;
+    GrStatementOwner container = member instanceof GrMethod ? ((GrMethod)member).getBlock() :
+                                 member instanceof GrClassInitializer ? ((GrClassInitializer)member).getBlock() :
+                                 place.getContainingFile() instanceof GroovyFile ? ((GroovyFile)place.getContainingFile()) :
+                                 null;
     assert container != null;
 
     final GrStatement anchor;
@@ -199,35 +203,21 @@
     generateAssignment(field, anchor, container);
   }
 
-  void initializeInConstructor(GrVariable field) {
+  void initializeInConstructor(@NotNull GrVariable field) {
     final PsiClass scope = (PsiClass)context.getScope();
-    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
 
     if (scope instanceof GrAnonymousClassDefinition) {
-      final GrClassInitializer[] initializers = ((GrAnonymousClassDefinition)scope).getInitializers();
-      final GrClassInitializer initializer;
-      if (initializers.length == 0) {
-        initializer = (GrClassInitializer)scope.add(factory.createClassInitializer());
-      }
-      else {
-        initializer = initializers[0];
-      }
-
-
-      final PsiElement anchor = findAnchorForAssignment(initializer.getBlock());
-      generateAssignment(field, (GrStatement)anchor, initializer.getBlock());
-      return;
+      initializeInAnonymousClassInitializer(field, (GrAnonymousClassDefinition)scope);
     }
+    else {
+      initializeInConstructor(field, scope);
+    }
+  }
 
-
+  private void initializeInConstructor(@NotNull GrVariable field, @NotNull PsiClass scope) {
     PsiMethod[] constructors = scope.getConstructors();
     if (constructors.length == 0) {
-      final String name = scope.getName();
-      LOG.assertTrue(name != null, scope.getText());
-      final GrMethod constructor =
-        factory.createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", scope);
-      final PsiElement added = scope.add(constructor);
-      constructors = new PsiMethod[]{(PsiMethod)added};
+      constructors = new PsiMethod[]{generateConstructor(scope)};
     }
 
     for (PsiMethod constructor : constructors) {
@@ -239,18 +229,39 @@
     }
   }
 
+  @NotNull
+  private PsiMethod generateConstructor(@NotNull PsiClass scope) {
+    final String name = scope.getName();
+    LOG.assertTrue(name != null, scope.getText());
+    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
+    final GrMethod
+      constructor = factory.createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", scope);
+    if (scope instanceof GroovyScriptClass) constructor.getModifierList().setModifierProperty(GrModifier.DEF, true);
+    return (PsiMethod)scope.add(constructor);
+  }
+
+  private void initializeInAnonymousClassInitializer(@NotNull GrVariable field, @NotNull GrAnonymousClassDefinition scope) {
+    final GrClassInitializer[] initializers = scope.getInitializers();
+    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
+    final GrClassInitializer initializer = initializers.length == 0 ? (GrClassInitializer)scope.add(factory.createClassInitializer())
+                                                                    : initializers[0];
+
+    final PsiElement anchor = findAnchorForAssignment(initializer.getBlock());
+    generateAssignment(field, (GrStatement)anchor, initializer.getBlock());
+  }
+
   private void generateAssignment(GrVariable field,
                                   @Nullable GrStatement anchor,
-                                  GrCodeBlock defaultContainer) {
+                                  GrStatementOwner defaultContainer) {
     final GrExpression initializer = getInitializer();
     GrAssignmentExpression init = (GrAssignmentExpression)GroovyPsiElementFactory.getInstance(context.getProject())
       .createExpressionFromText(settings.getName() + " = " + initializer.getText());
 
-    GrCodeBlock block;
+    GrStatementOwner block;
     if (anchor != null) {
       anchor = GroovyRefactoringUtil.addBlockIntoParent(anchor);
-      LOG.assertTrue(anchor.getParent() instanceof GrCodeBlock);
-      block = (GrCodeBlock)anchor.getParent();
+      LOG.assertTrue(anchor.getParent() instanceof GrStatementOwner);
+      block = (GrStatementOwner)anchor.getParent();
     }
     else {
       block = defaultContainer;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java
index 77278f6..bbbd9a5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
 
+import com.intellij.codeInsight.template.TemplateBuilderImpl;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.editor.Editor;
@@ -25,9 +26,12 @@
 import com.intellij.ui.NonFocusableCheckBox;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
 import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener;
 import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
 import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
+import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression;
 
 import javax.swing.*;
 import java.awt.*;
@@ -90,4 +94,14 @@
     return panel;
 
   }
+
+  @Override
+  protected void addAdditionalVariables(TemplateBuilderImpl builder) {
+    GrVariable variable = getVariable();
+    assert variable != null;
+    TypeConstraint[] constraints = {SubtypeConstraint.create(variable.getType())};
+    ChooseTypeExpression typeExpression = new ChooseTypeExpression(constraints, variable.getManager(), true, variable.getResolveScope());
+    builder.replaceElement(variable.getTypeElementGroovy(), "Variable_type", typeExpression, true, true);
+  }
+
 }
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 2aa7150..3cdabe3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestFramework.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 icons.JetgroovyIcons;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.actions.GroovyTemplates;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
 
@@ -125,15 +126,15 @@
 
   @Override
   public FileTemplateDescriptor getSetUpMethodFileTemplateDescriptor() {
-    return new FileTemplateDescriptor("Groovy JUnit SetUp Method.groovy");
+    return new FileTemplateDescriptor(GroovyTemplates.GROOVY_JUNIT_SET_UP_METHOD_GROOVY);
   }
 
   public FileTemplateDescriptor getTearDownMethodFileTemplateDescriptor() {
-    return new FileTemplateDescriptor("Groovy JUnit TearDown Method.groovy");
+    return new FileTemplateDescriptor(GroovyTemplates.GROOVY_JUNIT_TEAR_DOWN_METHOD_GROOVY);
   }
 
   public FileTemplateDescriptor getTestMethodFileTemplateDescriptor() {
-    return new FileTemplateDescriptor("Groovy JUnit Test Method.groovy");
+    return new FileTemplateDescriptor(GroovyTemplates.GROOVY_JUNIT_TEST_METHOD_GROOVY);
   }
 
   @Override
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
index c733fcf..81008c7 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
@@ -47,6 +47,18 @@
 
     TestUtils.checkCompletionContains(myFixture, "\$()", "to()", "go()", "currentWindow", "verifyAt()", "title")
   }
+  
+  void testTestNGTestMemberCompletion() {
+    myFixture.configureByText("FooTest.groovy", """
+class FooTest extends geb.testng.GebReportingTest {
+    def testFoo() {
+      <caret>
+    }
+}
+""")
+
+    TestUtils.checkCompletionContains(myFixture, "\$()", "to()", "go()", "currentWindow", "verifyAt()", "title")
+  }
 
   void testFieldNameCompletion() {
     myFixture.configureByText("FooTest.groovy", """
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy
index 564a794..60d3af34 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy
@@ -508,4 +508,20 @@
 }
 ''')
   }
+
+  void testInc() {
+    testHighlighting('''\
+class Aaa {
+    final int foo = 0
+
+    def test(final String p) {
+        ++<warning>foo</warning>
+        ++<warning>p</warning>
+
+        final int i = 0
+        ++<warning>i</warning>
+    }
+}
+''')
+  }
 }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy
index 9beb849..5bc936ef 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.plugins.groovy.lang.aliasAnnotations
 
+import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
 import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase
 
 /**
@@ -199,4 +200,24 @@
 def bbb() {}
 ''')
   }
+
+  void testCompileDynamic() {
+    testHighlighting('''\
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+
+@CompileStatic
+class B {
+    B() {
+        println <error>x</error>
+    }
+
+    @CompileDynamic
+    def foo() {
+        println <warning>y</warning>
+    }
+}
+''', GrUnresolvedAccessInspection)
+  }
+
 }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
index fe0a604..efed43e 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
@@ -207,6 +207,22 @@
 ''', GroovyAccessibilityInspection)
   }
 
+  public void testStaticImportCapsProperty() {
+    myFixture.addFileToProject('Foo.groovy', '''\
+class Foo {
+  static def FOO = 2
+  private static def BAR = 2
+}
+''')
+    testHighlighting('''\
+import static Foo.FOO
+import static Foo.<warning descr="Access to 'BAR' exceeds its access rights">BAR</warning>
+
+print FOO + <warning descr="Access to 'BAR' exceeds its access rights">BAR</warning>
+''', GroovyAccessibilityInspection)
+  }
+
+
   public void testUntypedAccess() { doTest(new GroovyUntypedAccessInspection()) }
 
   public void testMethodMayBeStaticForCategoryClasses() {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
index b20ca795..92331f6 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
@@ -1120,7 +1120,7 @@
 ''')
   }
 
-  void testDelegatesToApplicability() {
+  void _testDelegatesToApplicability() {
     testHighlighting('''
       def with(@DelegatesTo.Target Object target, @DelegatesTo Closure arg) {
         arg.delegate = target
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/ConvertAnnotationMemberValueTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/ConvertAnnotationMemberValueTest.groovy
new file mode 100644
index 0000000..a0e3e2f
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertJavaToGroovy/ConvertAnnotationMemberValueTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * 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.refactoring.convertJavaToGroovy
+
+import com.intellij.ide.highlighter.JavaFileType
+import com.intellij.psi.PsiAnnotationMemberValue
+import com.intellij.psi.PsiJavaFile
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
+import org.jetbrains.annotations.NotNull
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue
+
+/**
+ * Created by Max Medvedev on 8/19/13
+ */
+class ConvertAnnotationMemberValueTest extends LightCodeInsightFixtureTestCase {
+  void testSimpleExpression1() {
+    doTest('1 + 1', '1 + 1')
+  }
+
+  void testSimpleExpression2() {
+    doTest('foo(bar)', 'foo(bar)')
+  }
+
+  void testSimpleAnnotation1() {
+    doTest('@A', '@A')
+  }
+
+  void testSimpleAnnotation2() {
+    doTest('@A()', '@A')
+  }
+
+  void testSimpleAnnotation3() {
+    doTest('@A(1, value = 2)', '@A(1,value=2)')
+  }
+
+  void testAnnotationInitializer() {
+    doTest('@A({1, 2, 3})', '@A([1,2,3])')
+  }
+
+  void testArrayInitializer() {
+    doTest('new int[]{1, 2, 3}', '([1,2,3] as int[])')
+  }
+
+  void doTest(@NotNull String java, @NotNull String expectedGroovy) {
+    myFixture.configureByText(JavaFileType.INSTANCE, '@A(' + java + ') class Clazz{}')
+
+    PsiJavaFile file = myFixture.file as PsiJavaFile
+    PsiAnnotationMemberValue value = file.classes[0].modifierList.annotations[0].parameterList.attributes[0].value
+    GrAnnotationMemberValue result = new AnnotationArgConverter().convert(value)
+
+    assertEquals(expectedGroovy, result.text)
+  }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy
index a0a96d2..fa46e62 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy
@@ -25,7 +25,6 @@
 import com.intellij.psi.impl.source.tree.TreeElement
 import com.intellij.refactoring.util.CommonRefactoringUtil
 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-import junit.framework.Assert
 import org.jetbrains.plugins.groovy.GroovyFileType
 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
@@ -72,7 +71,7 @@
 
   public void testUndefinedVarInline() {doTest()}
 
-  public void testImplicitCast() { doTest() }
+  public void testImplicitCast1() { doTest() }
   public void testImplicitCast2() { doTest() }
 
   protected void doFieldTest() {
@@ -102,13 +101,13 @@
     if (selectedArea == null) {
       PsiElement identifier = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, PsiElement.class);
       if (identifier != null) {
-        Assert.assertTrue("Selected area doesn't point to var", identifier.parent instanceof GrVariable);
+        assertTrue("Selected area doesn't point to var", identifier.parent instanceof GrVariable);
         selectedArea = (GroovyPsiElement)identifier.parent;
       }
     }
-    Assert.assertNotNull("Selected area reference points to nothing", selectedArea);
+    assertNotNull("Selected area reference points to nothing", selectedArea);
     PsiElement element = selectedArea instanceof GrExpression ? selectedArea.reference.resolve() : selectedArea;
-    Assert.assertNotNull("Cannot resolve selected reference expression", element);
+    assertNotNull("Cannot resolve selected reference expression", element);
 
     try {
       if (!inlineDef) {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
index e9c6791..b709431 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
@@ -57,7 +57,7 @@
   public static final String GROOVY_JAR = "groovy-all.jar";
   public static final String GROOVY_JAR_17 = "groovy-all-1.7.jar";
   public static final String GROOVY_JAR_18 = "groovy-1.8.0-beta-2.jar";
-  public static final String GROOVY_JAR_21 = "groovy-all-2.1.0-beta-1.jar";
+  public static final String GROOVY_JAR_21 = "groovy-all-2.1.3.jar";
   public static final String GROOVY_JAR_22 = "groovy-all-2.2.0-beta-1.jar";
 
   public static String getMockJdkHome() {
diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineLocal/ImplicitCast.test b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast1.test
similarity index 98%
rename from plugins/groovy/testdata/groovy/refactoring/inlineLocal/ImplicitCast.test
rename to plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast1.test
index 9cfa98f..e82ca12 100644
--- a/plugins/groovy/testdata/groovy/refactoring/inlineLocal/ImplicitCast.test
+++ b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast1.test
@@ -2,4 +2,4 @@
 
 print <selection>s</selection>
 -----
-print 2 as String
+print 2 as String
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast2.test b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast2.test
index 871700e..a60678e 100644
--- a/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast2.test
+++ b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/implicitCast2.test
@@ -3,4 +3,4 @@
 print <selection>s</selection>
 -----
 String s = 'a'
-print 2 as String
+print 2 as String
\ No newline at end of file
diff --git a/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar b/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar
new file mode 100644
index 0000000..c61f665
--- /dev/null
+++ b/plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar
Binary files differ
diff --git a/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.0-beta-1.jar b/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.0-beta-1.jar
deleted file mode 100644
index 28ff8fd..0000000
--- a/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.0-beta-1.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.3.jar b/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.3.jar
new file mode 100644
index 0000000..9e434a5
--- /dev/null
+++ b/plugins/groovy/testdata/mockGroovyLib2.1/groovy-all-2.1.3.jar
Binary files differ
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
index 13b1cc9..849305a 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
@@ -39,7 +39,7 @@
 
   private static final Logger LOGGER = Logger.getInstance(HgVersion.class);
   private static final Pattern HG_VERSION_PATTERN =
-    Pattern.compile(".+\\(\\s*\\S+\\s+(\\d+)\\.(\\d+)[\\+\\.-]?(\\d*)?.*\\s*\\)\\s*", Pattern.CASE_INSENSITIVE);
+    Pattern.compile(".+\\(\\s*\\S+\\s+(\\d+)\\.(\\d+)[\\+\\.-]?(\\d*)?.*\\s*\\)\\s*.*\\s*", Pattern.CASE_INSENSITIVE);
   //f.e. Mercurial Distributed SCM (version 2.6+20130507) or Mercurial Distributed SCM (version 2.6.2), 2.7-rc+5-ca2dfc2f63eb
 
   /**
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java b/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java
new file mode 100644
index 0000000..c63c715
--- /dev/null
+++ b/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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 hg4idea.test.history;
+
+import com.intellij.openapi.vcs.CachingCommittedChangesProvider;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import hg4idea.test.HgPlatformTest;
+import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.execution.HgCommandException;
+import org.zmlx.hg4idea.provider.HgRepositoryLocation;
+
+import java.text.ParseException;
+import java.util.List;
+
+import static com.intellij.dvcs.test.Executor.cd;
+import static com.intellij.dvcs.test.Executor.touch;
+import static hg4idea.test.HgExecutor.hg;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class HgBrowseChangesTest extends HgPlatformTest {
+
+  private HgVcs myVcs;
+  private ChangeBrowserSettings mySettings;
+  private String dateBefore;
+  private String dateAfter;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    myVcs = HgVcs.getInstance(myProject);
+    assert myVcs != null;
+    mySettings = new ChangeBrowserSettings();
+    cd(myRepository);
+    touch("f2.txt");
+    hg("add");
+    hg("commit -m add");
+    java.util.Calendar now = java.util.Calendar.getInstance();
+    dateBefore = ChangeBrowserSettings.DATE_FORMAT.format(now.getTime());
+    now.set(java.util.Calendar.YEAR, 1970);
+    dateAfter = ChangeBrowserSettings.DATE_FORMAT.format(now.getTime());
+    if (!SystemInfo.isWindows) {
+      myVcs.getGlobalSettings().setRunViaBash(true);
+    }
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    myVcs.getGlobalSettings().setRunViaBash(false);
+    super.tearDown();
+  }
+
+  public void testLogRevisionWithDataFilter() throws HgCommandException, ParseException, VcsException {
+    mySettings.USE_DATE_AFTER_FILTER = true;
+    mySettings.USE_DATE_BEFORE_FILTER = true;
+    mySettings.DATE_BEFORE = dateBefore;
+    mySettings.DATE_AFTER = dateAfter;
+    doTest();
+  }
+
+  public void testLogRevisionWithAfterDataFilter() throws HgCommandException, ParseException, VcsException {
+    mySettings.USE_DATE_AFTER_FILTER = true;
+    mySettings.DATE_AFTER = dateAfter;
+    doTest();
+  }
+
+  public void testLogRevisionWithBeforeDataFilter() throws HgCommandException, ParseException, VcsException {
+    mySettings.USE_DATE_BEFORE_FILTER = true;
+    mySettings.DATE_BEFORE = dateBefore;
+    doTest();
+  }
+
+  public void testLogRevisionWithBeforeFilter() throws HgCommandException, ParseException, VcsException {
+
+    mySettings.USE_CHANGE_BEFORE_FILTER = true;
+    mySettings.CHANGE_BEFORE = "1";
+    doTest();
+  }
+
+  public void testLogRevisionWithAfterFilter() throws HgCommandException, ParseException, VcsException {
+    mySettings.USE_CHANGE_AFTER_FILTER = true;
+    mySettings.CHANGE_AFTER = "0";
+    doTest();
+  }
+
+  public void testLogRevisionWithFilter() throws HgCommandException, ParseException, VcsException {
+
+    mySettings.USE_CHANGE_BEFORE_FILTER = true;
+    mySettings.USE_CHANGE_AFTER_FILTER = true;
+    mySettings.USE_DATE_AFTER_FILTER = true;
+    mySettings.USE_DATE_BEFORE_FILTER = true;
+    mySettings.DATE_BEFORE = dateBefore;
+    mySettings.DATE_AFTER = dateAfter;
+    mySettings.CHANGE_BEFORE = "1";
+    mySettings.CHANGE_AFTER = "0";
+    doTest();
+  }
+
+  private void doTest() throws HgCommandException, VcsException {
+    CachingCommittedChangesProvider provider = myVcs.getCachingCommittedChangesProvider();
+    assert provider != null;
+    //noinspection unchecked
+    List<CommittedChangeList> revisions =
+      provider.getCommittedChanges(mySettings, new HgRepositoryLocation(myRepository.getUrl(), myRepository), -1);
+    assertTrue(!revisions.isEmpty());
+  }
+}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogTest.java b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogTest.java
index 4e1638e..7436367 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogTest.java
@@ -33,20 +33,21 @@
 
   public void testParseCopiedWithoutBraces() throws HgCommandException {
     parseCopied("f.txt");
+    if (!SystemInfo.isWindows) {
+      myVcs.getGlobalSettings().setRunViaBash(true);
+      try {
+        parseCopied("f1.txt");
+      }
+      finally {
+        myVcs.getGlobalSettings().setRunViaBash(false);
+      }
+    }
   }
 
   public void testParseCopiedWithBraces() throws HgCommandException {
     parseCopied("(f.txt)");
   }
 
-  public void testLogCommandViaBash() throws HgCommandException {
-    if (SystemInfo.isWindows) {
-      return;
-    }
-    myVcs.getGlobalSettings().setRunViaBash(true);
-    parseCopied("f.txt");
-  }
-
   public void testParseFileCopiesWithWhitespaces() {
     Map<String, String> filesMap = HgLogCommand.parseCopiesFileList("/a/b c/d.txt (a/b a/d.txt)\u0001/a/b c/(d).txt (/a/b c/(f).txt)");
     assertTrue(filesMap.containsKey("a/b a/d.txt"));
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
index 9708617..a28f3b3 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
@@ -25,6 +25,7 @@
  */
 public class HgVersionTest extends HgPlatformTest {
 
+  //todo: should be changed to Junit Parameterized tests
   private static final TestHgVersion[] commonTests = {
     new TestHgVersion("Mercurial Distributed SCM (version 2.6.2)", 2, 6, 2),
     new TestHgVersion("Mercurial Distributed SCM (version 2.6+20130507)", 2, 6, 20130507),
@@ -33,7 +34,10 @@
     new TestHgVersion("Mercurial Distributed SCM (version 2.7-rc+5-ca2dfc2f63eb)", 2, 7, 0),
     new TestHgVersion("Распределенная SCM Mercurial (версия 2.0.2)", 2, 0, 2),
     new TestHgVersion("Mercurial Distributed SCM (version 2.4.2+20130102)", 2, 4, 2),
-    new TestHgVersion("Распределенная SCM Mercurial (версия 2.6.1)", 2, 6, 1)
+    new TestHgVersion("Распределенная SCM Mercurial (версия 2.6.1)", 2, 6, 1),
+    new TestHgVersion("[Mercurial Distributed SCM (version 2.6.2+20130606)]", 2, 6, 2),
+    new TestHgVersion("[Mercurial Distributed SCM (version 2.4.2+20130203)]\n", 2, 4, 2),
+    new TestHgVersion("Mercurial Distributed SCM (version 2.6.2)\n", 2, 6, 2)
   };
 
   public void testParseSupported() throws Exception {
diff --git a/plugins/javaFX/javaFX.iml b/plugins/javaFX/javaFX.iml
index b56fab0..3513259 100644
--- a/plugins/javaFX/javaFX.iml
+++ b/plugins/javaFX/javaFX.iml
@@ -21,6 +21,7 @@
     <orderEntry type="module" module-name="compiler-openapi" />
     <orderEntry type="module" module-name="compiler-impl" />
     <orderEntry type="module" module-name="common-javaFX-plugin" />
+    <orderEntry type="module" module-name="manifest" />
   </component>
 </module>
 
diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
index f989e46..df18ddf 100644
--- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
+++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
@@ -49,6 +49,7 @@
     <referencesSearch implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxControllerFieldSearcher"/>
     <renamePsiElementProcessor implementation="org.jetbrains.plugins.javaFX.JavaFxRenameAttributeProcessor" order="before xmlAttribute"/>
     <completion.contributor implementationClass="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxCompletionContributor" language="XML" order="before xmlNonFirst"/>
+    <manifest.parser.provider implementation="org.jetbrains.plugins.javaFX.manifest.JavaFxManifestHeaderParsers"/>
   </extensions>
 
   <actions>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
index 0becfab..3274603 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
@@ -149,8 +149,8 @@
   }
 
   public static PsiClassType getPropertyClassType(PsiElement field, final String superTypeFQN) {
-    if (field instanceof PsiField) {
-      final PsiType type = ((PsiField)field).getType();
+    if (field instanceof PsiMember) {
+      final PsiType type = PropertyUtil.getPropertyType((PsiMember)field);
       if (type instanceof PsiClassType) {
         final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
         final PsiClass attributeClass = resolveResult.getElement();
@@ -166,6 +166,9 @@
                 return (PsiClassType)propertyType;
               }
             }
+            else {
+              return (PsiClassType)type;
+            }
           }
         }
       }
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 69cb857..41d10e4 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
@@ -7,6 +7,7 @@
 import com.intellij.util.ArrayUtil;
 import com.intellij.xml.XmlAttributeDescriptor;
 import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
 import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
@@ -21,7 +22,7 @@
  * User: anna
  * Date: 1/10/13
  */
-public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor {
+public class JavaFxPropertyAttributeDescriptor extends BasicXmlAttributeDescriptor {
   private final String myName;
   private final PsiClass myPsiClass;
 
@@ -62,7 +63,7 @@
 
   @Override
   public boolean isEnumerated() {
-    return getEnum() != null;
+    return getEnumeratedValues() != null;
   }
 
   @Nullable
@@ -87,7 +88,7 @@
       return new String[] {"true", "false"};
     }
 
-    return ArrayUtil.EMPTY_STRING_ARRAY;
+    return null;
   }
 
   protected boolean isConstant(PsiField enumField) {
@@ -99,13 +100,14 @@
     return aClass != null && aClass.isEnum() ? aClass : null;
   }
 
-  public PsiField getEnumConstant(String attrValue) {
-    if (isEnumerated()) {
-      final PsiClass aClass = getEnum();
-      final PsiField fieldByName = aClass.findFieldByName(attrValue, false);
-      return fieldByName != null ? fieldByName : aClass.findFieldByName(attrValue.toUpperCase(), false);
+  @Override
+  protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) {
+    final PsiClass aClass = getEnum();
+    if (aClass != null) {
+      final PsiField fieldByName = aClass.findFieldByName(value, false);
+      return fieldByName != null ? fieldByName : aClass.findFieldByName(value.toUpperCase(), false);
     }
-    return null;
+    return attributeValue;
   }
 
   @Nullable
@@ -207,6 +209,12 @@
   }
 
   @Override
+  public PsiReference[] getValueReferences(XmlAttributeValue value) {
+    String s = value.getValue();
+    return s != null && !s.startsWith("${") ? super.getValueReferences(value) : PsiReference.EMPTY_ARRAY;
+  }
+
+  @Override
   public String getName(PsiElement context) {
     return getName();
   }
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java
deleted file mode 100644
index ef72a7fb..0000000
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java
+++ /dev/null
@@ -1,60 +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.plugins.javaFX.fxml.refs;
-
-import com.intellij.psi.*;
-import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlAttributeValue;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.ProcessingContext;
-import com.intellij.xml.XmlAttributeDescriptor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyAttributeDescriptor;
-
-/**
-* User: anna
-*/
-class EnumeratedAttributeReferenceProvider extends PsiReferenceProvider {
-  @NotNull
-  @Override
-  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
-    if (element instanceof XmlAttributeValue) {
-      final XmlAttributeValue xmlAttributeValue = (XmlAttributeValue)element;
-      final PsiElement parent = xmlAttributeValue.getParent();
-      if (parent instanceof XmlAttribute) {
-        final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
-        if (descriptor instanceof JavaFxPropertyAttributeDescriptor && descriptor.isEnumerated()) {
-          final PsiField enumConstant = ((JavaFxPropertyAttributeDescriptor)descriptor).getEnumConstant(xmlAttributeValue.getValue());
-          return new PsiReference[] {new PsiReferenceBase<XmlAttributeValue>(xmlAttributeValue){
-            @Nullable
-            @Override
-            public PsiElement resolve() {
-              return enumConstant;
-            }
-
-            @NotNull
-            @Override
-            public Object[] getVariants() {
-              return ArrayUtil.EMPTY_OBJECT_ARRAY;
-            }
-          }};
-        }
-      }
-    }
-     return PsiReference.EMPTY_ARRAY;
-  }
-}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
index d3b6a97..baaa54d 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
@@ -102,9 +102,6 @@
                                         new ImportReferenceProvider());
 
     registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(attributeValueInFxml),
-                                        new EnumeratedAttributeReferenceProvider()); 
-
-    registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(attributeValueInFxml),
                                         new JavaFxColorReferenceProvider()); 
 
     registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue()
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
index 2e04ca9..a348d38 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
@@ -63,7 +63,7 @@
           if (resolve instanceof PsiMember) {
             if (!JavaFxPsiUtil.isVisibleInFxml((PsiMember)resolve)) {
               final String symbolPresentation = "'" + SymbolPresentationUtil.getSymbolPresentableText(resolve) + "'";
-              final Annotation annotation = holder.createErrorAnnotation(element, 
+              final Annotation annotation = holder.createErrorAnnotation(element,
                                                                          symbolPresentation + (resolve instanceof PsiClass ? " should be public" : " should be public or annotated with @FXML"));
               if (!(resolve instanceof PsiClass)) {
                 annotation.registerUniversalFix(new AddAnnotationFix(JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, (PsiMember)resolve, ArrayUtil.EMPTY_STRING_ARRAY), null, null);
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
index 432e3eea..ca308cd 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
@@ -93,7 +93,7 @@
   public static class JavaFxUnresolvedReferenceHandlerQuickfixProvider extends UnresolvedReferenceQuickFixProvider<JavaFxEventHandlerReference> {
 
     @Override
-    public void registerFixes(final JavaFxEventHandlerReference ref, final QuickFixActionRegistrar registrar) {
+    public void registerFixes(@NotNull final JavaFxEventHandlerReference ref, @NotNull final QuickFixActionRegistrar registrar) {
       if (ref.myController != null && ref.myEventHandler == null) {
         final CreateMethodQuickFix quickFix = CreateMethodQuickFix.createFix(ref.myController, getHandlerSignature(ref), "");
         if (quickFix != null) {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
index c7b8522..e01234f 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
@@ -60,7 +60,7 @@
 
   public static class JavaFxUnresolvedTagRefsProvider extends UnresolvedReferenceQuickFixProvider<JavaFxTagNameReference> {
     @Override
-    public void registerFixes(JavaFxTagNameReference ref, QuickFixActionRegistrar registrar) {
+    public void registerFixes(@NotNull JavaFxTagNameReference ref, @NotNull QuickFixActionRegistrar registrar) {
       XmlTag element = ref.getTagElement();
       if (element != null) {
         registrar.register(new JavaFxImportClassFix(ref, element) {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/manifest/JavaFxManifestHeaderParsers.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/manifest/JavaFxManifestHeaderParsers.java
new file mode 100644
index 0000000..0151143
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/manifest/JavaFxManifestHeaderParsers.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007-2009, Osmorc Development Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright notice, this list
+ *       of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice, this
+ *       list of conditions and the following disclaimer in the documentation and/or other
+ *       materials provided with the distribution.
+ *     * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
+ *       used to endorse or promote products derived from this software without specific
+ *       prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.jetbrains.plugins.javaFX.manifest;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.lang.manifest.header.HeaderParser;
+import org.jetbrains.lang.manifest.header.HeaderParserProvider;
+import org.jetbrains.lang.manifest.header.impl.StandardHeaderParser;
+
+import java.util.Map;
+
+public class JavaFxManifestHeaderParsers implements HeaderParserProvider {
+  private final Map<String, HeaderParser> myParsers;
+
+  public JavaFxManifestHeaderParsers() {
+    myParsers = ContainerUtil.newHashMap();
+    myParsers.put("JavaFX-Application-Class", StandardHeaderParser.INSTANCE);
+    myParsers.put("JavaFX-Version", StandardHeaderParser.INSTANCE);
+    myParsers.put("JavaFX-Class-Path", StandardHeaderParser.INSTANCE);
+    myParsers.put("JavaFX-Preloader-Class", StandardHeaderParser.INSTANCE);
+    myParsers.put("JavaFX-Fallback-Class", StandardHeaderParser.INSTANCE);
+  }
+
+  @NotNull
+  @Override
+  public Map<String, HeaderParser> getHeaderParsers() {
+    return myParsers;
+  }
+}
diff --git a/plugins/javaFX/testData/highlighting/enumValues.fxml b/plugins/javaFX/testData/highlighting/enumValues.fxml
index 251ead1..c48b589 100644
--- a/plugins/javaFX/testData/highlighting/enumValues.fxml
+++ b/plugins/javaFX/testData/highlighting/enumValues.fxml
@@ -4,5 +4,5 @@
 <?import javafx.scene.control.*?>
 
 <GridPane xmlns:fx="http://javafx.com/fxml" alignment="center">
-    <HBox alignment="<error descr="Cannot resolve symbol 'UNKNOWN'">UNKNOWN</error>"/>
+    <HBox alignment="<error descr="Wrong attribute value">UNKNOWN</error>"/>
 </GridPane>
\ No newline at end of file
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
index 0caff423..6b710ff 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
@@ -78,7 +78,13 @@
   @NotNull
   @Override
   public MavenProjectConfiguration getMavenProjectConfiguration(BuildDataPaths paths) {
-    final File configFile = new File(paths.getDataStorageRoot(), MavenProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+    final File dataStorageRoot = paths.getDataStorageRoot();
+    return getMavenProjectConfiguration(dataStorageRoot);
+  }
+
+  @NotNull
+  public MavenProjectConfiguration getMavenProjectConfiguration(@NotNull File dataStorageRoot) {
+    final File configFile = new File(dataStorageRoot, MavenProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
     MavenProjectConfiguration config;
     synchronized (myLoadedConfigs) {
       config = myLoadedConfigs.get(configFile);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/ResolveReferenceQuickFixProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/ResolveReferenceQuickFixProvider.java
index 15cb9f9..3ce874b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/ResolveReferenceQuickFixProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/ResolveReferenceQuickFixProvider.java
@@ -22,7 +22,7 @@
 
 public class ResolveReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
 
-  public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new AddMavenDependencyQuickFix(ref));
   }
 
diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesRefactoringSupportProvider.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesRefactoringSupportProvider.java
index fbb2454..5c3fd1f 100644
--- a/plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesRefactoringSupportProvider.java
+++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesRefactoringSupportProvider.java
@@ -21,9 +21,10 @@
 
 import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
 
 public class PropertiesRefactoringSupportProvider extends RefactoringSupportProvider {
-  public boolean isSafeDeleteAvailable(PsiElement element) {
+  public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
     return true;
   }
 }
\ No newline at end of file
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 dc89bb2..13b8e7d 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
@@ -37,13 +37,25 @@
  * @author Dmitry Avdeev
  */
 @Tag("server")
-public abstract class TaskRepository  {
+public abstract class TaskRepository {
 
   protected static final int NO_FEATURES = 0;
   public static final int BASIC_HTTP_AUTHORIZATION = 0x0001;
   public static final int LOGIN_ANONYMOUSLY = 0x0002;
   public static final int TIME_MANAGEMENT = 0x0004;
   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
+   * 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
+   */
+  public static final int NATIVE_SEARCH = 0x0010;
 
   @Attribute("url")
   public String getUrl() {
@@ -79,7 +91,8 @@
    * @deprecated
    * @see #createCancellableConnection()
    */
-  public void testConnection() throws Exception {}
+  public void testConnection() throws Exception {
+  }
 
   /**
    * Returns an object that can test connection.
@@ -93,9 +106,10 @@
 
   /**
    * 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.
    *
    * @param query repository specific.
-   * @param max maximum issues number to return
+   * @param max   maximum issues number to return
    * @param since last updated timestamp. If 0, all issues should be returned.
    * @return found issues
    * @throws Exception
@@ -228,13 +242,28 @@
     public abstract void cancel();
   }
 
-  public boolean isSupported(@MagicConstant(
-    flags = {NO_FEATURES, BASIC_HTTP_AUTHORIZATION, LOGIN_ANONYMOUSLY, STATE_UPDATING, TIME_MANAGEMENT}) int feature) {
+  public boolean isSupported(
+    @MagicConstant(
+      flags = {
+        NO_FEATURES,
+        BASIC_HTTP_AUTHORIZATION,
+        LOGIN_ANONYMOUSLY,
+        STATE_UPDATING,
+        TIME_MANAGEMENT,
+        NATIVE_SEARCH}
+    ) int feature) {
     return (getFeatures() & feature) != 0;
   }
 
-  @MagicConstant(flags = { NO_FEATURES, BASIC_HTTP_AUTHORIZATION, LOGIN_ANONYMOUSLY, STATE_UPDATING, TIME_MANAGEMENT})
+  @MagicConstant(
+    flags = {
+      NO_FEATURES,
+      BASIC_HTTP_AUTHORIZATION,
+      LOGIN_ANONYMOUSLY,
+      STATE_UPDATING,
+      TIME_MANAGEMENT,
+      NATIVE_SEARCH})
   protected int getFeatures() {
-    return NO_FEATURES;
+    return NATIVE_SEARCH;
   }
 }
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositorySubtype.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositorySubtype.java
new file mode 100644
index 0000000..e7c0991
--- /dev/null
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositorySubtype.java
@@ -0,0 +1,32 @@
+/*
+ * 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.tasks;
+
+import javax.swing.*;
+
+/**
+ * This auxiliary interface was added to support creation of configured generic repositories.
+ * Every TaskRepositoryType subclass can be considered subtype of its own.
+ *
+ * @author Mikhail Golubev
+ */
+public interface TaskRepositorySubtype {
+  String getName();
+
+  Icon getIcon();
+
+  TaskRepository createRepository();
+}
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
index e947be9..96f0c94 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
@@ -23,14 +23,16 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.List;
 
 /**
  * The main extension point for issue tracking integration.
  *
  * @author Dmitry Avdeev
  */
-public abstract class TaskRepositoryType<T extends TaskRepository> {
+public abstract class TaskRepositoryType<T extends TaskRepository> implements TaskRepositorySubtype {
 
   public static final ExtensionPointName<TaskRepositoryType> EP_NAME = new ExtensionPointName<TaskRepositoryType>("com.intellij.tasks.repositoryType");
 
@@ -46,6 +48,15 @@
   @NotNull
   public abstract TaskRepositoryEditor createEditor(T repository, Project project, Consumer<T> changeListener);
 
+  public List<TaskRepositorySubtype> getAvailableSubtypes() {
+    return Arrays.asList((TaskRepositorySubtype)this);
+  }
+
+  @NotNull
+  public TaskRepository createRepository(TaskRepositorySubtype subtype) {
+    return subtype.createRepository();
+  }
+
   @NotNull
   public abstract TaskRepository createRepository();
 
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
index c290829..d0058ec 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
@@ -61,7 +61,7 @@
   private JButton myProxySettingsButton;
   protected JCheckBox myUseHttpAuthenticationCheckBox;
 
-  private JPanel myCustomPanel;
+  protected JPanel myCustomPanel;
   private JBCheckBox myAddCommitMessage;
   private JBLabel myComment;
   private JPanel myEditorPanel;
@@ -150,6 +150,16 @@
     loginAnonymouslyChanged(!myLoginAnonymouslyJBCheckBox.isSelected());
   }
 
+
+  protected final void updateCustomPanel() {
+    myCustomPanel.removeAll();
+    JComponent customPanel = createCustomPanel();
+    if (customPanel != null) {
+      myCustomPanel.add(customPanel, BorderLayout.CENTER);
+    }
+    myCustomPanel.repaint();
+  }
+
   private void loginAnonymouslyChanged(boolean enabled) {
     myUsernameLabel.setEnabled(enabled);
     myUserNameText.setEnabled(enabled);
diff --git a/plugins/tasks/tasks-core/lib/json-path-0.8.0.jar b/plugins/tasks/tasks-core/lib/json-path-0.8.0.jar
new file mode 100644
index 0000000..e165784
--- /dev/null
+++ b/plugins/tasks/tasks-core/lib/json-path-0.8.0.jar
Binary files differ
diff --git a/plugins/tasks/tasks-core/lib/json-smart-1.1.1.jar b/plugins/tasks/tasks-core/lib/json-smart-1.1.1.jar
new file mode 100644
index 0000000..9cdad9f
--- /dev/null
+++ b/plugins/tasks/tasks-core/lib/json-smart-1.1.1.jar
Binary files differ
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskRepositoriesConfigurable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskRepositoriesConfigurable.java
index 1b5ad85..e021c94 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskRepositoriesConfigurable.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskRepositoriesConfigurable.java
@@ -14,6 +14,7 @@
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.tasks.TaskRepositorySubtype;
 import com.intellij.tasks.TaskManager;
 import com.intellij.tasks.TaskRepository;
 import com.intellij.tasks.TaskRepositoryType;
@@ -83,18 +84,19 @@
 
     TaskRepositoryType[] groups = TaskManager.ourRepositoryTypes;
 
-    final List<AnAction> createActions = ContainerUtil.map2List(groups, new Function<TaskRepositoryType, AnAction>() {
-      public AnAction fun(final TaskRepositoryType group) {
-        String description = "New " + group.getName() + " server";
-        return new IconWithTextAction(group.getName(), description, group.getIcon()) {
+    final List<AnAction> createActions = new ArrayList<AnAction>();
+    for (final TaskRepositoryType repositoryType : groups) {
+      for (final TaskRepositorySubtype subtype : (List<TaskRepositorySubtype>)repositoryType.getAvailableSubtypes()) {
+        String description = "New " + subtype.getName() + " server";
+        createActions.add(new IconWithTextAction(subtype.getName(), description, subtype.getIcon()) {
           @Override
           public void actionPerformed(AnActionEvent e) {
-            TaskRepository repository = group.createRepository();
+            TaskRepository repository = repositoryType.createRepository(subtype);
             addRepository(repository);
           }
-        };
+        });
       }
-    });
+    }
 
     ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myRepositoriesList).disableUpDownActions();
 
@@ -110,7 +112,7 @@
         if (!repositories.isEmpty()) {
           group.add(Separator.getInstance());
           for (final TaskRepository repository : repositories) {
-            group.add(new IconWithTextAction(repository.getUrl(), repository.getUrl(), repository.getRepositoryType().getIcon()) {
+            group.add(new IconWithTextAction(repository.getUrl(), repository.getUrl(), repository.getIcon()) {
               @Override
               public void actionPerformed(AnActionEvent e) {
                 addRepository(repository);
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 8245c9e..7177d44 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
@@ -1,58 +1,83 @@
 package com.intellij.tasks.generic;
 
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.io.StreamUtil;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.XmlElementFactory;
-import com.intellij.psi.xml.XmlTag;
 import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskRepositorySubtype;
 import com.intellij.tasks.TaskRepositoryType;
-import com.intellij.tasks.actions.TaskSearchSupport;
 import com.intellij.tasks.impl.BaseRepositoryImpl;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.net.HTTPMethod;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
 import com.intellij.util.xmlb.annotations.Tag;
-import com.intellij.xml.util.XmlUtil;
-import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.commons.httpclient.methods.PostMethod;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import javax.swing.*;
+import java.util.*;
+
+import static com.intellij.tasks.generic.GenericRepositoryUtil.concat;
+import static com.intellij.tasks.generic.TemplateVariable.*;
 
 /**
- * User: Evgeny.Zakrevsky
- * Date: 10/4/12
+ * @author Evgeny.Zakrevsky
  */
 @Tag("Generic")
 public class GenericRepository extends BaseRepositoryImpl {
-  private String myTasksListURL = "";
-  private String myTaskPattern = "";
+  private static final Logger LOG = Logger.getInstance(GenericRepository.class);
+
+  public final PredefinedFactoryVariable SERVER_URL_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("serverUrl") {
+    @Override
+    public String getValue() {
+      return GenericRepository.this.getUrl();
+    }
+  };
+  public final PredefinedFactoryVariable USERNAME_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("username") {
+    @Override
+    public String getValue() {
+      return GenericRepository.this.getUsername();
+    }
+  };
+  public final PredefinedFactoryVariable PASSWORD_TEMPLATE_VARIABLE = new PredefinedFactoryVariable("password", true) {
+    @Override
+    public String getValue() {
+      return GenericRepository.this.getPassword();
+    }
+  };
+
+  public final List<TemplateVariable> PREDEFINED_TEMPLATE_VARIABLES = ContainerUtil.<TemplateVariable>newSmartList(
+    SERVER_URL_TEMPLATE_VARIABLE,
+    USERNAME_TEMPLATE_VARIABLE,
+    PASSWORD_TEMPLATE_VARIABLE
+  );
+
   private String myLoginURL = "";
-  private String myLoginMethodType = GenericRepositoryEditor.GET;
-  private String myTasksListMethodType = GenericRepositoryEditor.GET;
+  private String myTasksListUrl = "";
+  private String mySingleTaskUrl;
+
+  private HTTPMethod myLoginMethodType = HTTPMethod.GET;
+  private HTTPMethod myTasksListMethodType = HTTPMethod.GET;
+  private HTTPMethod mySingleTaskMethodType = HTTPMethod.GET;
+
   private ResponseType myResponseType = ResponseType.XML;
+
+  private EnumMap<ResponseType, ResponseHandler> myResponseHandlersMap = new EnumMap<ResponseType, ResponseHandler>(ResponseType.class);
+
   private List<TemplateVariable> myTemplateVariables = new ArrayList<TemplateVariable>();
 
-  final static String SERVER_URL_PLACEHOLDER = "{serverUrl}";
-  final static String USERNAME_PLACEHOLDER = "{username}";
-  final static String PASSWORD_PLACEHOLDER = "{password}";
-  final static String ID_PLACEHOLDER = "{id}";
-  final static String SUMMARY_PLACEHOLDER = "{summary}";
-  final static String QUERY_PLACEHOLDER = "{query}";
-  final static String MAX_COUNT_PLACEHOLDER = "{count}";
-  //todo
-  final static String DESCRIPTION_PLACEHOLDER = "{description}";
-  //todo
-  final static String PAGE_PLACEHOLDER = "{page}";
+  private String mySubtypeName;
 
+  /**
+   * Serialization constructor
+   */
   @SuppressWarnings({"UnusedDeclaration"})
   public GenericRepository() {
+    // empty
   }
 
   public GenericRepository(final TaskRepositoryType type) {
@@ -60,152 +85,43 @@
     resetToDefaults();
   }
 
+  /**
+   * Cloning constructor
+   */
   public GenericRepository(final GenericRepository other) {
     super(other);
-    myTasksListURL = other.getTasksListURL();
-    myTaskPattern = other.getTaskPattern();
-    myLoginURL = other.getLoginURL();
+    myLoginURL = other.getLoginUrl();
+    myTasksListUrl = other.getTasksListUrl();
+    mySingleTaskUrl = other.getSingleTaskUrl();
+
     myLoginMethodType = other.getLoginMethodType();
     myTasksListMethodType = other.getTasksListMethodType();
+    mySingleTaskMethodType = other.getSingleTaskMethodType();
+
     myResponseType = other.getResponseType();
     myTemplateVariables = other.getTemplateVariables();
-  }
-
-  @Override
-  public boolean isConfigured() {
-    return StringUtil.isNotEmpty(myTasksListURL) && StringUtil.isNotEmpty(myTaskPattern);
-  }
-
-  @Override
-  public Task[] getIssues(@Nullable final String query, final int max, final long since) throws Exception {
-    final HttpClient httpClient = getHttpClient();
-
-    if (!isLoginAnonymously() && !isUseHttpAuthentication()) login(httpClient);
-
-    final HttpMethod method = getTaskListsMethod(query != null ? query : "", max);
-    httpClient.executeMethod(method);
-    if (method.getStatusCode() != 200) throw new Exception("Cannot get tasks: HTTP status code " + method.getStatusCode());
-    final String response = method.getResponseBodyAsString();
-    return parseResponse(query, max, response);
-  }
-
-  public Task[] parseResponse(String query, int max, String response) throws Exception {
-
-    final List<String> placeholders = getPlaceholders(getTaskPattern());
-    if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
-      throw new Exception("Incorrect Task Pattern");
+    myResponseHandlersMap = new EnumMap<ResponseType, ResponseHandler>(ResponseType.class);
+    mySubtypeName = other.mySubtypeName;
+    for (Map.Entry<ResponseType, ResponseHandler> e : other.myResponseHandlersMap.entrySet()) {
+      ResponseHandler handler = e.getValue().clone();
+      handler.setRepository(this);
+      myResponseHandlersMap.put(e.getKey(), handler);
     }
-
-    final String taskPatternWithoutPlaceholders = getTaskPattern().replaceAll("\\{.+?\\}", "");
-    Matcher matcher = Pattern
-      .compile(taskPatternWithoutPlaceholders,
-               Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.UNICODE_CASE | Pattern.CANON_EQ)
-      .matcher(response);
-
-    List<Task> tasks = new ArrayList<Task>();
-    while (matcher.find()) {
-      String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1);
-      String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1);
-      if (myResponseType == ResponseType.XML && summary != null) {
-        final String finalSummary = summary;
-        summary = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
-          @Override
-          public String compute() {
-            XmlElementFactory factory = XmlElementFactory.getInstance(ProjectManager.getInstance().getDefaultProject());
-            XmlTag text = factory.createTagFromText("<a>" + finalSummary + "</a>");
-            return XmlUtil.decode(text.getValue().getTrimmedText());
-          }
-        });
-      }
-      tasks.add(new GenericTask(id, summary, this));
-    }
-
-    final boolean searchSupported = getTasksListURL().contains(QUERY_PLACEHOLDER);
-    if (!searchSupported) {
-      tasks = TaskSearchSupport.filterTasks(query != null ? query : "", tasks);
-    }
-
-    tasks = tasks.subList(0, Math.min(max, tasks.size()));
-
-    return tasks.toArray(new Task[tasks.size()]);
   }
 
-  private HttpMethod getTaskListsMethod(final String query, final int max) {
-    String requestUrl = getFullTasksUrl(query, max);
-    final HttpMethod method =
-      GenericRepositoryEditor.GET.equals(getTasksListMethodType()) ? new GetMethod(requestUrl) : getPostMethodFromURL(requestUrl);
-    configureHttpMethod(method);
-    return method;
-  }
-
-  @Override
-  protected void configureHttpMethod(final HttpMethod method) {
-    super.configureHttpMethod(method);
-    method.addRequestHeader("accept", getResponseType().getMimeType());
-  }
-
-  private void login(final HttpClient httpClient) throws Exception {
-    final HttpMethod method = getLoginMethod();
-    httpClient.executeMethod(method);
-    if (method.getStatusCode() != 200) throw new Exception("Cannot login: HTTP status code " + method.getStatusCode());
-  }
-
-  private HttpMethod getLoginMethod() {
-    String requestUrl = getFullLoginUrl();
-    return GenericRepositoryEditor.GET.equals(getLoginMethodType()) ? new GetMethod(requestUrl) : getPostMethodFromURL(requestUrl);
-  }
-
-  private static HttpMethod getPostMethodFromURL(final String requestUrl) {
-    int n = requestUrl.indexOf('?');
-    if (n == -1) {
-      return new PostMethod(requestUrl);
-    }
-
-    PostMethod postMethod = new PostMethod(requestUrl.substring(0, n));
-    n = requestUrl.indexOf('?');
-    String[] requestParams = requestUrl.substring(n + 1).split("&");
-    for (String requestParam : requestParams) {
-      String[] nv = requestParam.split("=");
-      if (nv.length == 1) {
-        postMethod.addParameter(nv[0], "");
-      } else {
-        postMethod.addParameter(nv[0], nv[1]);
-      }
-    }
-    return postMethod;
-  }
-
-  private static List<String> getPlaceholders(String value) {
-    if (value == null) {
-      return ContainerUtil.emptyList();
-    }
-
-    List<String> vars = new ArrayList<String>();
-    Matcher m = Pattern.compile("\\{(.+?)\\}").matcher(value);
-    while (m.find()) {
-      vars.add(m.group(0));
-    }
-    return vars;
-  }
-
-  private String getFullTasksUrl(final String query, final int max) {
-    return replaceTemplateVariables(getTasksListURL())
-      .replaceAll(Pattern.quote(SERVER_URL_PLACEHOLDER), getUrl())
-      .replaceAll(Pattern.quote(QUERY_PLACEHOLDER), encodeUrl(query))
-      .replaceAll(Pattern.quote(MAX_COUNT_PLACEHOLDER), String.valueOf(max));
-  }
-
-  private String getFullLoginUrl() {
-    return replaceTemplateVariables(getLoginURL())
-      .replaceAll(Pattern.quote(SERVER_URL_PLACEHOLDER), getUrl())
-      .replaceAll(Pattern.quote(USERNAME_PLACEHOLDER), encodeUrl(getUsername()))
-      .replaceAll(Pattern.quote(PASSWORD_PLACEHOLDER), encodeUrl(getPassword()));
-  }
-
-  @Nullable
-  @Override
-  public Task findTask(final String id) throws Exception {
-    return null;
+  public void resetToDefaults() {
+    myLoginURL = "";
+    myTasksListUrl = "";
+    mySingleTaskUrl = "";
+    myLoginMethodType = HTTPMethod.GET;
+    myTasksListMethodType = HTTPMethod.GET;
+    mySingleTaskMethodType = HTTPMethod.GET;
+    myResponseType = ResponseType.XML;
+    myTemplateVariables = new ArrayList<TemplateVariable>();
+    myResponseHandlersMap = new EnumMap<ResponseType, ResponseHandler>(ResponseType.class);
+    myResponseHandlersMap.put(ResponseType.XML, getXmlResponseHandlerDefault());
+    myResponseHandlersMap.put(ResponseType.JSON, getJsonResponseHandlerDefault());
+    myResponseHandlersMap.put(ResponseType.TEXT, getTextResponseHandlerDefault());
   }
 
   @Override
@@ -219,24 +135,100 @@
     if (!(o instanceof GenericRepository)) return false;
     if (!super.equals(o)) return false;
     GenericRepository that = (GenericRepository)o;
-    if (!Comparing.equal(getTasksListURL(), that.getTasksListURL())) return false;
-    if (!Comparing.equal(getTaskPattern(), that.getTaskPattern())) return false;
-    if (!Comparing.equal(getLoginURL(), that.getLoginURL())) return false;
+    if (!Comparing.equal(getLoginUrl(), that.getLoginUrl())) return false;
+    if (!Comparing.equal(getTasksListUrl(), that.getTasksListUrl())) return false;
+    if (!Comparing.equal(getSingleTaskUrl(), that.getSingleTaskUrl())) return false;
     if (!Comparing.equal(getLoginMethodType(), that.getLoginMethodType())) return false;
     if (!Comparing.equal(getTasksListMethodType(), that.getTasksListMethodType())) return false;
+    if (!Comparing.equal(getSingleTaskMethodType(), that.getSingleTaskMethodType())) return false;
     if (!Comparing.equal(getResponseType(), that.getResponseType())) return false;
     if (!Comparing.equal(getTemplateVariables(), that.getTemplateVariables())) return false;
+    if (!Comparing.equal(getResponseHandlers(), that.getResponseHandlers())) return false;
     return true;
   }
 
+  @Override
+  public boolean isConfigured() {
+    if (!super.isConfigured()) return false;
+    for (TemplateVariable variable : getTemplateVariables()) {
+      if (variable.getIsShownOnFirstTab() && StringUtil.isEmpty(variable.getValue())) {
+        return false;
+      }
+    }
+    return StringUtil.isNotEmpty(myTasksListUrl) && getActiveResponseHandler().isConfigured();
+  }
+
+  @Override
+  public Task[] getIssues(@Nullable final String query, final int max, final long since) throws Exception {
+    if (!isLoginAnonymously() && !isUseHttpAuthentication()) {
+      executeMethod(getLoginMethod());
+    }
+    List<TemplateVariable> variables = concat(getAllTemplateVariables(),
+                                              new TemplateVariable("max", max),
+                                              new TemplateVariable("since", since));
+    String requestUrl = GenericRepositoryUtil.substituteTemplateVariables(getTasksListUrl(), variables);
+    String responseBody = executeMethod(getHttpMethod(requestUrl, myTasksListMethodType));
+    Task[] tasks = getActiveResponseHandler().parseIssues(responseBody);
+    if (!StringUtil.isEmpty(mySingleTaskUrl) && !(myResponseType == ResponseType.TEXT)) {
+      for (int i = 0; i < tasks.length; i++) {
+        tasks[i] = findTask(tasks[i].getId());
+      }
+    }
+    return tasks;
+  }
+
+  private String executeMethod(HttpMethod method) throws Exception {
+    LOG.debug("URI is " + method.getURI());
+    String responseBody;
+    try {
+      getHttpClient().executeMethod(method);
+      Header contentType = method.getResponseHeader("Content-Type");
+      if (contentType != null && contentType.getValue().contains("charset")) {
+        // ISO-8859-1 if charset wasn't specified in response
+        responseBody = method.getResponseBodyAsString();
+      }
+      else {
+        responseBody = StreamUtil.readText(method.getResponseBodyAsStream(), "utf-8");
+      }
+    }
+    finally {
+      method.releaseConnection();
+    }
+    LOG.debug(responseBody);
+    LOG.debug("Status code is " + method.getStatusCode());
+    if (method.getStatusCode() != HttpStatus.SC_OK) {
+      throw new Exception("Request failed with HTTP error: " + method.getStatusText());
+    }
+    return responseBody;
+  }
+
+  private HttpMethod getHttpMethod(String requestUrl, HTTPMethod type) {
+    HttpMethod method = type == HTTPMethod.GET ? new GetMethod(requestUrl) : GenericRepositoryUtil.getPostMethodFromURL(requestUrl);
+    configureHttpMethod(method);
+    return method;
+  }
+
+  private HttpMethod getLoginMethod() {
+    String requestUrl = GenericRepositoryUtil.substituteTemplateVariables(getLoginUrl(), getAllTemplateVariables());
+    return getHttpMethod(requestUrl, myLoginMethodType);
+  }
+
+  @Nullable
+  @Override
+  public Task findTask(final String id) throws Exception {
+    List<TemplateVariable> variables = concat(getAllTemplateVariables(), new TemplateVariable("id", id));
+    String requestUrl = GenericRepositoryUtil.substituteTemplateVariables(getSingleTaskUrl(), variables);
+    HttpMethod method = getHttpMethod(requestUrl, mySingleTaskMethodType);
+    return getActiveResponseHandler().parseIssue(executeMethod(method));
+  }
+
   @Nullable
   @Override
   public CancellableConnection createCancellableConnection() {
     return new CancellableConnection() {
       @Override
       protected void doTest() throws Exception {
-        final Task[] issues = getIssues("", 1, 0);
-        if (issues.length == 0) throw new Exception("Tasks not found. Probably, you don't login.");
+        getIssues("", 1, 0);
       }
 
       @Override
@@ -245,38 +237,54 @@
     };
   }
 
-  private String replaceTemplateVariables(String s) {
-    String answer = new String(s);
-    for (TemplateVariable templateVariable : getTemplateVariables()) {
-      answer = answer.replaceAll(Pattern.quote("{" + templateVariable.getName() + "}"), templateVariable.getValue());
-    }
-    return answer;
+  public void setLoginUrl(final String loginUrl) {
+    myLoginURL = loginUrl;
   }
 
-  public String getLoginURL() {
+  public void setTasksListUrl(final String tasksListUrl) {
+    myTasksListUrl = tasksListUrl;
+  }
+
+  public void setSingleTaskUrl(String singleTaskUrl) {
+    mySingleTaskUrl = singleTaskUrl;
+  }
+
+  public String getLoginUrl() {
     return myLoginURL;
   }
 
-  public void setLoginURL(final String loginURL) {
-    myLoginURL = loginURL;
+  public String getTasksListUrl() {
+    return myTasksListUrl;
   }
 
-  public void setLoginMethodType(final String loginMethodType) {
+  public String getSingleTaskUrl() {
+    return mySingleTaskUrl;
+  }
+
+  public void setLoginMethodType(final HTTPMethod loginMethodType) {
     myLoginMethodType = loginMethodType;
   }
 
-  public void setTasksListMethodType(final String tasksListMethodType) {
+  public void setTasksListMethodType(final HTTPMethod tasksListMethodType) {
     myTasksListMethodType = tasksListMethodType;
   }
 
-  public String getLoginMethodType() {
+  public void setSingleTaskMethodType(HTTPMethod singleTaskMethodType) {
+    mySingleTaskMethodType = singleTaskMethodType;
+  }
+
+  public HTTPMethod getLoginMethodType() {
     return myLoginMethodType;
   }
 
-  public String getTasksListMethodType() {
+  public HTTPMethod getTasksListMethodType() {
     return myTasksListMethodType;
   }
 
+  public HTTPMethod getSingleTaskMethodType() {
+    return mySingleTaskMethodType;
+  }
+
   public ResponseType getResponseType() {
     return myResponseType;
   }
@@ -285,70 +293,91 @@
     myResponseType = responseType;
   }
 
-  public String getTasksListURL() {
-    return myTasksListURL;
-  }
-
-  public void setTasksListURL(final String tasksListURL) {
-    myTasksListURL = tasksListURL;
-  }
-
-  public String getTaskPattern() {
-    return myTaskPattern;
-  }
-
-  public void setTaskPattern(final String taskPattern) {
-    myTaskPattern = taskPattern;
-  }
-
   public List<TemplateVariable> getTemplateVariables() {
     return myTemplateVariables;
   }
 
+  /**
+   * Returns all template variables including both predefined and defined by user
+   */
+  public List<TemplateVariable> getAllTemplateVariables() {
+    return ContainerUtil.concat(PREDEFINED_TEMPLATE_VARIABLES, getTemplateVariables());
+  }
+
   public void setTemplateVariables(final List<TemplateVariable> templateVariables) {
     myTemplateVariables = templateVariables;
   }
 
-  public void resetToDefaults() {
-    myTasksListURL = getTasksListURLDefault();
-    myTaskPattern = getTaskPatternDefault();
-    myLoginURL = getLoginURLDefault();
-    myLoginMethodType = getLoginMethodTypeDefault();
-    myTasksListMethodType = getTasksListMethodTypeDefault();
-    myResponseType = getResponseTypeDefault();
-    myTemplateVariables = getTemplateVariablesDefault();
-  }
-
-  protected List<TemplateVariable> getTemplateVariablesDefault() {
-    return new ArrayList<TemplateVariable>();
-  }
-
-  protected ResponseType getResponseTypeDefault() {
-    return ResponseType.XML;
-  }
-
-  protected String getTasksListMethodTypeDefault() {
-    return GenericRepositoryEditor.GET;
-  }
-
-  protected String getLoginMethodTypeDefault() {
-    return GenericRepositoryEditor.GET;
-  }
-
-  protected String getLoginURLDefault() {
-    return "";
-  }
-
-  protected String getTaskPatternDefault() {
-    return "";
-  }
-
-  protected String getTasksListURLDefault() {
-    return "";
+  @Override
+  public Icon getIcon() {
+    if (mySubtypeName == null) {
+      return super.getIcon();
+    }
+    @SuppressWarnings("unchecked")
+    List<TaskRepositorySubtype> subtypes = getRepositoryType().getAvailableSubtypes();
+    for (TaskRepositorySubtype s : subtypes) {
+      if (mySubtypeName.equals(s.getName())) {
+        return s.getIcon();
+      }
+    }
+    throw new AssertionError("Unknown repository subtype");
   }
 
   @Override
   protected int getFeatures() {
     return LOGIN_ANONYMOUSLY | BASIC_HTTP_AUTHORIZATION;
   }
+
+  public ResponseHandler getResponseHandler(ResponseType type) {
+    return myResponseHandlersMap.get(type);
+  }
+
+  public ResponseHandler getActiveResponseHandler() {
+    return myResponseHandlersMap.get(myResponseType);
+  }
+
+  @AbstractCollection(
+    elementTypes = {
+      XPathResponseHandler.class,
+      JsonPathResponseHandler.class,
+      RegExResponseHandler.class
+    },
+    surroundWithTag = false
+  )
+  public List<ResponseHandler> getResponseHandlers() {
+    Collection<ResponseHandler> handlers = myResponseHandlersMap.values();
+    return new ArrayList<ResponseHandler>(handlers);
+  }
+
+  public void setResponseHandlers(List<ResponseHandler> responseHandlers) {
+    myResponseHandlersMap.clear();
+    for (ResponseHandler handler : responseHandlers) {
+      myResponseHandlersMap.put(handler.getResponseType(), handler);
+    }
+    // ResponseHandler#repository field is excluded from serialization to prevent
+    // circular dependency so it has to be done manually during serialization process
+    for (ResponseHandler handler : myResponseHandlersMap.values()) {
+      handler.setRepository(this);
+    }
+  }
+
+  public ResponseHandler getXmlResponseHandlerDefault() {
+    return new XPathResponseHandler(this);
+  }
+
+  public ResponseHandler getJsonResponseHandlerDefault() {
+    return new JsonPathResponseHandler(this);
+  }
+
+  public ResponseHandler getTextResponseHandlerDefault() {
+    return new RegExResponseHandler(this);
+  }
+
+  public String getSubtypeName() {
+    return mySubtypeName;
+  }
+
+  public void setSubtypeName(String subtypeName) {
+    mySubtypeName = subtypeName;
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form
index a04245f..0e86957 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form
@@ -1,149 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.tasks.generic.GenericRepositoryEditor">
-  <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="8">
+  <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="8">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
+      <xy x="20" y="20" width="500" height="438"/>
     </constraints>
     <properties/>
     <border type="none"/>
     <children>
-      <grid id="5918d" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
-        <margin top="0" left="0" bottom="0" right="0"/>
-        <constraints>
-          <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="true"/>
-        </constraints>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="37da0" class="com.intellij.ui.components.JBLabel" binding="myLoginURLLabel">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <labelFor value="a0a2f"/>
-              <text value="Lo&amp;gin URL:"/>
-            </properties>
-          </component>
-          <component id="a0a2f" class="com.intellij.ui.EditorTextField" binding="myLoginURLText" custom-create="true">
-            <constraints>
-              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
-                <preferred-size width="10" height="-1"/>
-              </grid>
-            </constraints>
-            <properties/>
-          </component>
-          <component id="ce0fe" class="com.intellij.ui.components.JBLabel" binding="myLoginTooltip">
-            <constraints>
-              <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <componentStyle value="SMALL"/>
-              <fontColor value="BRIGHTER"/>
-              <text value="tooltip"/>
-            </properties>
-          </component>
-          <component id="eee0a" class="com.intellij.openapi.ui.ComboBox" binding="myLoginMethodTypeComboBox">
-            <constraints>
-              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <model>
-                <item value="GET"/>
-                <item value="POST"/>
-              </model>
-            </properties>
-          </component>
-        </children>
-      </grid>
-      <grid id="294f1" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
-        <margin top="0" left="0" bottom="0" right="0"/>
-        <constraints>
-          <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
-        </constraints>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="6dd8" class="com.intellij.ui.components.JBLabel">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <labelFor value="87697"/>
-              <text value="Tasks &amp;List URL:"/>
-            </properties>
-          </component>
-          <component id="87697" class="com.intellij.ui.EditorTextField" binding="myTasksListURLText" custom-create="true">
-            <constraints>
-              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
-                <preferred-size width="10" height="-1"/>
-              </grid>
-            </constraints>
-            <properties/>
-          </component>
-          <component id="24df4" class="com.intellij.ui.components.JBLabel" binding="myTaskListTooltip">
-            <constraints>
-              <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <componentStyle value="SMALL"/>
-              <fontColor value="BRIGHTER"/>
-              <text value="tooltip"/>
-            </properties>
-          </component>
-          <component id="d1239" class="com.intellij.openapi.ui.ComboBox" binding="myTasksListMethodTypeComboBox">
-            <constraints>
-              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <model>
-                <item value="GET"/>
-                <item value="POST"/>
-              </model>
-            </properties>
-          </component>
-        </children>
-      </grid>
-      <grid id="ab85c" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
-        <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="true"/>
-        </constraints>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="8cc78" class="com.intellij.ui.components.JBLabel">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <labelFor value="a91dc"/>
-              <text value="Task &amp;Pattern:"/>
-            </properties>
-          </component>
-          <component id="21e89" class="com.intellij.ui.components.JBLabel" binding="myTaskPatternTooltip">
-            <constraints>
-              <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <componentStyle value="SMALL"/>
-              <fontColor value="BRIGHTER"/>
-              <text value="tooltip"/>
-            </properties>
-          </component>
-          <component id="a91dc" class="com.intellij.ui.EditorTextField" binding="myTaskPatternText" custom-create="true">
-            <constraints>
-              <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="7" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
-                <preferred-size width="1" height="1"/>
-              </grid>
-            </constraints>
-            <properties/>
-          </component>
-        </children>
-      </grid>
       <component id="df2e4" class="com.intellij.ui.components.JBLabel">
         <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
           <text value="Response Type:"/>
@@ -152,35 +19,43 @@
       <grid id="d68b9" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
-          <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+          <grid row="3" column="1" 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"/>
         <children>
           <component id="7c3b0" class="javax.swing.JRadioButton" binding="myXmlRadioButton">
             <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                <preferred-size width="49" height="44"/>
+              </grid>
             </constraints>
             <properties>
               <text value="X&amp;ML"/>
             </properties>
           </component>
-          <component id="90539" class="javax.swing.JRadioButton" binding="myHtmlRadioButton">
+          <component id="90539" class="javax.swing.JRadioButton" binding="myTextRadioButton">
             <constraints>
-              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                <preferred-size width="51" height="44"/>
+              </grid>
             </constraints>
             <properties>
-              <text value="&amp;HTML"/>
+              <text value="&amp;Text"/>
             </properties>
           </component>
           <hspacer id="cebcb">
             <constraints>
-              <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+              <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+                <preferred-size width="14" height="44"/>
+              </grid>
             </constraints>
           </hspacer>
           <component id="71bfc" class="javax.swing.JRadioButton" binding="myJsonRadioButton">
             <constraints>
-              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                <preferred-size width="55" height="44"/>
+              </grid>
             </constraints>
             <properties>
               <text value="JS&amp;ON"/>
@@ -191,7 +66,7 @@
       <grid id="2e934" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
-          <grid row="4" 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="5" 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"/>
@@ -227,10 +102,102 @@
           </component>
         </children>
       </grid>
+      <grid id="ccd1b" binding="myCardPanel" layout-manager="CardLayout" hgap="0" vgap="0">
+        <constraints>
+          <grid row="4" 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/>
+      </grid>
+      <component id="4acd" class="com.intellij.ui.components.JBLabel" binding="mySingleTaskURLLabel">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="2b4b2"/>
+          <text value="&amp;Single Task URL:"/>
+        </properties>
+      </component>
+      <component id="2b4b2" class="com.intellij.ui.EditorTextField" binding="mySingleTaskURLText" custom-create="true" default-binding="true">
+        <constraints>
+          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+            <preferred-size width="10" height="-1"/>
+          </grid>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="76f26" class="com.intellij.openapi.ui.ComboBox" binding="mySingleTaskMethodComboBox">
+        <constraints>
+          <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <model>
+            <item value="GET"/>
+            <item value="POST"/>
+          </model>
+        </properties>
+      </component>
+      <component id="6dd8" class="com.intellij.ui.components.JBLabel">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="87697"/>
+          <text value="Tasks &amp;List URL:"/>
+        </properties>
+      </component>
+      <component id="87697" class="com.intellij.ui.EditorTextField" binding="myTasksListURLText" custom-create="true">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+            <preferred-size width="10" height="-1"/>
+          </grid>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="d1239" class="com.intellij.openapi.ui.ComboBox" binding="myTasksListMethodTypeComboBox">
+        <constraints>
+          <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <model>
+            <item value="GET"/>
+            <item value="POST"/>
+          </model>
+        </properties>
+      </component>
+      <component id="37da0" class="com.intellij.ui.components.JBLabel" binding="myLoginURLLabel">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <labelFor value="a0a2f"/>
+          <text value="Lo&amp;gin URL:"/>
+        </properties>
+      </component>
+      <component id="a0a2f" class="com.intellij.ui.EditorTextField" binding="myLoginURLText" custom-create="true">
+        <constraints>
+          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+            <preferred-size width="10" height="-1"/>
+          </grid>
+        </constraints>
+        <properties/>
+      </component>
+      <component id="eee0a" class="com.intellij.openapi.ui.ComboBox" binding="myLoginMethodTypeComboBox">
+        <constraints>
+          <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <model>
+            <item value="GET"/>
+            <item value="POST"/>
+          </model>
+        </properties>
+      </component>
     </children>
   </grid>
   <buttonGroups>
-    <group name="myGroup1">
+    <group name="responseTypeGroup">
       <member id="7c3b0"/>
       <member id="90539"/>
       <member id="71bfc"/>
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 d1754a8..0a6b9a1 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
@@ -1,51 +1,57 @@
 package com.intellij.tasks.generic;
 
-import com.intellij.openapi.actionSystem.ActionManager;
-import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.keymap.KeymapUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.util.Condition;
 import com.intellij.tasks.TaskManager;
 import com.intellij.tasks.config.BaseRepositoryEditor;
 import com.intellij.ui.EditorTextField;
 import com.intellij.ui.TextFieldWithAutoCompletion;
-import com.intellij.ui.TextFieldWithAutoCompletionContributor;
 import com.intellij.ui.components.JBLabel;
 import com.intellij.util.Consumer;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.net.HTTPMethod;
+import com.intellij.util.ui.FormBuilder;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
 
-import static com.intellij.tasks.generic.GenericRepository.*;
+import static com.intellij.tasks.generic.GenericRepositoryUtil.concat;
+import static com.intellij.tasks.generic.GenericRepositoryUtil.createPlaceholdersList;
+import static com.intellij.tasks.generic.GenericRepositoryUtil.prettifyVariableName;
 
 /**
- * User: Evgeny.Zakrevsky
- * Date: 10/4/12
+ * @author Evgeny.Zakrevsky
+ * @author Mikhail Golubev
  */
 public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRepositoryEditor<T> {
-  public static final String POST = "POST";
-  public static final String GET = "GET";
-  private EditorTextField myTasksListURLText;
-  private EditorTextField myTaskPatternText;
-  protected JBLabel myLoginURLLabel;
+
   protected EditorTextField myLoginURLText;
+  private EditorTextField myTasksListURLText;
+  private EditorTextField mySingleTaskURLText;
+  protected JBLabel myLoginURLLabel;
   protected ComboBox myLoginMethodTypeComboBox;
   private ComboBox myTasksListMethodTypeComboBox;
-  private JBLabel myLoginTooltip;
-  private JBLabel myTaskListTooltip;
-  private JBLabel myTaskPatternTooltip;
+  private ComboBox mySingleTaskMethodComboBox;
   private JPanel myPanel;
   private JRadioButton myXmlRadioButton;
-  private JRadioButton myHtmlRadioButton;
+  private JRadioButton myTextRadioButton;
   private JButton myTest2Button;
   private JRadioButton myJsonRadioButton;
   private JButton myManageTemplateVariablesButton;
   private JButton myResetToDefaultsButton;
+  private JPanel myCardPanel;
+  private JBLabel mySingleTaskURLLabel;
+
+  private Map<JTextField, TemplateVariable> myField2Variable;
+  private Map<JRadioButton, ResponseType> myRadio2ResponseType;
 
   public GenericRepositoryEditor(final Project project,
                                  final T repository,
@@ -64,7 +70,6 @@
         loginUrlEnablingChanged();
       }
     });
-
     myUseHttpAuthenticationCheckBox.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(final ActionEvent e) {
@@ -72,63 +77,68 @@
       }
     });
 
-    switch (myRepository.getResponseType()) {
-      case XML:
-        myXmlRadioButton.setSelected(true);
-        myHtmlRadioButton.setSelected(false);
-        myJsonRadioButton.setSelected(false);
-        break;
-      case HTML:
-        myXmlRadioButton.setSelected(false);
-        myHtmlRadioButton.setSelected(true);
-        myJsonRadioButton.setSelected(false);
-        break;
-      case JSON:
-        myXmlRadioButton.setSelected(false);
-        myHtmlRadioButton.setSelected(false);
-        myJsonRadioButton.setSelected(true);
-        break;
-    }
-
-    ActionListener listener = new ActionListener() {
+    ActionListener radioButtonListener = new ActionListener() {
       @Override
       public void actionPerformed(final ActionEvent e) {
-        responseTypeChanged();
+        singleTaskUrlEnablingChanged();
+        doApply();
+        selectCardByResponseType();
       }
     };
-    myXmlRadioButton.addActionListener(listener);
-    myHtmlRadioButton.addActionListener(listener);
-    myJsonRadioButton.addActionListener(listener);
+    myXmlRadioButton.addActionListener(radioButtonListener);
+    myTextRadioButton.addActionListener(radioButtonListener);
+    myJsonRadioButton.addActionListener(radioButtonListener);
 
-    myLoginMethodTypeComboBox.setSelectedItem(myRepository.getLoginMethodType());
-    myTasksListMethodTypeComboBox.setSelectedItem(myRepository.getTasksListMethodType());
+    myLoginMethodTypeComboBox.setSelectedItem(myRepository.getLoginMethodType().toString());
+    myTasksListMethodTypeComboBox.setSelectedItem(myRepository.getTasksListMethodType().toString());
+    mySingleTaskMethodComboBox.setSelectedItem(myRepository.getSingleTaskMethodType().toString());
 
+    // set default listener updating model fields
     installListener(myLoginMethodTypeComboBox);
     installListener(myTasksListMethodTypeComboBox);
-    installListener(myTasksListURLText.getDocument());
-    installListener(myLoginURLText.getDocument());
-    installListener(myTaskPatternText.getDocument());
+    installListener(mySingleTaskMethodComboBox);
+    installListener(myLoginURLText);
+    installListener(myTasksListURLText);
+    installListener(mySingleTaskURLText);
+    myTabbedPane.addTab("Server configuration", myPanel);
 
-    String useCompletionText = ". Use " +
-                               KeymapUtil
-                                 .getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION)) +
-                               " for completion.";
-    myLoginTooltip.setText("<html>Available placeholders: " + SERVER_URL_PLACEHOLDER + ", " + USERNAME_PLACEHOLDER + ", " +
-                           PASSWORD_PLACEHOLDER + useCompletionText + "</html>");
-    myTaskListTooltip.setText("<html>Available placeholders: " + SERVER_URL_PLACEHOLDER + ", " + MAX_COUNT_PLACEHOLDER + ", " +
-                              QUERY_PLACEHOLDER + " (use for faster tasks search)" + useCompletionText + "</html>");
-    myTaskPatternTooltip.setText(
-      "<html>Task pattern should be a regexp with two matching groups: ({id}.+?) and ({summary}.+?)" + useCompletionText + "</html>");
+    // Put appropriate configuration components on the card panel
+    ResponseHandler xmlHandler = myRepository.getResponseHandler(ResponseType.XML);
+    ResponseHandler jsonHandler = myRepository.getResponseHandler(ResponseType.JSON);
+    ResponseHandler textHandler = myRepository.getResponseHandler(ResponseType.TEXT);
+    // Select appropriate card pane
+    myCardPanel.add(xmlHandler.getConfigurationComponent(myProject), ResponseType.XML.getMimeType());
+    myCardPanel.add(jsonHandler.getConfigurationComponent(myProject), ResponseType.JSON.getMimeType());
+    myCardPanel.add(textHandler.getConfigurationComponent(myProject), ResponseType.TEXT.getMimeType());
 
-    myTabbedPane.addTab("Additional", myPanel);
+    myRadio2ResponseType = new IdentityHashMap<JRadioButton, ResponseType>();
+    myRadio2ResponseType.put(myJsonRadioButton, ResponseType.JSON);
+    myRadio2ResponseType.put(myXmlRadioButton, ResponseType.XML);
+    myRadio2ResponseType.put(myTextRadioButton, ResponseType.TEXT);
 
     myManageTemplateVariablesButton.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(final ActionEvent e) {
         final ManageTemplateVariablesDialog dialog = new ManageTemplateVariablesDialog(myManageTemplateVariablesButton);
-        dialog.setTemplateVariables(myRepository.getTemplateVariables());
+        dialog.setTemplateVariables(myRepository.getAllTemplateVariables());
         if (dialog.showAndGet()) {
-          myRepository.setTemplateVariables(dialog.getTemplateVariables());
+          myRepository.setTemplateVariables(ContainerUtil.filter(dialog.getTemplateVariables(), new Condition<TemplateVariable>() {
+            @Override
+            public boolean value(TemplateVariable variable) {
+              return !variable.getIsPredefined();
+            }
+          }));
+          myCustomPanel.removeAll();
+          myCustomPanel.add(createCustomPanel());
+          //myCustomPanel.repaint();
+          myTabbedPane.getComponentAt(0).repaint();
+
+          //myLoginURLText = createEditorFieldWithPlaceholderCompletion(myRepository.getLoginUrl());
+          List<String> placeholders = createPlaceholdersList(myRepository);
+          ((TextFieldWithAutoCompletion)myLoginURLText).setVariants(placeholders);
+          ((TextFieldWithAutoCompletion)myTasksListURLText).setVariants(concat(placeholders, "{max}", "{since}"));
+          ((TextFieldWithAutoCompletion)mySingleTaskURLText).setVariants(concat(placeholders, "{id}"));
+          myPanel.repaint();
         }
       }
     });
@@ -137,79 +147,118 @@
       @Override
       public void actionPerformed(final ActionEvent e) {
         myRepository.resetToDefaults();
+        // XXX: Why clone() here?
         reset(myRepository.clone());
       }
     });
 
+    selectRadioButtonByResponseType();
+    selectCardByResponseType();
     loginUrlEnablingChanged();
+    singleTaskUrlEnablingChanged();
   }
 
-  protected void reset(final GenericRepository clone) {
-    myLoginURLText.setText(clone.getLoginURL());
-    myTasksListURLText.setText(clone.getTasksListURL());
-    myTaskPatternText.setText(clone.getTaskPattern());
-    myLoginMethodTypeComboBox.setSelectedItem(clone.getLoginMethodType());
-    myTasksListMethodTypeComboBox.setSelectedItem(clone.getTasksListMethodType());
-    switch (clone.getResponseType()) {
-      case XML:
-        myXmlRadioButton.setSelected(true);
-        myHtmlRadioButton.setSelected(false);
-        myJsonRadioButton.setSelected(false);
-        break;
-      case HTML:
-        myXmlRadioButton.setSelected(false);
-        myHtmlRadioButton.setSelected(true);
-        myJsonRadioButton.setSelected(false);
-        break;
-      case JSON:
-        myXmlRadioButton.setSelected(false);
-        myHtmlRadioButton.setSelected(false);
-        myJsonRadioButton.setSelected(true);
-        break;
-    }
-    responseTypeChanged();
-    loginUrlEnablingChanged();
-  }
-
-  private void responseTypeChanged() {
-    doApply();
-    myTaskPatternText.setFileType(myRepository.getResponseType().getFileType());
+  private void singleTaskUrlEnablingChanged() {
+    boolean enabled = !myTextRadioButton.isSelected();
+    // single task URL doesn't make sense when legacy regex handler is used
+    mySingleTaskURLText.setEnabled(enabled);
+    mySingleTaskMethodComboBox.setEnabled(enabled);
+    mySingleTaskURLLabel.setEnabled(enabled);
   }
 
   protected void loginUrlEnablingChanged() {
-    final boolean enabled = !myLoginAnonymouslyJBCheckBox.isSelected() && !myUseHttpAuthenticationCheckBox.isSelected();
+    boolean enabled = !myLoginAnonymouslyJBCheckBox.isSelected() && !myUseHttpAuthenticationCheckBox.isSelected();
     myLoginURLLabel.setEnabled(enabled);
     myLoginURLText.setEnabled(enabled);
     myLoginMethodTypeComboBox.setEnabled(enabled);
-    myLoginTooltip.setEnabled(enabled);
+  }
+
+  @Nullable
+  @Override
+  protected JComponent createCustomPanel() {
+    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());
+        myField2Variable.put(field, variable);
+        installListener(field);
+        JBLabel label = new JBLabel(prettifyVariableName(variable.getName()) + ":", SwingConstants.RIGHT);
+        label.setAnchor(getAnchor());
+        builder.addLabeledComponent(label, field);
+      }
+    }
+    return builder.getPanel();
+  }
+
+  protected void reset(final GenericRepository clone) {
+    myLoginURLText.setText(clone.getLoginUrl());
+    myTasksListURLText.setText(clone.getTasksListUrl());
+    mySingleTaskURLText.setText(clone.getSingleTaskUrl());
+    //myTaskPatternText.setText(clone.getTaskPattern());
+    myLoginMethodTypeComboBox.setSelectedItem(clone.getLoginMethodType());
+    myTasksListMethodTypeComboBox.setSelectedItem(clone.getTasksListMethodType());
+    mySingleTaskMethodComboBox.setSelectedItem(clone.getSingleTaskMethodType());
+    selectRadioButtonByResponseType();
+    selectCardByResponseType();
+    loginUrlEnablingChanged();
+  }
+
+  private void selectRadioButtonByResponseType() {
+    for (Map.Entry<JRadioButton, ResponseType> entry : myRadio2ResponseType.entrySet()) {
+      if (entry.getValue() == myRepository.getResponseType()) {
+        entry.getKey().setSelected(true);
+      }
+    }
+  }
+
+  private void selectCardByResponseType() {
+    CardLayout cardLayout = (CardLayout) myCardPanel.getLayout();
+    cardLayout.show(myCardPanel, myRepository.getResponseType().getMimeType());
   }
 
   @Override
   public void apply() {
-    myRepository.setTasksListURL(myTasksListURLText.getText());
-    myRepository.setTaskPattern(myTaskPatternText.getDocument().getText());
-    myRepository.setLoginURL(myLoginURLText.getText());
-    myRepository.setLoginMethodType((String)myLoginMethodTypeComboBox.getModel().getSelectedItem());
-    myRepository.setTasksListMethodType((String)myTasksListMethodTypeComboBox.getModel().getSelectedItem());
-    myRepository.setResponseType(
-      myXmlRadioButton.isSelected() ? ResponseType.XML : myJsonRadioButton.isSelected() ? ResponseType.JSON : ResponseType.HTML);
+    myRepository.setLoginUrl(myLoginURLText.getText());
+    myRepository.setTasksListUrl(myTasksListURLText.getText());
+    myRepository.setSingleTaskUrl(mySingleTaskURLText.getText());
+
+    myRepository.setLoginMethodType(HTTPMethod.valueOf((String)myLoginMethodTypeComboBox.getSelectedItem()));
+    myRepository.setTasksListMethodType(HTTPMethod.valueOf((String)myTasksListMethodTypeComboBox.getSelectedItem()));
+    myRepository.setSingleTaskMethodType(HTTPMethod.valueOf((String)mySingleTaskMethodComboBox.getSelectedItem()));
+
+   for (Map.Entry<JTextField, TemplateVariable> entry : myField2Variable.entrySet()) {
+      TemplateVariable variable = entry.getValue();
+      JTextField field = entry.getKey();
+      variable.setValue(field.getText());
+    }
+    for (Map.Entry<JRadioButton, ResponseType> entry : myRadio2ResponseType.entrySet()) {
+      if (entry.getKey().isSelected()) {
+        myRepository.setResponseType(entry.getValue());
+      }
+    }
     super.apply();
   }
 
   private void createUIComponents() {
-    //todo completion
-    //todo completion without whitespace before cursor
-    final ArrayList<String> completionList = ContainerUtil.newArrayList(SERVER_URL_PLACEHOLDER, USERNAME_PLACEHOLDER, PASSWORD_PLACEHOLDER);
-    myLoginURLText = TextFieldWithAutoCompletion.create(myProject, completionList, null, false, myRepository.getLoginURL());
+    List<String> placeholders = createPlaceholdersList(myRepository);
+    myLoginURLText = createTextFieldWithCompletion(myRepository.getLoginUrl(), placeholders);
+    myTasksListURLText = createTextFieldWithCompletion(myRepository.getTasksListUrl(),
+                                                       concat(placeholders, "{max}", "{since}"));
+    mySingleTaskURLText = createTextFieldWithCompletion(myRepository.getSingleTaskUrl(),
+                                                        concat(placeholders, "{id}"));
+  }
 
-    final ArrayList<String> completionList1 = ContainerUtil.newArrayList(SERVER_URL_PLACEHOLDER, QUERY_PLACEHOLDER, MAX_COUNT_PLACEHOLDER);
-    myTasksListURLText = TextFieldWithAutoCompletion.create(myProject, completionList1, null, false, myRepository.getTasksListURL());
+  private TextFieldWithAutoCompletion<String> createTextFieldWithCompletion(String text, List<String> variants) {
+    return TextFieldWithAutoCompletion.create(myProject, variants, true, text);
+  }
 
-    final Document document = EditorFactory.getInstance().createDocument(myRepository.getTaskPattern());
-    myTaskPatternText = new EditorTextField(document, myProject, myRepository.getResponseType().getFileType(), false, false);
-    final ArrayList<String> completionList2 = ContainerUtil.newArrayList("({id}.+?)", "({summary}.+?)");
-    TextFieldWithAutoCompletionContributor
-      .installCompletion(document, myProject, new TextFieldWithAutoCompletion.StringsCompletionProvider(completionList2, null), true);
-    myTaskPatternText.setFontInheritedFromLAF(false);
+  @Override
+  public void setAnchor(@Nullable JComponent anchor) {
+    super.setAnchor(anchor);
+    List<JBLabel> labels = UIUtil.findComponentsOfType(myCustomPanel, JBLabel.class);
+    for (JBLabel label : labels) {
+      label.setAnchor(anchor);
+    }
   }
 }
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 720afdb..1a9bb42 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
@@ -2,19 +2,28 @@
 
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.tasks.TaskRepositorySubtype;
 import com.intellij.tasks.TaskRepository;
 import com.intellij.tasks.config.TaskRepositoryEditor;
 import com.intellij.tasks.impl.BaseRepositoryType;
 import com.intellij.util.Consumer;
+import com.intellij.util.xmlb.XmlSerializer;
+import icons.TasksIcons;
+import org.jdom.Document;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * User: Evgeny.Zakrevsky
  * Date: 10/4/12
  */
 public class GenericRepositoryType extends BaseRepositoryType<GenericRepository> {
+
   @NotNull
   @Override
   public String getName() {
@@ -45,4 +54,61 @@
                                            final Consumer<GenericRepository> changeListener) {
     return new GenericRepositoryEditor<GenericRepository>(project, repository, changeListener);
   }
+
+  @Override
+  public List<TaskRepositorySubtype> getAvailableSubtypes() {
+    return Arrays.asList(
+      this,
+      new AsanaRepository()
+    );
+  }
+
+  public class GenericSubtype implements TaskRepositorySubtype {
+    private final String myName;
+    private final Icon myIcon;
+
+    GenericSubtype(String name, Icon icon) {
+      myName = name;
+      myIcon = icon;
+    }
+
+    @Override
+    public String getName() {
+      return myName + " [G]";
+    }
+
+    @Override
+    public Icon getIcon() {
+      return myIcon;
+    }
+
+    @Override
+    public TaskRepository createRepository() {
+      Document document;
+      try {
+        String configFileName = myName.toLowerCase() + ".xml";
+        //URL resourceUrl = ResourceUtil.getResource(GenericRepositoryType.class, "connectors", configFileName);
+        URL resourceUrl = GenericRepository.class.getResource("connectors/" + configFileName);
+        if (resourceUrl == null) {
+          throw new AssertionError("Repository configuration file '" + configFileName + "' not found");
+        }
+        document = JDOMUtil.loadResourceDocument(resourceUrl);
+      }
+      catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+      GenericRepository repository = XmlSerializer.deserialize(document.getRootElement(), GenericRepository.class);
+      if (repository != null) {
+        repository.setRepositoryType(GenericRepositoryType.this);
+        repository.setSubtypeName(getName());
+      }
+      return repository;
+    }
+  }
+
+  public class AsanaRepository extends GenericSubtype {
+    public AsanaRepository() {
+      super("Asana", TasksIcons.Asana);
+    }
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java
new file mode 100644
index 0000000..b90bfb83
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java
@@ -0,0 +1,115 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashMap;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class GenericRepositoryUtil {
+  private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{(\\w[-\\w]*)\\}");
+  private static SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+  private static Pattern ISO8601_DATE_PATTERN = Pattern.compile(
+    "(\\d{4}-\\d{2}-\\d{2})[ T](\\d{2}:\\d{2}:\\d{2})(.\\d{3,})?([+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2}|Z)");
+
+  public static HttpMethod getPostMethodFromURL(final String requestUrl) {
+    int n = requestUrl.indexOf('?');
+    if (n == -1) {
+      return new PostMethod(requestUrl);
+    }
+    PostMethod postMethod = new PostMethod(requestUrl.substring(0, n));
+    String[] queryParams = requestUrl.substring(n + 1).split("&");
+    postMethod.addParameters(ContainerUtil.map2Array(queryParams, NameValuePair.class, new Function<String, NameValuePair>() {
+      @Override
+      public NameValuePair fun(String s) {
+        String[] nv = s.split("=");
+        if (nv.length == 1) {
+          return new NameValuePair(nv[0], "");
+        }
+        return new NameValuePair(nv[0], nv[1]);
+      }
+    }));
+    return postMethod;
+  }
+
+  public static String substituteTemplateVariables(String s, Collection<TemplateVariable> variables) {
+    Map<String, String> lookup = new HashMap<String, String>();
+    for (TemplateVariable v : variables) {
+      lookup.put(v.getName(), v.getValue());
+    }
+    StringBuffer sb = new StringBuffer();
+    Matcher m = PLACEHOLDER_PATTERN.matcher(s);
+    while (m.find()) {
+      String replacement = lookup.containsKey(m.group(1)) ? lookup.get(m.group(1)) : m.group(0);
+      m.appendReplacement(sb, replacement);
+    }
+    return m.appendTail(sb).toString();
+  }
+
+  public static List<String> createPlaceholdersList(GenericRepository repository) {
+    return createPlaceholdersList(repository.getAllTemplateVariables());
+  }
+
+  public static List<String> createPlaceholdersList(List<TemplateVariable> variables) {
+    return ContainerUtil.map2List(variables, new Function<TemplateVariable, String>() {
+      @Override
+      public String  fun(TemplateVariable variable) {
+        return String.format("{%s}", variable.getName());
+      }
+    });
+  }
+
+  @Nullable
+  public static Date parseISO8601Date(@NotNull String s) {
+    // SimpleDateFormat prior JDK7 doesn't support 'X' specifier for ISO 8601 timezone format.
+    // Because some bug trackers and task servers e.g. send dates ending with 'Z' (that stands for UTC),
+    // dates should be preprocessed before parsing.
+    Matcher m = ISO8601_DATE_PATTERN.matcher(s);
+    if (!m.matches()) {
+      return null;
+    }
+    String datePart = m.group(1);
+    String timePart = m.group(2);
+    String milliseconds = m.group(3);
+    milliseconds = milliseconds == null? "000" : milliseconds.substring(1, 4);
+    String timezone = m.group(4);
+    if (timezone.equals("Z")) {
+      timezone = "+0000";
+    } else if (timezone.length() == 3) {
+      // [+-]HH
+      timezone += "00";
+    } else if (timezone.length() == 6) {
+      // [+-]HH:MM
+      timezone = timezone.substring(0, 3) + timezone.substring(4, 6);
+    }
+    String canonicalForm = String.format("%sT%s.%s%s", datePart, timePart, milliseconds, timezone);
+    try {
+      return ISO8601_DATE_FORMAT.parse(canonicalForm);
+    }
+    catch (ParseException e) {
+      return null;
+    }
+  }
+
+  public static String prettifyVariableName(String variableName) {
+    String prettyName = variableName.replace('_', ' ');
+    return StringUtil.capitalizeWords(prettyName, true);
+  }
+
+  public static <T> List<T> concat(List<? extends T> list, T... values) {
+    return ContainerUtil.concat(true, list, values);
+  }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericTask.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericTask.java
index 0cca695..43234c2 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericTask.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericTask.java
@@ -12,12 +12,17 @@
 
 public class GenericTask extends Task {
   private final String myId;
-  private final String myDescription;
+  private final String mySummary;
+  private String myDescription;
+  private Date myUpdated;
+  private Date myCreated;
+  private String myIssueUrl;
   private TaskRepository myRepository;
+  private boolean myClosed;
 
-  public GenericTask(final String id, final String description, final TaskRepository repository) {
+  public GenericTask(final String id, final String summary, final TaskRepository repository) {
     myId = id;
-    myDescription = description;
+    mySummary = summary;
     myRepository = repository;
   }
 
@@ -30,25 +35,25 @@
   @NotNull
   @Override
   public String getSummary() {
-    return myDescription;
+    return mySummary;
   }
 
   @Nullable
   @Override
   public String getDescription() {
-    return null;
+    return myDescription;
   }
 
   @NotNull
   @Override
   public Comment[] getComments() {
-    return new Comment[0];
+    return Comment.EMPTY_ARRAY;
   }
 
   @NotNull
   @Override
   public Icon getIcon() {
-    return myRepository.getRepositoryType().getIcon();
+    return myRepository.getIcon();
   }
 
   @NotNull
@@ -60,18 +65,18 @@
   @Nullable
   @Override
   public Date getUpdated() {
-    return null;
+    return myUpdated;
   }
 
   @Nullable
   @Override
   public Date getCreated() {
-    return null;
+    return myCreated;
   }
 
   @Override
   public boolean isClosed() {
-    return false;
+    return myClosed;
   }
 
   @Override
@@ -82,7 +87,7 @@
   @Nullable
   @Override
   public String getIssueUrl() {
-    return null;
+    return myIssueUrl;
   }
 
   @Nullable
@@ -90,4 +95,24 @@
   public TaskRepository getRepository() {
     return myRepository;
   }
+
+  public void setIssueUrl(@Nullable String issueUrl) {
+    myIssueUrl = issueUrl;
+  }
+
+  public void setCreated(@Nullable Date created) {
+    myCreated = created;
+  }
+
+  public void setUpdated(@Nullable Date updated) {
+    myUpdated = updated;
+  }
+
+  public void setDescription(@Nullable String description) {
+    myDescription = description;
+  }
+
+  public void setClosed(boolean closed) {
+    myClosed = closed;
+  }
 }
\ No newline at end of file
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java
new file mode 100644
index 0000000..48d7b1b
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java
@@ -0,0 +1,99 @@
+/*
+ * 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.tasks.generic;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.LanguageTextField;
+import com.intellij.ui.table.TableView;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ColumnInfo;
+import com.intellij.util.ui.ListTableModel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+import java.util.List;
+
+
+class HighlightedSelectorsTable extends TableView<Selector> {
+
+  private final FileType myValueFileType;
+  private final Project myProject;
+
+  public HighlightedSelectorsTable(@NotNull FileType valueFileType, @NotNull Project project) {
+    this(valueFileType, project, ContainerUtil.<Selector>emptyList());
+  }
+
+  public HighlightedSelectorsTable(@NotNull final FileType valueFileType, @NotNull final Project project, @NotNull final List<Selector> selectors) {
+    super(new ListTableModel<Selector>(new ColumnInfo[]{
+      new ColumnInfo<Selector, String>("Name") {
+        @Nullable
+        @Override
+        public String valueOf(Selector selector) {
+          return selector.getName();
+        }
+      },
+      new ColumnInfo<Selector, String>("Path") {
+        @Nullable
+        @Override
+        public String valueOf(Selector selector) {
+          return selector.getPath();
+        }
+
+        @Override
+        public boolean isCellEditable(Selector selector) {
+          return true;
+        }
+
+        @Override
+        public void setValue(Selector selector, String value) {
+          selector.setPath(value);
+        }
+
+        @Nullable
+        @Override
+        public TableCellRenderer getRenderer(Selector selector) {
+          return new LanguageTextFieldRenderer(((LanguageFileType)valueFileType).getLanguage(), project);
+        }
+      }
+    }, selectors, 0));
+    myValueFileType = valueFileType;
+    myProject = project;
+  }
+  public List<Selector> getSelectors() {
+    return getItems();
+  }
+
+  private static class LanguageTextFieldRenderer implements TableCellRenderer {
+    private final Project myProject;
+    private final Language myLanguage;
+
+    private LanguageTextFieldRenderer(Language language, Project project) {
+      myProject = project;
+      myLanguage = language;
+    }
+
+    @Override
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+      return new LanguageTextField(myLanguage, myProject, (String)value);
+    }
+  }
+}
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
new file mode 100644
index 0000000..e2f1ea8
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java
@@ -0,0 +1,162 @@
+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.tasks.Task;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.jayway.jsonpath.InvalidPathException;
+import com.jayway.jsonpath.JsonPath;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Author: Mikhail Golubev
+ */
+@Tag("JsonResponseHandler")
+public final class JsonPathResponseHandler extends SelectorBasedResponseHandler {
+
+  private static final Map<Class<?>, String> JSON_TYPES = ContainerUtil.newHashMap(
+    new Pair<Class<?>, String>(Map.class, "JSON object"),
+    new Pair<Class<?>, String>(List.class, "JSON array"),
+    new Pair<Class<?>, String>(String.class, "JSON string"),
+    new Pair<Class<?>, String>(Integer.class, "JSON number"),
+    new Pair<Class<?>, String>(Double.class, "JSON number"),
+    new Pair<Class<?>, String>(Boolean.class, "JSON boolean")
+  );
+
+  /**
+   * Serialization constructor
+   */
+  @SuppressWarnings("UnusedDeclaration")
+  public JsonPathResponseHandler() {
+  }
+
+  public JsonPathResponseHandler(GenericRepository repository) {
+    super(repository);
+  }
+
+  @Override
+  public FileType getSelectorFileType() {
+    return PlainTextFileType.INSTANCE;
+  }
+
+  @SuppressWarnings("unchecked")
+  @NotNull
+  @Override
+  public Task[] doParseIssues(String response) throws Exception {
+    Object tasksMatch = JsonPath.read(response, getSelectorPath("tasks"));
+    if (!(tasksMatch instanceof List)) {
+      throw new Exception("Selector 'task' should match array of tasks. Got " + tasksMatch.toString() + " instead");
+    }
+    List<Object> tasks = (List<Object>)tasksMatch;
+    List<GenericTask> result = new ArrayList<GenericTask>(tasks.size());
+    for (Object rawTask : tasks) {
+      String taskText = rawTask.toString();
+      String id = extractId(taskText, getSelector("id"));
+      String summary = extractString(taskText, getSelector("summary"));
+      assert summary != null;
+      GenericTask task = new GenericTask(id, summary, myRepository);
+      task.setDescription(extractString(response, getSelector("description")));
+      task.setIssueUrl(extractString(response, getSelector("issueUrl")));
+      Boolean closed = extractBoolean(response, getSelector("closed"));
+      if (closed != null) {
+        task.setClosed(closed);
+      }
+      task.setUpdated(extractDate(response, getSelector("updated")));
+      task.setCreated(extractDate(response, getSelector("created")));
+      result.add(task);
+    }
+    return result.toArray(new Task[result.size()]);
+  }
+
+  @Nullable
+  @Override
+  public Task doParseIssue(String response) throws Exception {
+    String id = extractId(response, getSelector("singleTask-id"));
+    String summary = extractString(response, getSelector("singleTask-summary"));
+    GenericTask task = new GenericTask(id, summary, myRepository);
+    task.setDescription(extractString(response, getSelector("singleTask-description")));
+    task.setIssueUrl(extractString(response, getSelector("singleTask-issueUrl")));
+    Boolean closed = extractBoolean(response, getSelector("singleTask-closed"));
+    if (closed != null) {
+      task.setClosed(closed);
+    }
+    task.setUpdated(extractDate(response, getSelector("singleTask-updated")));
+    task.setCreated(extractDate(response, getSelector("singleTask-created")));
+    return task;
+  }
+
+  @SuppressWarnings({"unchecked", "MethodMayBeStatic"})
+  @Nullable
+  private <T> T extractValueAndCheckType(String source, Selector selector, Class<T> cls) throws Exception {
+    if (selector == null || StringUtil.isEmpty(selector.getPath())) {
+      return null;
+    }
+    Object value;
+    try {
+      value = JsonPath.read(source, selector.getPath());
+    }
+    catch (InvalidPathException e) {
+      // NOTE: could be thrown when selector is actually invalid or just not matched
+      throw new Exception(String.format("JsonPath expression '%s' is malformed or didn't match", selector.getPath()), e);
+    }
+    if (value == null) {
+      return null;
+    }
+    if (!(cls.isInstance(value))) {
+      throw new Exception(
+        String.format("Selector '%s' should match %s. Got '%s' instead", selector.getName(), JSON_TYPES.get(cls), value.toString()));
+    }
+    return (T)value;
+  }
+
+  @SuppressWarnings("MethodMayBeStatic")
+  @Nullable
+  private String extractId(String task, Selector idSelector) throws Exception {
+    Object rawId;
+    try {
+      rawId = JsonPath.read(task, idSelector.getPath());
+    }
+    catch (InvalidPathException e) {
+      throw new Exception(String.format("JsonPath expression '%s' is malformed or didn't match", idSelector.getPath()), e);
+    }
+    if (!(rawId instanceof String) && !(rawId instanceof Long)) {
+      throw new Exception(
+        String.format("Selector 'id' should match either JSON string or JSON number value. Got '%s' instead", rawId.toString()));
+    }
+    return String.valueOf(rawId);
+  }
+
+  private String extractString(String source, Selector selector) throws Exception {
+    return extractValueAndCheckType(source, selector, String.class);
+  }
+
+  private Boolean extractBoolean(String source, Selector selector) throws Exception {
+    return extractValueAndCheckType(source, selector, Boolean.class);
+  }
+
+  private Long extractLong(String source, Selector selector) throws Exception {
+    return extractValueAndCheckType(source, selector, Long.class);
+  }
+
+  private Date extractDate(String response, Selector selector) throws Exception {
+    String dateString = extractString(response, selector);
+    if (dateString == null) {
+      return null;
+    }
+    return GenericRepositoryUtil.parseISO8601Date(dateString);
+  }
+
+  @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 a783b66..fca6b21 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
@@ -8,6 +8,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
 import java.awt.*;
 import java.util.List;
 
@@ -88,6 +89,24 @@
           setModified();
         }
 
+        @Override
+        public TableCellRenderer getRenderer(TemplateVariable variable) {
+          if (variable.getIsHidden()) {
+            return new TableCellRenderer() {
+              @Override
+              public Component getTableCellRendererComponent(JTable table,
+                                                             Object value,
+                                                             boolean isSelected,
+                                                             boolean hasFocus,
+                                                             int row,
+                                                             int column) {
+                return new JPasswordField(value.toString());
+              }
+            };
+          }
+          return super.getRenderer(variable);
+        }
+
         @Nullable
         @Override
         protected String getDescription(TemplateVariable templateVariable) {
@@ -95,7 +114,68 @@
         }
       };
 
-      return new ListTableModel((new ColumnInfo[]{name, value}));
+      final ColumnInfo isShownOnFirstTab = new ColumnInfo<TemplateVariable, Boolean>("Show on first tab") {
+        @Nullable
+        @Override
+        public Boolean valueOf(TemplateVariable o) {
+          return o.getIsShownOnFirstTab();
+        }
+
+        @Override
+        public void setValue(TemplateVariable variable, Boolean value) {
+          variable.setIsShownOnFirstTab(value);
+          setModified();
+        }
+
+        @Override
+        public Class getColumnClass() {
+          return Boolean.class;
+        }
+
+        @Override
+        public boolean isCellEditable(TemplateVariable variable) {
+          return !variable.getIsPredefined();
+        }
+
+        @Nullable
+        @Override
+        public String getTooltipText() {
+          return "Whether this template variable will be shown in 'General tab'";
+        }
+      };
+
+      final ColumnInfo isHidden = new ColumnInfo<TemplateVariable, Boolean>("Hide") {
+        @Nullable
+        @Override
+        public Boolean valueOf(TemplateVariable o) {
+          return o.getIsHidden();
+        }
+
+        @Override
+        public void setValue(TemplateVariable variable, Boolean value) {
+          variable.setIsHidden(value);
+          setModified();
+          // value column editor may be changed
+          TemplateVariablesTable.this.refreshValues();
+        }
+
+        @Override
+        public Class getColumnClass() {
+          return Boolean.class;
+        }
+
+        @Override
+        public boolean isCellEditable(TemplateVariable variable) {
+          return !variable.getIsPredefined();
+        }
+
+        @Nullable
+        @Override
+        public String getTooltipText() {
+          return "Whether this template variable will be hidden like password field";
+        }
+      };
+      return new ListTableModel((new ColumnInfo[]{name, value, isShownOnFirstTab, isHidden}));
     }
 
     @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
new file mode 100644
index 0000000..45332b5d
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java
@@ -0,0 +1,164 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.tasks.Task;
+import com.intellij.ui.EditorTextField;
+import com.intellij.ui.LanguageTextField;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.FormBuilder;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.xml.util.XmlUtil;
+import org.intellij.lang.regexp.RegExpLanguage;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Handler that uses legacy regex-based approach for tasks extraction.
+ *
+ * @author Evgeny.Zakrevsky
+ * @author Mikhail Golubev
+ */
+@Tag("RegExResponseHandler")
+public final class RegExResponseHandler extends ResponseHandler {
+  private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.generic.RegExResponseHandler");
+  private static final String ID_PLACEHOLDER = "{id}";
+  private static final String SUMMARY_PLACEHOLDER = "{summary}";
+
+  private String myTaskRegex = "";
+
+  /**
+   * Serialization constructor
+   */
+  @SuppressWarnings("UnusedDeclaration")
+  public RegExResponseHandler() {
+    // empty
+  }
+
+  public RegExResponseHandler(GenericRepository repository) {
+    super(repository);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RegExResponseHandler handler = (RegExResponseHandler)o;
+    return myTaskRegex.equals(handler.myTaskRegex);
+  }
+
+  @Override
+  public int hashCode() {
+    return myTaskRegex.hashCode();
+  }
+
+  @Override
+  public JComponent getConfigurationComponent(Project project) {
+    FormBuilder builder = FormBuilder.createFormBuilder();
+    final EditorTextField taskPatternText;
+    taskPatternText = new LanguageTextField(RegExpLanguage.INSTANCE, project, myTaskRegex, false);
+    taskPatternText.addDocumentListener(new DocumentAdapter() {
+      @Override
+      public void documentChanged(DocumentEvent e) {
+        myTaskRegex = taskPatternText.getText();
+      }
+    });
+    String tooltip = "<html>Task pattern should be a regexp with two matching groups: ({id}.+?) and ({summary}.+?)";
+    builder.addLabeledComponent("Task Pattern:", new JBScrollPane(taskPatternText)).addTooltip(tooltip);
+    return builder.getPanel();
+  }
+
+  @NotNull
+  @Override
+  public Task[] parseIssues(String response) throws Exception {
+    final List<String> placeholders = getPlaceholders(myTaskRegex);
+    if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
+      throw new Exception("Incorrect Task Pattern");
+    }
+
+    final String taskPatternWithoutPlaceholders = myTaskRegex.replaceAll("\\{.+?\\}", "");
+    Matcher matcher = Pattern
+      .compile(taskPatternWithoutPlaceholders,
+               Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.UNICODE_CASE | Pattern.CANON_EQ)
+      .matcher(response);
+
+    List<Task> tasks = new ArrayList<Task>();
+    while (matcher.find()) {
+      String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1);
+      String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1);
+      // temporary workaround to make AssemblaIntegrationTestPass
+      final String finalSummary = summary;
+      summary = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+        @Override
+        public String compute() {
+          XmlElementFactory factory = XmlElementFactory.getInstance(ProjectManager.getInstance().getDefaultProject());
+          XmlTag text = factory.createTagFromText("<a>" + finalSummary + "</a>");
+          String trimmedText = text.getValue().getTrimmedText();
+          return XmlUtil.decode(trimmedText);
+        }
+      });
+      tasks.add(new GenericTask(id, summary, myRepository));
+    }
+    return tasks.toArray(new Task[tasks.size()]);
+  }
+
+  @Nullable
+  @Override
+  public Task parseIssue(String response) throws Exception {
+    return null;
+  }
+
+  private static List<String> getPlaceholders(String value) {
+    if (value == null) {
+      return ContainerUtil.emptyList();
+    }
+
+    List<String> vars = new ArrayList<String>();
+    Matcher m = Pattern.compile("\\{(.+?)\\}").matcher(value);
+    while (m.find()) {
+      vars.add(m.group(0));
+    }
+    return vars;
+  }
+
+  public String getTaskRegex() {
+    return myTaskRegex;
+  }
+
+  public void setTaskRegex(String taskRegex) {
+    myTaskRegex = taskRegex;
+  }
+
+  @Override
+  public boolean isConfigured() {
+    return !StringUtil.isEmpty(myTaskRegex);
+  }
+
+  @Override
+  public ResponseType getResponseType() {
+    return ResponseType.TEXT;
+  }
+
+  @Override
+  public RegExResponseHandler clone() {
+    RegExResponseHandler clone = (RegExResponseHandler)super.clone();
+    clone.myTaskRegex = myTaskRegex;
+    return clone;
+  }
+}
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
new file mode 100644
index 0000000..94bdd97
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java
@@ -0,0 +1,63 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.tasks.Task;
+import com.intellij.util.xmlb.annotations.Transient;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * ResponseHandler subclasses represent different strategies of extracting tasks from
+ * task server responses (e.g. using regular expressions, XPath, JSONPath, CSS selector etc.).
+ *
+ * @see XPathResponseHandler
+ * @see JsonPathResponseHandler
+ * @see RegExResponseHandler
+ * @author Mikhail Golubev
+ */
+public abstract class ResponseHandler implements Cloneable {
+
+  // XXX: what about serialization of circular dependencies?
+  protected GenericRepository myRepository;
+
+  // Serialization constructor
+  public ResponseHandler() {
+    // empty
+  }
+
+  public ResponseHandler(GenericRepository repository) {
+    myRepository = repository;
+  }
+
+  public void setRepository(GenericRepository repository) {
+    myRepository = repository;
+  }
+
+  @Transient
+  public GenericRepository getRepository() {
+    return myRepository;
+  }
+
+  public abstract JComponent getConfigurationComponent(Project project);
+
+  public abstract ResponseType getResponseType();
+
+  @NotNull
+  public abstract Task[] parseIssues(String response) throws Exception;
+
+  @Nullable
+  public abstract Task parseIssue(String response) throws Exception;
+
+  public abstract boolean isConfigured();
+
+  @Override
+  public ResponseHandler clone() {
+    try {
+      return (ResponseHandler) super.clone();
+    } catch (CloneNotSupportedException e) {
+      throw new AssertionError("ResponseHandler#clone() should be supported");
+    }
+  }
+}
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 6a1248d..aa4bd78 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
@@ -4,29 +4,39 @@
 import com.intellij.ide.highlighter.XmlFileType;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.PlainTextFileType;
+import org.intellij.lang.regexp.RegExpFileType;
+import org.intellij.lang.xpath.XPathFileType;
 
 /**
  * User: evgeny.zakrevsky
  * Date: 10/25/12
  */
 public enum ResponseType {
-  XML("application/xml", XmlFileType.INSTANCE),
-  HTML("text/html", HtmlFileType.INSTANCE),
-  JSON("application/json", PlainTextFileType.INSTANCE);
+  XML("application/xml", XmlFileType.INSTANCE, XPathFileType.XPATH2),
+  JSON("application/json", PlainTextFileType.INSTANCE, 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 myFileType;
+  private FileType myContentFileType;
+  private FileType mySelectorFileType;
 
-  ResponseType(final String s, final FileType fileType) {
+  ResponseType(final String s, final FileType contentFileType, final FileType selectorFileType) {
     myMimeType = s;
-    myFileType = fileType;
+    myContentFileType = contentFileType;
+    mySelectorFileType = selectorFileType;
   }
 
   public String getMimeType() {
     return myMimeType;
   }
 
-  public FileType getFileType() {
-    return myFileType;
+  public FileType getContentFileType() {
+    return myContentFileType;
+  }
+
+  public FileType getSelectorFileType() {
+    return mySelectorFileType;
   }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/Selector.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/Selector.java
new file mode 100644
index 0000000..ea30e2f
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/Selector.java
@@ -0,0 +1,87 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Mikhail Golubev
+ */
+
+@Tag("selector")
+public final class Selector {
+  @NotNull private String myName;
+  @NotNull private String myPath;
+
+
+  /**
+   * Serialization constructor
+   */
+  @SuppressWarnings({"UnusedDeclatation"})
+  public Selector() {
+    // empty
+  }
+
+  public Selector(@NotNull String name) {
+    this(name, "");
+  }
+
+  public Selector(@NotNull String name, @NotNull String path) {
+    myName = name;
+    myPath = path;
+  }
+
+  public Selector(Selector other) {
+    myName = other.myName;
+    myPath = other.myPath;
+  }
+
+  @Attribute("name")
+  @NotNull
+  public String getName() {
+    return myName;
+  }
+
+  @Attribute("path")
+  @NotNull
+  public String getPath() {
+    return myPath;
+  }
+
+  public void setName(@NotNull String name) {
+    myName = name;
+  }
+
+  public void setPath(@NotNull String path) {
+    myPath = path;
+  }
+
+  public Selector clone() {
+    return new Selector(this);
+  }
+
+  @Override
+  public String toString() {
+    return String.format("Selector(name='%s', path='%s')", getName(), getPath());
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    Selector selector = (Selector)o;
+
+    if (!myName.equals(selector.myName)) return false;
+    if (!myPath.equals(selector.myPath)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myName.hashCode();
+    result = (31 * result) + (myPath.hashCode());
+    return result;
+  }
+}
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
new file mode 100644
index 0000000..5ef8809
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java
@@ -0,0 +1,158 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.tasks.Task;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * @author Mikhail Golubev
+ */
+public abstract class SelectorBasedResponseHandler extends ResponseHandler {
+
+  protected LinkedHashMap<String, Selector> mySelectors = new LinkedHashMap<String, Selector>();
+
+  /**
+   * Serialization constructor
+   */
+  @SuppressWarnings("UnusedDeclaration")
+  protected SelectorBasedResponseHandler() {
+    // empty
+  }
+
+  protected SelectorBasedResponseHandler(GenericRepository repository) {
+    super(repository);
+    // standard selectors
+    setSelectors(ContainerUtil.newArrayList(
+      // matched against list of tasks at whole downloaded from "taskListUrl"
+      new Selector("tasks", ""),
+
+      // matched against single tasks extracted from the list downloaded from "taskListUrl"
+      new Selector("id"),
+      new Selector("summary"),
+      new Selector("description"),
+      new Selector("updated"),
+      new Selector("created"),
+      new Selector("closed"),
+      new Selector("issueUrl"),
+
+      // matched against single task downloaded from "singleTaskUrl"
+      new Selector("singleTask-id"),
+      new Selector("singleTask-summary"),
+      new Selector("singleTask-description"),
+      new Selector("singleTask-updated"),
+      new Selector("singleTask-created"),
+      new Selector("singleTask-closed"),
+      new Selector("singleTask-issueUrl")
+    ));
+  }
+
+  public abstract FileType getSelectorFileType();
+
+  @Tag("selectors")
+  @Property(surroundWithTag = false)
+  @AbstractCollection(surroundWithTag = false)
+  @NotNull
+  public List<Selector> getSelectors() {
+    return new ArrayList<Selector>(mySelectors.values());
+  }
+
+  public void setSelectors(@NotNull List<Selector> selectors) {
+    mySelectors.clear();
+    for (Selector selector : selectors) {
+      mySelectors.put(selector.getName(), selector);
+    }
+  }
+
+  @Nullable
+  public Selector getSelector(@NotNull String name) {
+    return mySelectors.get(name);
+  }
+
+  @Nullable
+  public String getSelectorPath(@NotNull String name) {
+    Selector s = getSelector(name);
+    return s == null ? null : s.getPath();
+  }
+
+  @Override
+  public JComponent getConfigurationComponent(Project project) {
+    HighlightedSelectorsTable table = new HighlightedSelectorsTable(getSelectorFileType(),
+                                                                    project,
+                                                                    getSelectors());
+    return new JBScrollPane(table);
+  }
+
+  @Override
+  public SelectorBasedResponseHandler clone() {
+    SelectorBasedResponseHandler clone = (SelectorBasedResponseHandler)super.clone();
+    clone.mySelectors = new LinkedHashMap<String, Selector>(mySelectors.size());
+    for (Selector selector : mySelectors.values()) {
+      clone.mySelectors.put(selector.getName(), selector.clone());
+    }
+    return clone;
+  }
+
+  @Override
+  public boolean isConfigured() {
+    Selector idSelector = getSelector("id");
+    if (idSelector == null || StringUtil.isEmpty(idSelector.getPath())) return false;
+    Selector summarySelector = getSelector("summary");
+    if (summarySelector == null || StringUtil.isEmpty(summarySelector.getPath())) return false;
+    return true;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof SelectorBasedResponseHandler)) return false;
+
+    SelectorBasedResponseHandler handler = (SelectorBasedResponseHandler)o;
+
+    if (!mySelectors.equals(handler.mySelectors)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return mySelectors.hashCode();
+  }
+
+  @NotNull
+  @Override
+  public final Task[] parseIssues(String response) 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");
+    }
+    return doParseIssues(response);
+  }
+
+  protected abstract Task[] doParseIssues(String response) throws Exception;
+
+  @Nullable
+  @Override
+  public final Task parseIssue(String response) throws Exception {
+    if (StringUtil.isEmpty(getSelectorPath("singleTask-id")) ||
+        StringUtil.isEmpty(getSelectorPath("singleTask-summary"))) {
+      throw new Exception("Selectors 'singleTask-id' and 'singleTask-summary' are mandatory");
+    }
+    return doParseIssue(response);
+  }
+
+  protected abstract Task doParseIssue(String response) throws Exception;
+}
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 e89fdd7..d8377bb 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
@@ -1,5 +1,6 @@
 package com.intellij.tasks.generic;
 
+import com.intellij.util.xmlb.annotations.Attribute;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -10,17 +11,55 @@
  */
 public class TemplateVariable {
   private String myName;
-  private String myValue;
-  private boolean myIsPredefined;
+  private String myValue = "";
   private String myDescription;
+  private boolean myIsPredefined;
+  private boolean myIsHidden;
+  private boolean myIsShownOnFirstTab;
 
-  public TemplateVariable(@NotNull @NonNls String name, @NotNull @NonNls String value, boolean isPredefined, @Nullable String description) {
+  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) {
     myName = name;
-    myValue = value;
+    myValue = String.valueOf(value);
     myIsPredefined = isPredefined;
     myDescription = description;
   }
 
+  /**
+   * Serialization constructor
+   */
+  public TemplateVariable() {
+  }
+
+
+  /**
+   * Cloning constructor
+   */
+  private TemplateVariable(TemplateVariable other) {
+    myName = other.getName();
+    myValue = other.getValue();
+    myDescription = other.getDescription();
+    myIsHidden = other.getIsHidden();
+    myIsPredefined = other.getIsPredefined();
+    myIsShownOnFirstTab = other.getIsShownOnFirstTab();
+  }
+
   public void setName(String name) {
     myName = name;
   }
@@ -42,15 +81,133 @@
     return myDescription;
   }
 
+  @Attribute("isPredefined")
   public boolean getIsPredefined() {
     return myIsPredefined;
   }
 
+  public void setIsPredefined(boolean isPredefined) {
+    myIsPredefined = isPredefined;
+  }
+
+  @Attribute("isHidden")
+  public boolean getIsHidden() {
+    return myIsHidden;
+  }
+
+  public void setIsHidden(boolean isHidden) {
+    myIsHidden = isHidden;
+  }
+
+  @Attribute("shownOnFirstTab")
+  public boolean getIsShownOnFirstTab() {
+    return myIsShownOnFirstTab;
+  }
+
+  public void setIsShownOnFirstTab(boolean isShownOnFirstTab) {
+    myIsShownOnFirstTab = isShownOnFirstTab;
+  }
+
   public TemplateVariable clone() {
-    return new TemplateVariable(myName, myValue, myIsPredefined, myDescription);
+    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.
+   */
+  public abstract static class PredefinedFactoryVariable extends TemplateVariable {
+
+    protected PredefinedFactoryVariable(String name) {
+      this(name, false);
+    }
+
+    public PredefinedFactoryVariable(String name, boolean isHidden) {
+      this(name, name, isHidden);
+    }
+
+    public PredefinedFactoryVariable(String name, String description, boolean isHidden) {
+      super(builder(name).description(description).isHidden(isHidden));
+    }
+
+    @Override
+    public abstract String getValue();
+
+    @Override
+    public final void setName(String name) {
+      throw new UnsupportedOperationException("Name of predefined variable can't be changed");
+    }
+
+    @Override
+    public final void setValue(String value) {
+      throw new UnsupportedOperationException("Value of predefined variable can't be changed explicitly");
+    }
+
+    @Override
+    public final void setIsShownOnFirstTab(boolean isShownOnFirstTab) {
+      throw new UnsupportedOperationException("This parameter can't be changed for predefined variable");
+    }
+
+    @Override
+    public void setIsPredefined(boolean isPredefined) {
+      throw new UnsupportedOperationException("This parameter can't be changed for predefined variable");
+    }
+
+    @Override
+    public boolean getIsPredefined() {
+      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
new file mode 100644
index 0000000..97dfc07
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java
@@ -0,0 +1,97 @@
+package com.intellij.tasks.generic;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.tasks.Task;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.intellij.lang.xpath.XPathFileType;
+import org.jetbrains.annotations.Nullable;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+
+/**
+ * @author Mikhail Golubev
+ */
+@Tag("XPathResponseHandler")
+public final class XPathResponseHandler extends SelectorBasedResponseHandler {
+  private final static DocumentBuilder ourDocumentBuilder = createDocumentBuilder();
+  private static DocumentBuilder createDocumentBuilder() {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    try {
+      return factory.newDocumentBuilder();
+    } catch (ParserConfigurationException e) {
+      throw new AssertionError("Can't create DocumentBuilder");
+    }
+  }
+
+  private final static XPathFactory ourXPathFactory = createXPathFactory();
+  private static XPathFactory createXPathFactory() {
+    return XPathFactory.newInstance();
+  }
+
+  /**
+   * Serialization constructor
+   */
+  @SuppressWarnings("UnusedDeclaration")
+  public XPathResponseHandler() {
+    // empty
+  }
+
+  public XPathResponseHandler(GenericRepository repository) {
+    super(repository);
+  }
+
+  @Override
+  public FileType getSelectorFileType() {
+    return XPathFileType.XPATH2;
+  }
+
+  @Override
+  public Task[] doParseIssues(String response) throws Exception {
+    String idSelector = getSelectorPath("id"), summarySelector = getSelectorPath("summary");
+    if (idSelector == null || summarySelector == null) {
+      throw new IllegalArgumentException("Selectors 'task', 'id' and 'summary' are mandatory");
+    }
+
+    Document document = ourDocumentBuilder.parse(new ByteArrayInputStream(response.getBytes()));
+
+    XPathExpression idPath = ourXPathFactory.newXPath().compile(idSelector);
+    NodeList idNodes = (NodeList)idPath.evaluate(document, XPathConstants.NODESET);
+
+    XPathExpression summaryPath = ourXPathFactory.newXPath().compile(summarySelector);
+    NodeList summaryNodes = (NodeList)summaryPath.evaluate(document, XPathConstants.NODESET);
+
+    if (summaryNodes.getLength() != idNodes.getLength()) {
+      // popup will be shown to the user
+      throw new IllegalArgumentException("Number of tasks selected by 'id' and 'summary' XPath expressions is not the same.");
+    }
+
+    ArrayList<Task> tasks = new ArrayList<Task>(idNodes.getLength());
+    for (int i = 0; i < idNodes.getLength(); i++) {
+      String id = idNodes.item(i).getNodeValue();
+      String summary = summaryNodes.item(i).getNodeValue();
+      tasks.add(new GenericTask(id, summary, myRepository));
+    }
+    return tasks.toArray(new Task[tasks.size()]);
+  }
+
+  @Nullable
+  @Override
+  public Task doParseIssue(String response) throws Exception {
+    return null;
+  }
+
+  @Override
+  public ResponseType getResponseType() {
+    return ResponseType.XML;
+  }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/assembla/AssemblaRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/assembla/AssemblaRepository.java
index dfe20bf8..1356f9d 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/assembla/AssemblaRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/assembla/AssemblaRepository.java
@@ -2,31 +2,31 @@
 
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.tasks.TaskRepositoryType;
-import com.intellij.tasks.generic.GenericRepository;
-import com.intellij.tasks.generic.GenericRepositoryEditor;
-import com.intellij.tasks.generic.ResponseType;
-import com.intellij.tasks.generic.TemplateVariable;
+import com.intellij.tasks.generic.*;
 import com.intellij.util.xmlb.annotations.Tag;
 
-import java.util.List;
-
 /**
  * User: evgeny.zakrevsky
  * Date: 10/26/12
  */
+// TODO: move to new Generic Repository API
 @Tag("Assembla")
 public class AssemblaRepository extends GenericRepository {
 
+  private static final String TASK_REGEX =
+    "<ticket>.*?<number type=\"integer\">({id}.*?)</number>.*?<summary>({summary}.*?)</summary>.*?</ticket>";
+
   @SuppressWarnings({"UnusedDeclaration"})
   public AssemblaRepository() {
   }
 
   public AssemblaRepository(final TaskRepositoryType type) {
     super(type);
-    myUseHttpAuthentication = true;
+    setUseHttpAuthentication(true);
+    setUrl("http://www.assembla.com/");
   }
 
-  public AssemblaRepository(final GenericRepository other) {
+  public AssemblaRepository(final AssemblaRepository other) {
     super(other);
   }
 
@@ -36,38 +36,10 @@
   }
 
   @Override
-  protected List<TemplateVariable> getTemplateVariablesDefault() {
-    return super.getTemplateVariablesDefault();
-  }
-
-  @Override
-  protected ResponseType getResponseTypeDefault() {
-    return ResponseType.XML;
-  }
-
-  @Override
-  protected String getTasksListMethodTypeDefault() {
-    return GenericRepositoryEditor.GET;
-  }
-
-  @Override
-  protected String getLoginMethodTypeDefault() {
-    return GenericRepositoryEditor.POST;
-  }
-
-  @Override
-  protected String getLoginURLDefault() {
-    return "";
-  }
-
-  @Override
-  protected String getTaskPatternDefault() {
-    return "<ticket>.*?<number type=\"integer\">({id}.*?)</number>.*?<summary>({summary}.*?)</summary>.*?</ticket>";
-  }
-
-  @Override
-  protected String getTasksListURLDefault() {
-    return "http://www.assembla.com/tickets.xml";
+  public void resetToDefaults() {
+    super.resetToDefaults();
+    setTasksListUrl("http://www.assembla.com/tickets.xml");
+    setResponseType(ResponseType.TEXT);
   }
 
   @Override
@@ -84,4 +56,11 @@
   protected int getFeatures() {
     return BASIC_HTTP_AUTHORIZATION;
   }
+
+  @Override
+  public ResponseHandler getTextResponseHandlerDefault() {
+    RegExResponseHandler regexHandler = new RegExResponseHandler(this);
+    regexHandler.setTaskRegex(TASK_REGEX);
+    return regexHandler;
+  }
 }
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
new file mode 100644
index 0000000..b374b7f
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml
@@ -0,0 +1,67 @@
+<Generic shared="false" url="https://app.asana.com/api/1.0">
+  <commitMessageFormat>{id} {summary}</commitMessageFormat>
+  <password/>
+  <option name="loginAnonymously" value="false"/>
+  <option name="loginMethodType" value="GET"/>
+  <option name="loginUrl" value=""/>
+  <option name="responseHandlers">
+    <XPathResponseHandler>
+      <selectors>
+        <selector name="tasks" path="foo"/>
+        <selector name="id" path=""/>
+        <selector name="summary" path=""/>
+        <selector name="description" path=""/>
+        <selector name="updated" path=""/>
+        <selector name="created" 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-issueUrl" path=""/>
+      </selectors>
+    </XPathResponseHandler>
+    <JsonResponseHandler>
+      <selectors>
+        <selector name="tasks" path="data[*]"/>
+        <selector name="id" path="id"/>
+        <selector name="summary" path="name"/>
+        <selector name="description" path=""/>
+        <selector name="updated" path=""/>
+        <selector name="created" path=""/>
+        <selector name="completed" path=""/>
+        <selector name="issueUrl" path=""/>
+        <selector name="singleTask-id" path="data.id"/>
+        <selector name="singleTask-summary" path="data.name"/>
+        <selector name="singleTask-description" path="data.notes"/>
+        <selector name="singleTask-updated" path="data.modified_at"/>
+        <selector name="singleTask-created" path="data.created_at"/>
+        <selector name="singleTask-closed" path="data.completed"/>
+        <selector name="singleTask-issueUrl" path=""/>
+      </selectors>
+    </JsonResponseHandler>
+    <RegExResponseHandler>
+      <option name="taskRegex" value=""/>
+    </RegExResponseHandler>
+  </option>
+  <option name="responseType" value="JSON"/>
+  <option name="shouldFormatCommitMessage" value="false"/>
+  <option name="singleTaskMethodType" value="GET"/>
+  <option name="singleTaskUrl" value="{serverUrl}/tasks/{id}"/>
+  <option name="subtypeName"/>
+  <option name="tasksListMethodType" value="GET"/>
+  <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"/>
+        <option name="name" value="project_ID"/>
+        <option name="value" value=""/>
+      </TemplateVariable>
+    </list>
+  </option>
+  <option name="useHttpAuthentication" value="true"/>
+  <option name="useProxy" value="false"/>
+  <username/>
+</Generic>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
index 8c4785e..fb2c776 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
@@ -36,6 +36,7 @@
 import com.intellij.openapi.vcs.VcsType;
 import com.intellij.openapi.vcs.changes.*;
 import com.intellij.tasks.*;
+import com.intellij.tasks.actions.TaskSearchSupport;
 import com.intellij.tasks.config.TaskRepositoriesConfigurable;
 import com.intellij.tasks.context.WorkingContextManager;
 import com.intellij.ui.ColoredTreeCellRenderer;
@@ -571,6 +572,7 @@
           }
           catch (XmlSerializationException e) {
             // ignore
+            LOG.error(e.getMessage());
           }
         }
       }
@@ -766,10 +768,15 @@
         continue;
       }
       try {
-        final Task[] tasks = repository.getIssues(request, max, since, cancelled);
+        Task[] tasks = repository.getIssues(request, max, since, cancelled);
         myBadRepositories.remove(repository);
         if (issues == null) issues = new ArrayList<Task>(tasks.length);
-        ContainerUtil.addAll(issues, tasks);
+        if (!repository.isSupported(TaskRepository.NATIVE_SEARCH)) {
+          List<Task> filteredTasks = TaskSearchSupport.filterTasks(request, ContainerUtil.list(tasks));
+          ContainerUtil.addAll(issues, filteredTasks);
+        } else {
+          ContainerUtil.addAll(issues, tasks);
+        }
       }
       catch (ProcessCanceledException ignored) {
         // OK
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
index 8a9fd91..63b1ca9 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
@@ -118,7 +118,7 @@
 
   @Override
   protected int getFeatures() {
-    return TIME_MANAGEMENT;
+    return super.getFeatures() | TIME_MANAGEMENT;
   }
 
   public String getSearchQuery() {
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 baefe2d..484a357bc 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
@@ -1,6 +1,7 @@
 package com.intellij.tasks.jira.jql.codeinsight;
 
 import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
 import com.intellij.codeInsight.lookup.LookupElementBuilder;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Condition;
@@ -78,16 +79,16 @@
 
   // Patterns:
 
-  public static final PsiElementPattern.Capture<PsiElement> AFTER_CLAUSE_WITH_HISTORY_PREDICATE =
+  private static final PsiElementPattern.Capture<PsiElement> AFTER_CLAUSE_WITH_HISTORY_PREDICATE =
     psiElement().and(rightAfterElement(JqlClauseWithHistoryPredicates.class));
 
   private static final PsiElementPattern.Capture<PsiElement> AFTER_ANY_CLAUSE =
     psiElement().and(rightAfterElement(JqlTerminalClause.class));
 
-  public static final PsiElementPattern.Capture<PsiElement> AFTER_ORDER_KEYWORD =
+  private static final PsiElementPattern.Capture<PsiElement> AFTER_ORDER_KEYWORD =
     psiElement().afterLeaf(psiElement(JqlTokenTypes.ORDER_KEYWORD));
 
-  public static final PsiElementPattern.Capture<PsiElement> AFTER_FIELD_IN_CLAUSE =
+  private static final PsiElementPattern.Capture<PsiElement> AFTER_FIELD_IN_CLAUSE =
     psiElement().and(rightAfterElement(
       psiElement(JqlIdentifier.class).
         andNot(psiElement().inside(JqlFunctionCall.class)).
@@ -103,6 +104,8 @@
       psiElement().withElementType(JqlTokenTypes.AND_OPERATORS),
       psiElement().withElementType(JqlTokenTypes.OR_OPERATORS),
       psiElement().withElementType(JqlTokenTypes.NOT_OPERATORS).
+        andNot(psiElement().inside(JqlTerminalClause.class)),
+      psiElement().withElementType(JqlTokenTypes.LPAR).
         andNot(psiElement().inside(JqlTerminalClause.class))
     )));
 
@@ -259,8 +262,9 @@
                                   @NotNull CompletionResultSet result) {
       JqlFieldType operandType;
       boolean listFunctionExpected;
-      PsiElement pos = parameters.getPosition();
-      JqlHistoryPredicate predicate = PsiTreeUtil.getParentOfType(pos, JqlHistoryPredicate.class);
+      PsiElement curElem = parameters.getPosition();
+      PsiElement origElem = parameters.getOriginalPosition();
+      JqlHistoryPredicate predicate = PsiTreeUtil.getParentOfType(curElem, JqlHistoryPredicate.class);
       if (predicate != null) {
         listFunctionExpected = false;
         JqlHistoryPredicate.Type predicateType = predicate.getType();
@@ -276,15 +280,16 @@
             break;
           // from, to
           default:
-            operandType = findTypeOfField(pos);
+            operandType = findTypeOfField(curElem);
         }
       }
       else {
-        operandType = findTypeOfField(pos);
-        listFunctionExpected = insideClauseWithListOperator(pos);
+        operandType = findTypeOfField(curElem);
+        listFunctionExpected = insideClauseWithListOperator(curElem);
       }
       for (String functionName : JqlStandardFunction.allOfType(operandType, listFunctionExpected)) {
-        result.addElement(LookupElementBuilder.create(functionName + "()"));
+        result.addElement(LookupElementBuilder.create(functionName)
+          .withInsertHandler(ParenthesesInsertHandler.NO_PARAMETERS));
       }
     }
 
@@ -301,15 +306,7 @@
       if (clause == null || clause.getType() == null) {
         return false;
       }
-      switch (clause.getType()) {
-        case IN:
-        case NOT_IN:
-        case WAS_IN:
-        case WAS_NOT_IN:
-          return true;
-        default:
-          return false;
-      }
+      return clause.getType().isListOperator();
     }
   }
 
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardField.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardField.java
index e6b0f96..366d56b 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardField.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardField.java
@@ -5,6 +5,7 @@
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.containers.MultiMap;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -64,7 +65,7 @@
 
   private final String myName;
   private final JqlFieldType myType;
-  private JqlStandardField(String name, JqlFieldType type) {
+  JqlStandardField(String name, JqlFieldType type) {
     myName = name;
     myType = type;
   }
@@ -100,10 +101,10 @@
   }
 
   public static Collection<String> allOfType(JqlFieldType type) {
-    return type == JqlFieldType.UNKNOWN? ALL_FIELDS_NAMES : TYPE_LOOKUP.get(type);
+    return type == JqlFieldType.UNKNOWN? ALL_FIELD_NAMES : new ArrayList<String>(TYPE_LOOKUP.get(type));
   }
 
-  public static final List<String> ALL_FIELDS_NAMES = ContainerUtil.map2List(VALUES, new Function<JqlStandardField, String>() {
+  public static final List<String> ALL_FIELD_NAMES = ContainerUtil.map2List(VALUES, new Function<JqlStandardField, String>() {
     @Override
     public String fun(JqlStandardField field) {
       return field.myName;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardFunction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardFunction.java
index 27f7c6c..8e6cf34 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardFunction.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/codeinsight/JqlStandardFunction.java
@@ -5,10 +5,9 @@
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author Mikhail Golubev
@@ -71,7 +70,7 @@
     }
   });
 
-  public static JqlStandardFunction byName(String name) {
+  public static JqlStandardFunction byName(@NotNull String name) {
     return NAME_LOOKUP.get(name);
   }
 
@@ -82,8 +81,11 @@
     }
   }
 
-  public static Collection<String> allOfType(JqlFieldType type, boolean multipleResults) {
-    return type == JqlFieldType.UNKNOWN? ALL_FUNCTION_NAMES : TYPE_LOOKUP.get(Pair.create(type, multipleResults));
+  public static List<String> allOfType(@NotNull JqlFieldType type, boolean multipleResults) {
+    if (type == JqlFieldType.UNKNOWN) {
+      return ALL_FUNCTION_NAMES;
+    }
+    return new ArrayList<String>(TYPE_LOOKUP.get(Pair.create(type, multipleResults)));
   }
 
   public static final List<String> ALL_FUNCTION_NAMES = ContainerUtil.map2List(VALUES, new Function<JqlStandardFunction, String>() {
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 c087181..d16a106 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
@@ -12,25 +12,32 @@
  */
 public interface JqlTerminalClause extends JqlElement {
   enum Type {
-    EQ,
-    NE,
-    LT,
-    GT,
-    LE,
-    GE,
-    CONTAINS,
-    NOT_CONTAINS,
-    IS,
-    IS_NOT,
-    IN,
-    NOT_IN,
-    WAS,
-    WAS_IN,
-    WAS_NOT,
-    WAS_NOT_IN,
-    CHANGED;
+    EQ(false),
+    NE(false),
+    LT(false),
+    GT(false),
+    LE(false),
+    GE(false),
+    CONTAINS(false),
+    NOT_CONTAINS(false),
+    IS(false),
+    IS_NOT(false),
+    IN(true),
+    NOT_IN(true),
+    WAS(false),
+    WAS_IN(true),
+    WAS_NOT(false),
+    WAS_NOT_IN(true),
+    CHANGED(false);
+
+    private boolean myListOperator;
+
+    Type(boolean listOperator) {
+      myListOperator = listOperator;
+    }
 
     private final static IdentityHashMap<IElementType, Type> MAP = new IdentityHashMap<IElementType, Type>();
+
     static {
       MAP.put(JqlTokenTypes.EQ, EQ);
       MAP.put(JqlTokenTypes.NE, NE);
@@ -47,6 +54,9 @@
       return MAP.get(type);
     }
 
+    public boolean isListOperator() {
+      return myListOperator;
+    }
   }
 
   @Nullable
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java
index 9b8ba34..e3e533c 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java
@@ -6,7 +6,6 @@
 import com.intellij.tasks.Comment;
 import com.intellij.tasks.Task;
 import com.intellij.tasks.TaskRepositoryType;
-import com.intellij.tasks.actions.TaskSearchSupport;
 import com.intellij.tasks.impl.BaseRepository;
 import com.intellij.tasks.impl.BaseRepositoryImpl;
 import com.intellij.tasks.mantis.model.*;
@@ -85,8 +84,7 @@
     while (true) {
       cancelled.checkCanceled();
       final List<Task> issuesFromPage = getIssues(page, issuesOnPage, soap);
-      final List<Task> filteredTasks = TaskSearchSupport.filterTasks(query != null ? query : "", issuesFromPage);
-      tasks.addAll(filteredTasks);
+      tasks.addAll(issuesFromPage);
       if (issuesFromPage.size() < issuesOnPage || tasks.size() >= max) {
         break;
       }
@@ -275,4 +273,9 @@
            Comparing.equal(getProject(), ((MantisRepository)o).getProject()) &&
            Comparing.equal(getFilter(), ((MantisRepository)o).getFilter());
   }
+
+  @Override
+  protected int getFeatures() {
+    return super.getFeatures() & ~NATIVE_SEARCH;
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
index 48c6054..c0d46b8 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
@@ -363,6 +363,6 @@
 
   @Override
   protected int getFeatures() {
-    return BASIC_HTTP_AUTHORIZATION;
+    return super.getFeatures() | BASIC_HTTP_AUTHORIZATION;
   }
 }
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 f2b082d..847d7b1 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
@@ -308,6 +308,6 @@
 
   @Override
   protected int getFeatures() {
-    return BASIC_HTTP_AUTHORIZATION;
+    return super.getFeatures() | BASIC_HTTP_AUTHORIZATION;
   }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
index 6d9a771..19dadba 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
@@ -269,6 +269,6 @@
 
   @Override
   protected int getFeatures() {
-    return BASIC_HTTP_AUTHORIZATION;
+    return super.getFeatures() | BASIC_HTTP_AUTHORIZATION;
   }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
index 0430dea..80d5246 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java
@@ -330,7 +330,7 @@
   }
 
   @Override
-  public String getUrl() {
+  public String getPresentableName() {
     String pseudoUrl = "trello.com";
     if (myCurrentBoard != null) {
       pseudoUrl += "/" + myCurrentBoard.getName();
@@ -353,4 +353,19 @@
       }
     };
   }
+
+  @Override
+  public boolean isConfigured() {
+    return super.isConfigured() && StringUtil.isNotEmpty(myPassword);
+  }
+
+  @Override
+  public String getUrl() {
+    return "trello.com";
+  }
+
+  @Override
+  protected int getFeatures() {
+    return super.getFeatures() & ~NATIVE_SEARCH;
+  }
 }
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java
index 3fb032d..86fca7a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java
@@ -18,8 +18,8 @@
 
 import com.intellij.openapi.project.Project;
 import com.intellij.tasks.TaskRepository;
-import com.intellij.tasks.TaskRepositoryType;
 import com.intellij.tasks.config.TaskRepositoryEditor;
+import com.intellij.tasks.impl.BaseRepositoryType;
 import com.intellij.util.Consumer;
 import icons.TasksIcons;
 import org.jetbrains.annotations.NotNull;
@@ -30,7 +30,7 @@
 /**
  * @author Mikhail Golubev
  */
-public class TrelloRepositoryType extends TaskRepositoryType<TrelloRepository> {
+public class TrelloRepositoryType extends BaseRepositoryType<TrelloRepository> {
   public static final String DEVELOPER_KEY = "d6ec3709f7141007e150de64d4701181";
   public static final String CLIENT_AUTHORIZATION_URL =
     "https://trello.com/1/authorize?key=" + DEVELOPER_KEY +"&name=JetBrains&expiration=never&response_type=token";
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
index 1ff6d9d..44fa593 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
@@ -317,6 +317,6 @@
 
   @Override
   protected int getFeatures() {
-    return TIME_MANAGEMENT;
+    return super.getFeatures() | TIME_MANAGEMENT;
   }
 }
diff --git a/plugins/tasks/tasks-core/src/icons/TasksIcons.java b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
index b089872..3313ba8 100644
--- a/plugins/tasks/tasks-core/src/icons/TasksIcons.java
+++ b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
@@ -40,6 +40,7 @@
   public static final Icon Trac = load("/icons/trac.png"); // 16x16
   public static final Icon Unknown = load("/icons/unknown.png"); // 16x16
   public static final Icon Youtrack = load("/icons/youtrack.png"); // 16x16
+  public static final Icon Asana = load("/icons/asana.png"); // 16x16
   public static final Icon Trello = load("/icons/trello.png"); // 16x16
   public static final Icon JIRA = load("/icons/jira.png"); // 16x16
 }
diff --git a/plugins/tasks/tasks-core/src/icons/asana.png b/plugins/tasks/tasks-core/src/icons/asana.png
new file mode 100644
index 0000000..25cea96
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/icons/asana.png
Binary files differ
diff --git a/plugins/tasks/tasks-core/tasks-core.iml b/plugins/tasks/tasks-core/tasks-core.iml
index 707b452..11c3bc9 100644
--- a/plugins/tasks/tasks-core/tasks-core.iml
+++ b/plugins/tasks/tasks-core/tasks-core.iml
@@ -27,8 +27,38 @@
     </orderEntry>
     <orderEntry type="library" exported="" name="http-client-3.1" level="project" />
     <orderEntry type="library" name="XmlRPC" level="project" />
+    <orderEntry type="module-library" exported="">
+      <library name="markdownj">
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/markdownj-core-0.4.2-SNAPSHOT.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
     <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>
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/json-path-0.8.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/json-smart-1.1.1.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
     <orderEntry type="module-library">
       <library>
         <CLASSES>
@@ -41,7 +71,6 @@
     <orderEntry type="module" module-name="xdebugger-api" />
     <orderEntry type="module" module-name="xdebugger-impl" />
     <orderEntry type="library" exported="" name="markdownj" level="project" />
-    <orderEntry type="module" module-name="core-api" />
   </component>
 </module>
 
diff --git a/plugins/tasks/tasks-tests/tasks-tests.iml b/plugins/tasks/tasks-tests/tasks-tests.iml
index deeddcc..a1d5001 100644
--- a/plugins/tasks/tasks-tests/tasks-tests.iml
+++ b/plugins/tasks/tasks-tests/tasks-tests.iml
@@ -18,6 +18,8 @@
     <orderEntry type="module" module-name="xslt-debugger" />
     <orderEntry type="module" module-name="xdebugger-impl" scope="TEST" />
     <orderEntry type="module" module-name="git4idea" scope="TEST" />
+    <orderEntry type="module" module-name="remote-servers-impl" scope="TEST" />
+    <orderEntry type="module" module-name="manifest" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java
new file mode 100644
index 0000000..1a6d3bf
--- /dev/null
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.tasks.integration;
+
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskManagerTestCase;
+import com.intellij.tasks.generic.GenericRepository;
+import com.intellij.tasks.generic.GenericRepositoryType;
+import com.intellij.tasks.generic.GenericTask;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class AsanaGenericIntegrationTest extends TaskManagerTestCase {
+  private static final String RESPONSE = "" +
+   "{\n" +
+   "  \"data\": [\n" +
+   "    {\n" +
+   "      \"id\": 5479650606120,\n" +
+   "      \"name\": \"Task #1\"\n" +
+   "    },\n" +
+   "    {\n" +
+   "      \"id\": 5202014833559,\n" +
+   "      \"name\": \"Task #2\"\n" +
+   "    }\n" +
+   "  ]\n" +
+   "}";
+
+  private GenericRepository myRepository;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    GenericRepositoryType genericType = new GenericRepositoryType();
+    myRepository = (GenericRepository) genericType.new AsanaRepository().createRepository();
+  }
+
+  public void testParsing() throws Exception {
+    Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(RESPONSE);
+    List<Task> expected = ContainerUtil.<Task>newArrayList(
+      new GenericTask("5479650606120", "Task #1", myRepository),
+      new GenericTask("5202014833559", "Task #2", myRepository)
+    );
+    assertEquals(expected, Arrays.asList(tasks));
+  }
+}
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
index 1f26161..43a8af6 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
@@ -26,42 +26,44 @@
  */
 public class AssemblaIntegrationTest extends TaskManagerTestCase {
 
+  public static final String RESPONSE =
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+    "<tickets type=\"array\">\n" +
+    "<ticket>\n" +
+    "  <assigned-to-id>dsNkyYr0Gr4iEBeJe5cbCb</assigned-to-id>\n" +
+    "  <completed-date type=\"datetime\"></completed-date>\n" +
+    "  <component-id type=\"integer\"></component-id>\n" +
+    "  <created-on type=\"datetime\">2013-04-01T10:45:06+03:00</created-on>\n" +
+    "  <description></description>\n" +
+    "  <from-support type=\"integer\">0</from-support>\n" +
+    "  <id type=\"integer\">50351983</id>\n" +
+    "  <importance type=\"integer\">-1</importance>\n" +
+    "  <importance-float type=\"float\">-1.0</importance-float>\n" +
+    "  <is-story type=\"boolean\">false</is-story>\n" +
+    "  <milestone-id type=\"integer\"></milestone-id>\n" +
+    "  <notification-list>dsNkyYr0Gr4iEBeJe5cbCb</notification-list>\n" +
+    "  <number type=\"integer\">1</number>\n" +
+    "  <priority type=\"integer\">3</priority>\n" +
+    "  <reporter-id>dsNkyYr0Gr4iEBeJe5cbCb</reporter-id>\n" +
+    "  <space-id>ab1WOCMQar4QGgacwqjQWU</space-id>\n" +
+    "  <status type='integer'>0</status>\n" +
+    "  <status-name>New</status-name>\n" +
+    "  <story-importance type=\"integer\">0</story-importance>\n" +
+    "  <summary>&#1055;&#1088;&#1080;&#1074;&#1077;&#1090;</summary>\n" +
+    "  <updated-at type=\"datetime\">2013-04-01T10:48:19+03:00</updated-at>\n" +
+    "  <working-hours type=\"float\">0.0</working-hours>\n" +
+    "  <working-hour type=\"float\" warning=\"deprecated\">0.0</working-hour>\n" +
+    "  <estimate type=\"string\">Small</estimate>\n" +
+    "  <total-estimate type=\"float\">1.0</total-estimate>\n" +
+    "  <invested-hours type=\"float\">0.0</invested-hours>\n" +
+    "  <assigned-to><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></assigned-to>\n" +
+    "  <reporter><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></reporter>\n" +
+    "</ticket>\n" +
+    "</tickets>";
+
   public void testParseCyrillic() throws Exception {
-
-    Task[] tasks = new AssemblaRepository(new AssemblaRepositoryType()).parseResponse("", 100, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
-                                                                                               "<tickets type=\"array\">\n" +
-                                                                                               "<ticket>\n" +
-                                                                                               "  <assigned-to-id>dsNkyYr0Gr4iEBeJe5cbCb</assigned-to-id>\n" +
-                                                                                               "  <completed-date type=\"datetime\"></completed-date>\n" +
-                                                                                               "  <component-id type=\"integer\"></component-id>\n" +
-                                                                                               "  <created-on type=\"datetime\">2013-04-01T10:45:06+03:00</created-on>\n" +
-                                                                                               "  <description></description>\n" +
-                                                                                               "  <from-support type=\"integer\">0</from-support>\n" +
-                                                                                               "  <id type=\"integer\">50351983</id>\n" +
-                                                                                               "  <importance type=\"integer\">-1</importance>\n" +
-                                                                                               "  <importance-float type=\"float\">-1.0</importance-float>\n" +
-                                                                                               "  <is-story type=\"boolean\">false</is-story>\n" +
-                                                                                               "  <milestone-id type=\"integer\"></milestone-id>\n" +
-                                                                                               "  <notification-list>dsNkyYr0Gr4iEBeJe5cbCb</notification-list>\n" +
-                                                                                               "  <number type=\"integer\">1</number>\n" +
-                                                                                               "  <priority type=\"integer\">3</priority>\n" +
-                                                                                               "  <reporter-id>dsNkyYr0Gr4iEBeJe5cbCb</reporter-id>\n" +
-                                                                                               "  <space-id>ab1WOCMQar4QGgacwqjQWU</space-id>\n" +
-                                                                                               "  <status type='integer'>0</status>\n" +
-                                                                                               "  <status-name>New</status-name>\n" +
-                                                                                               "  <story-importance type=\"integer\">0</story-importance>\n" +
-                                                                                               "  <summary>&#1055;&#1088;&#1080;&#1074;&#1077;&#1090;</summary>\n" +
-                                                                                               "  <updated-at type=\"datetime\">2013-04-01T10:48:19+03:00</updated-at>\n" +
-                                                                                               "  <working-hours type=\"float\">0.0</working-hours>\n" +
-                                                                                               "  <working-hour type=\"float\" warning=\"deprecated\">0.0</working-hour>\n" +
-                                                                                               "  <estimate type=\"string\">Small</estimate>\n" +
-                                                                                               "  <total-estimate type=\"float\">1.0</total-estimate>\n" +
-                                                                                               "  <invested-hours type=\"float\">0.0</invested-hours>\n" +
-                                                                                               "  <assigned-to><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></assigned-to>\n" +
-                                                                                               "  <reporter><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></reporter>\n" +
-                                                                                               "</ticket>\n" +
-                                                                                               "</tickets>");
-
+    AssemblaRepository repository = new AssemblaRepository(new AssemblaRepositoryType());
+    Task[] tasks = repository.getActiveResponseHandler().parseIssues(RESPONSE);
     assertEquals(1, tasks.length);
     assertEquals("\u041F\u0440\u0438\u0432\u0435\u0442", tasks[0].getSummary());
   }
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 bf56b70..d3ee5b1 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
@@ -1,18 +1,17 @@
 package com.intellij.tasks.jira.jql;
 
 import com.intellij.tasks.jira.jql.codeinsight.JqlFieldType;
-import com.intellij.tasks.jira.jql.codeinsight.JqlStandardField;
 import com.intellij.tasks.jira.jql.codeinsight.JqlStandardFunction;
 import com.intellij.testFramework.IdeaTestCase;
 import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
 import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
+import static com.intellij.tasks.jira.jql.codeinsight.JqlStandardField.*;
+import static com.intellij.tasks.jira.jql.codeinsight.JqlStandardFunction.ALL_FUNCTION_NAMES;
+
 /**
  * @author Mikhail Golubev
  */
@@ -39,28 +38,16 @@
   }
 
   private void checkCompletionVariants(List<String> initial, String... others) {
-    List<String> variants = new ArrayList<String>(initial);
-    ContainerUtil.addAll(variants, others);
-    myFixture.testCompletionVariants(getTestFilePath(), ArrayUtil.toStringArray(variants));
+    myFixture.testCompletionVariants(getTestFilePath(),
+                                     ArrayUtil.toStringArray(ContainerUtil.concat(true, initial, others)));
   }
 
   private void checkCompletionVariants(String... variants) {
     checkCompletionVariants(ContainerUtil.<String>emptyList(), variants);
   }
 
-  private static List<String> parenthesize(Collection<String> names) {
-    return ContainerUtil.map2List(names, new Function<String, String>() {
-      @Override
-      public String fun(String s) {
-        return s + "()";
-      }
-    });
-  }
-
-  private static final List<String> PARENTHESIZED_FUNCTION_NAMES = parenthesize(JqlStandardFunction.ALL_FUNCTION_NAMES);
-
   public void testBeginningOfLine() throws Exception {
-    checkCompletionVariants(JqlStandardField.ALL_FIELDS_NAMES, "not");
+    checkCompletionVariants(ALL_FIELD_NAMES, "not");
   }
 
   public void testAfterClause() throws Exception {
@@ -98,44 +85,47 @@
   }
 
   public void testFunctionType1() throws Exception {
-    checkCompletionVariants("membersOf()");
+    checkCompletionVariants("membersOf");
   }
 
   public void testFunctionType2() throws Exception {
-    checkCompletionVariants("currentUser()");
+    checkCompletionVariants("currentUser");
   }
 
   public void testFunctionType3() throws Exception {
-    checkCompletionVariants("currentUser()");
+    checkCompletionVariants("currentUser");
   }
 
   public void testFunctionType4() throws Exception {
-    checkCompletionVariants(parenthesize(JqlStandardFunction.allOfType(JqlFieldType.DATE, false)));
+    checkCompletionVariants(JqlStandardFunction.allOfType(JqlFieldType.DATE, false));
   }
 
   public void testFunctionType5() throws Exception {
-    checkCompletionVariants(parenthesize(JqlStandardFunction.allOfType(JqlFieldType.DATE, false)));
+    checkCompletionVariants(JqlStandardFunction.allOfType(JqlFieldType.DATE, false));
   }
 
-  /**
-   * "not |" -> "not not |", "not field |"
-   */
+  public void testAfterParenthesisInSubClause() throws Exception {
+    checkCompletionVariants(ALL_FIELD_NAMES, "not");
+  }
+
+  public void testFunctionArguments() throws Exception {
+    // only literals accepted so we can't assume anything
+    checkCompletionVariants(ContainerUtil.<String>emptyList());
+  }
+
   public void testAfterNotKeywordInNotClause() throws Exception {
-    checkCompletionVariants(JqlStandardField.ALL_FIELDS_NAMES, "not");
+    checkCompletionVariants(ALL_FIELD_NAMES, "not");
   }
 
   public void testAfterOrderKeyword() throws Exception {
     checkCompletionVariants("by");
   }
 
-  /**
-   * "foo was |" -> "foo was func()", "foo was not |", "foo was in |"
-   */
   public void testAfterWasKeyword() throws Exception {
-    checkCompletionVariants(PARENTHESIZED_FUNCTION_NAMES, "not", "in");
+    checkCompletionVariants(ALL_FUNCTION_NAMES, "not", "in");
   }
 
   public void testInList() throws Exception {
-    checkCompletionVariants(PARENTHESIZED_FUNCTION_NAMES);
+    checkCompletionVariants(ALL_FUNCTION_NAMES);
   }
 }
diff --git a/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterParenthesisInSubClause.jql b/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterParenthesisInSubClause.jql
new file mode 100644
index 0000000..66abe15
--- /dev/null
+++ b/plugins/tasks/tasks-tests/testData/jira/jql/completion/AfterParenthesisInSubClause.jql
@@ -0,0 +1 @@
+reporter = "Bob" and (<caret>)
\ No newline at end of file
diff --git a/plugins/tasks/tasks-tests/testData/jira/jql/completion/FunctionArguments.jql b/plugins/tasks/tasks-tests/testData/jira/jql/completion/FunctionArguments.jql
new file mode 100644
index 0000000..685ddbc
--- /dev/null
+++ b/plugins/tasks/tasks-tests/testData/jira/jql/completion/FunctionArguments.jql
@@ -0,0 +1 @@
+status was not someFunction(<caret>)
\ No newline at end of file
diff --git a/plugins/terminal/lib/jna-platform.jar b/plugins/terminal/lib/jna-platform.jar
new file mode 100644
index 0000000..4b3d567
--- /dev/null
+++ b/plugins/terminal/lib/jna-platform.jar
Binary files differ
diff --git a/plugins/terminal/lib/libwinpty.dll b/plugins/terminal/lib/libwinpty.dll
deleted file mode 100644
index 9a7eaf6..0000000
--- a/plugins/terminal/lib/libwinpty.dll
+++ /dev/null
Binary files differ
diff --git a/plugins/terminal/lib/linux/x86/libpty.so b/plugins/terminal/lib/linux/x86/libpty.so
new file mode 100755
index 0000000..f6d92d7
--- /dev/null
+++ b/plugins/terminal/lib/linux/x86/libpty.so
Binary files differ
diff --git a/plugins/terminal/lib/linux/x86_64/libpty.so b/plugins/terminal/lib/linux/x86_64/libpty.so
new file mode 100755
index 0000000..4417e95
--- /dev/null
+++ b/plugins/terminal/lib/linux/x86_64/libpty.so
Binary files differ
diff --git a/plugins/terminal/lib/macosx/x86/libpty.dylib b/plugins/terminal/lib/macosx/x86/libpty.dylib
new file mode 100755
index 0000000..e4f428d
--- /dev/null
+++ b/plugins/terminal/lib/macosx/x86/libpty.dylib
Binary files differ
diff --git a/plugins/terminal/lib/pty4j-0.3.jar b/plugins/terminal/lib/pty4j-0.3.jar
index 38b0470..a4d2cb9 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/lib/winpty-agent.exe b/plugins/terminal/lib/winpty-agent.exe
deleted file mode 100644
index 87431b5..0000000
--- a/plugins/terminal/lib/winpty-agent.exe
+++ /dev/null
Binary files differ
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
index bd540bfa..dc8c410 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
@@ -4,8 +4,8 @@
 import com.intellij.execution.process.*;
 import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModuleRootManager;
 import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.text.StringUtil;
@@ -16,14 +16,12 @@
 import com.jediterm.terminal.TtyConnector;
 import com.pty4j.PtyProcess;
 import com.pty4j.util.PtyUtil;
-import com.pty4j.windows.WinPty;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.charset.Charset;
-import java.security.CodeSource;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
@@ -32,6 +30,7 @@
  * @author traff
  */
 public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess> {
+  private static final Logger LOG = Logger.getInstance(LocalTerminalDirectRunner.class);
 
   private final Charset myDefaultCharset;
   private final String[] myCommand;
@@ -56,13 +55,18 @@
   }
 
   private static File findRCFile() {
-    String folder = PtyUtil.getJarFolder();
-    if (folder != null) {
-      File rcFile = new File(folder, "jediterm.in");
-      if (rcFile.exists()) {
-        return rcFile;
+    try {
+      final String folder = PtyUtil.getJarFolder();
+      if (folder != null) {
+        File rcFile = new File(folder, "jediterm.in");
+        if (rcFile.exists()) {
+          return rcFile;
+        }
       }
     }
+    catch (Exception e) {
+      LOG.warn("Unable to get jar folder", e);
+    }
     return null;
   }
 
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
index ad7d06a..7d57aac 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
@@ -1,5 +1,6 @@
 package org.jetbrains.plugins.terminal;
 
+import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.wm.ToolWindow;
 import com.intellij.openapi.wm.ToolWindowFactory;
@@ -7,7 +8,7 @@
 /**
  * @author traff
  */
-public class TerminalToolWindowFactory implements ToolWindowFactory {
+public class TerminalToolWindowFactory implements ToolWindowFactory, DumbAware {
   @Override
   public void createToolWindowContent(Project project, ToolWindow toolWindow) {
     TerminalView terminalView = TerminalView.getInstance();
diff --git a/plugins/testng/src/META-INF/plugin.xml b/plugins/testng/src/META-INF/plugin.xml
index 0315fc3..fe64bc8 100644
--- a/plugins/testng/src/META-INF/plugin.xml
+++ b/plugins/testng/src/META-INF/plugin.xml
@@ -8,10 +8,10 @@
         <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
         <deadCode implementation="com.theoryinpractice.testng.inspection.TestNGEntryPoint"/>
         <cantBeStatic implementation="com.theoryinpractice.testng.inspection.TestNGCanBeStaticExtension" />
-        <configurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGPatternConfigurationProducer"/>
-        <configurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGInClassConfigurationProducer"/>
-        <configurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGPackageConfigurationProducer"/>
-        <configurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGSuiteConfigurationProducer"/>
+        <runConfigurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGPatternConfigurationProducer"/>
+        <runConfigurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGInClassConfigurationProducer"/>
+        <runConfigurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGPackageConfigurationProducer"/>
+        <runConfigurationProducer implementation="com.theoryinpractice.testng.configuration.TestNGSuiteConfigurationProducer"/>
         <configurationType implementation="com.theoryinpractice.testng.configuration.TestNGConfigurationType"/>
        <psi.referenceContributor language="JAVA" implementation="com.theoryinpractice.testng.TestNGReferenceContributor"/>
        <psi.referenceContributor language="XML" implementation="com.theoryinpractice.testng.TestNGSuiteReferenceContributor"/>
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java
index 2baeab6..5d3bbb9 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java
@@ -20,50 +20,46 @@
  */
 package com.theoryinpractice.testng.configuration;
 
-import com.intellij.execution.Location;
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.*;
 import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.actions.RunConfigurationProducer;
+import com.intellij.execution.configurations.RunConfiguration;
 import com.intellij.execution.impl.RunManagerImpl;
+import com.intellij.execution.junit.JUnitUtil;
+import com.intellij.execution.junit.JavaRunConfigurationProducerBase;
 import com.intellij.execution.junit.JavaRuntimeConfigurationProducerBase;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.util.Comparing;
-import com.intellij.psi.PsiElement;
+import com.intellij.psi.*;
 import com.theoryinpractice.testng.model.TestData;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 
-public abstract class TestNGConfigurationProducer extends JavaRuntimeConfigurationProducerBase implements Cloneable {
+public abstract class TestNGConfigurationProducer extends JavaRunConfigurationProducerBase<TestNGConfiguration> implements Cloneable {
 
   public TestNGConfigurationProducer() {
     super(TestNGConfigurationType.getInstance());
   }
 
   @Override
-  protected RunnerAndConfigurationSettings findExistingByElement(Location location,
-                                                                 @NotNull List<RunnerAndConfigurationSettings> existingConfigurations,
-                                                                 ConfigurationContext context) {
-    final TestNGConfiguration testNGConfiguration =
-      (TestNGConfiguration)context.getOriginalConfiguration(TestNGConfigurationType.getInstance());
-    final String vmParameters = testNGConfiguration != null ? testNGConfiguration.getVMParameters() : null;
-    final Module predefinedModule =
-              ((TestNGConfiguration)((RunManagerImpl)RunManagerEx.getInstanceEx(location.getProject()))
-                .getConfigurationTemplate(getConfigurationFactory())
-                .getConfiguration()).getConfigurationModule().getModule();
-    for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) {
-      TestNGConfiguration config = (TestNGConfiguration)existingConfiguration.getConfiguration();
-      if (vmParameters != null && !Comparing.strEqual(config.getVMParameters(), vmParameters)) continue;
-      TestData testobject = config.getPersistantData();
-      if (testobject != null){
-        final PsiElement element = location.getPsiElement();
-        if (testobject.isConfiguredByElement(element)) {
-          final Module configurationModule = config.getConfigurationModule().getModule();
-          if (Comparing.equal(location.getModule(), configurationModule)) return existingConfiguration;
-          if (Comparing.equal(predefinedModule, configurationModule)) return existingConfiguration;
-        }
+  public boolean isConfigurationFromContext(TestNGConfiguration testNGConfiguration, ConfigurationContext context) {
+    final RunConfiguration predefinedConfiguration = context.getOriginalConfiguration(TestNGConfigurationType.getInstance());
+    Location location = JavaExecutionUtil.stepIntoSingleClass(context.getLocation());
+    final PsiElement element = location.getPsiElement();
+    RunnerAndConfigurationSettings template = RunManager.getInstance(location.getProject()).getConfigurationTemplate(getConfigurationFactory());
+    final Module predefinedModule = ((TestNGConfiguration)template.getConfiguration()).getConfigurationModule().getModule();
+    final String vmParameters =
+      predefinedConfiguration instanceof TestNGConfiguration ? ((TestNGConfiguration)predefinedConfiguration).getVMParameters() : null;
+    if (vmParameters != null && !Comparing.strEqual(vmParameters, testNGConfiguration.getVMParameters())) return false;
+    TestData testobject = testNGConfiguration.getPersistantData();
+    if (testobject != null) {
+      if (testobject.isConfiguredByElement(element)) {
+        final Module configurationModule = testNGConfiguration.getConfigurationModule().getModule();
+        if (Comparing.equal(location.getModule(), configurationModule)) return true;
+        if (Comparing.equal(predefinedModule, configurationModule)) return true;
       }
     }
-    return null;
+    return false;
   }
 }
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGInClassConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGInClassConfigurationProducer.java
index 815a847..b613e1d 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGInClassConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGInClassConfigurationProducer.java
@@ -25,14 +25,20 @@
 import com.intellij.execution.PsiLocation;
 import com.intellij.execution.RunnerAndConfigurationSettings;
 import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.actions.ConfigurationFromContext;
 import com.intellij.execution.junit.InheritorChooser;
+import com.intellij.execution.junit.JUnitUtil;
+import com.intellij.execution.junit.JavaRuntimeConfigurationProducerBase;
+import com.intellij.execution.junit2.info.LocationUtil;
 import com.intellij.execution.junit2.info.MethodLocation;
 import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiClassUtil;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.theoryinpractice.testng.model.TestData;
 import com.theoryinpractice.testng.util.TestNGUtil;
 import org.jetbrains.annotations.Nullable;
 
@@ -41,74 +47,12 @@
 public class TestNGInClassConfigurationProducer extends TestNGConfigurationProducer{
   private PsiElement myPsiElement = null;
 
-  public PsiElement getSourceElement() {
-    return myPsiElement;
-  }
-
-  @Nullable
-  protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) {
-    final PsiElement[] elements = context != null ? LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()) : null;
-    if (elements != null && TestNGPatternConfigurationProducer.collectTestMembers(elements).size() > 1) {
-      return null;
-    }
-
-    PsiClass psiClass = null;
-    PsiElement element = location.getPsiElement();
-    while (element != null) {
-      if (element instanceof PsiClass && isTestNGClass((PsiClass)element)) {
-        psiClass = (PsiClass)element;
-        break;
-      }
-      else if (element instanceof PsiMember) {
-        psiClass = ((PsiMember)element).getContainingClass();
-        if (isTestNGClass(psiClass)) {
-          break;
-        }
-      }
-      else if (element instanceof PsiClassOwner) {
-        final PsiClass[] classes = ((PsiClassOwner)element).getClasses();
-        if (classes.length == 1) {
-          psiClass = classes[0];
-          break;
-        }
-      }
-      element = element.getParent();
-    }
-    if (!isTestNGClass(psiClass)) return null;
-
-    myPsiElement = psiClass;
-    final Project project = location.getProject();
-    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
-    final TestNGConfiguration configuration = (TestNGConfiguration)settings.getConfiguration();
-    setupConfigurationModule(context, configuration);
-    final Module originalModule = configuration.getConfigurationModule().getModule();
-    configuration.setClassConfiguration(psiClass);
-
-    PsiMethod method = PsiTreeUtil.getParentOfType(location.getPsiElement(), PsiMethod.class, false);
-    while (method != null) {
-      if (TestNGUtil.hasTest(method)) {
-        configuration.setMethodConfiguration(PsiLocation.fromPsiElement(project, method));
-        myPsiElement = method;
-      }
-      method = PsiTreeUtil.getParentOfType(method, PsiMethod.class);
-    }
-
-    configuration.restoreOriginalModule(originalModule);
-    settings.setName(configuration.getName());
-    JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location);
-    return settings;
-  }
-
   private static boolean isTestNGClass(PsiClass psiClass) {
     return psiClass != null && PsiClassUtil.isRunnableClass(psiClass, true, false) && TestNGUtil.hasTest(psiClass);
   }
 
-  public int compareTo(Object o) {
-    return PREFERED;
-  }
-
   @Override
-  public void perform(final ConfigurationContext context, final Runnable performRunnable) {
+  public void onFirstRun(ConfigurationFromContext configuration, ConfigurationContext fromContext, Runnable performRunnable) {
     if (myPsiElement instanceof PsiMethod || myPsiElement instanceof PsiClass) {
 
       final PsiMethod psiMethod;
@@ -144,8 +88,63 @@
           super.runForClass(aClass, psiMethod, context, performRunnable);
         }
       };
-      if (inheritorChooser.runMethodInAbstractClass(context, performRunnable, psiMethod, containingClass)) return;
+      if (inheritorChooser.runMethodInAbstractClass(fromContext, performRunnable, psiMethod, containingClass)) return;
     }
-    super.perform(context, performRunnable);
+    super.onFirstRun(configuration, fromContext, performRunnable);
+  }
+
+  @Override
+  protected boolean setupConfigurationFromContext(TestNGConfiguration configuration,
+                                                  ConfigurationContext context,
+                                                  Ref<PsiElement> sourceElement) {
+    final PsiElement[] elements = context != null ? LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()) : null;
+    if (elements != null && TestNGPatternConfigurationProducer.collectTestMembers(elements).size() > 1) {
+      return false;
+    }
+
+    PsiClass psiClass = null;
+    PsiElement element = context.getPsiLocation();
+    while (element != null) {
+      if (element instanceof PsiClass && isTestNGClass((PsiClass)element)) {
+        psiClass = (PsiClass)element;
+        break;
+      }
+      else if (element instanceof PsiMember) {
+        psiClass = ((PsiMember)element).getContainingClass();
+        if (isTestNGClass(psiClass)) {
+          break;
+        }
+      }
+      else if (element instanceof PsiClassOwner) {
+        final PsiClass[] classes = ((PsiClassOwner)element).getClasses();
+        if (classes.length == 1) {
+          psiClass = classes[0];
+          break;
+        }
+      }
+      element = element.getParent();
+    }
+    if (!isTestNGClass(psiClass)) return false;
+
+    myPsiElement = psiClass;
+    final Project project = context.getProject();
+    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(context);
+    setupConfigurationModule(context, configuration);
+    final Module originalModule = configuration.getConfigurationModule().getModule();
+    configuration.setClassConfiguration(psiClass);
+
+    PsiMethod method = PsiTreeUtil.getParentOfType(context.getPsiLocation(), PsiMethod.class, false);
+    while (method != null) {
+      if (TestNGUtil.hasTest(method)) {
+        configuration.setMethodConfiguration(PsiLocation.fromPsiElement(project, method));
+        myPsiElement = method;
+      }
+      method = PsiTreeUtil.getParentOfType(method, PsiMethod.class);
+    }
+
+    configuration.restoreOriginalModule(originalModule);
+    settings.setName(configuration.getName());
+    sourceElement.set(myPsiElement);
+    return true;
   }
 }
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPackageConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPackageConfigurationProducer.java
index 5bf6ac9..3939e0c 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPackageConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPackageConfigurationProducer.java
@@ -19,8 +19,10 @@
 import com.intellij.execution.Location;
 import com.intellij.execution.RunnerAndConfigurationSettings;
 import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.junit.JavaRuntimeConfigurationProducerBase;
 import com.intellij.execution.junit2.info.LocationUtil;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiPackage;
 import com.theoryinpractice.testng.model.TestData;
@@ -28,30 +30,23 @@
 import com.theoryinpractice.testng.util.TestNGUtil;
 
 public class TestNGPackageConfigurationProducer extends TestNGConfigurationProducer {
-  private PsiPackage myPackage = null;
 
-  protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) {
-    final Project project = location.getProject();
-    final PsiElement element = location.getPsiElement();
-    myPackage = checkPackage(element);
-    if (myPackage == null) return null;
-    if (!LocationUtil.isJarAttached(location, myPackage, TestNGUtil.TEST_ANNOTATION_FQN)) return null;
-    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
-    final TestNGConfiguration configuration = (TestNGConfiguration)settings.getConfiguration();
+  @Override
+  protected boolean setupConfigurationFromContext(TestNGConfiguration configuration,
+                                                  ConfigurationContext context,
+                                                  Ref<PsiElement> sourceElement) {
+    final PsiElement element = context.getPsiLocation();
+    PsiPackage aPackage = JavaRuntimeConfigurationProducerBase.checkPackage(element);
+    if (aPackage == null) return false;
+    final Location location = context.getLocation();
+    if (!LocationUtil.isJarAttached(location, aPackage, TestNGUtil.TEST_ANNOTATION_FQN)) return false;
     final TestData data = configuration.data;
-    data.PACKAGE_NAME = myPackage.getQualifiedName();
+    data.PACKAGE_NAME = aPackage.getQualifiedName();
     data.TEST_OBJECT = TestType.PACKAGE.getType();
-    data.setScope(setupPackageConfiguration(context, project, configuration, data.getScope()));
+    data.setScope(setupPackageConfiguration(context, configuration, data.getScope()));
     configuration.setGeneratedName();
-    JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location);
-    return settings;
+    sourceElement.set(aPackage);
+    return true;
   }
 
-  public PsiElement getSourceElement() {
-    return myPackage;
-  }
-
-  public int compareTo(final Object o) {
-    return PREFERED;
-  }
 }
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
index 0866157..cc6d307 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
@@ -33,6 +33,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
 import com.theoryinpractice.testng.model.TestData;
 import com.theoryinpractice.testng.model.TestType;
@@ -45,27 +46,20 @@
 
 public class TestNGPatternConfigurationProducer extends TestNGConfigurationProducer{
 
-  private PsiElement[] myElements;
-  
-
-  public int compareTo(Object o) {
-    return PREFERED;
-  }
-
-  protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) {
-    final Project project = location.getProject();
+  @Override
+  protected boolean setupConfigurationFromContext(TestNGConfiguration configuration,
+                                                  ConfigurationContext context,
+                                                  Ref<PsiElement> sourceElement) {
     final LinkedHashSet<String> classes = new LinkedHashSet<String>();
-    myElements = collectPatternElements(context, classes);
-    if (classes.size() <= 1) return null;
-    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
-    final TestNGConfiguration configuration = (TestNGConfiguration)settings.getConfiguration();
+    PsiElement[] elements = collectPatternElements(context, classes);
+    if (classes.size() <= 1) return false;
     final TestData data = configuration.getPersistantData();
     data.setPatterns(classes);
     data.TEST_OBJECT = TestType.PATTERN.getType();
-    data.setScope(setupPackageConfiguration(context, project, configuration, data.getScope()));
+    data.setScope(setupPackageConfiguration(context, configuration, data.getScope()));
     configuration.setGeneratedName();
-    JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location);
-    return settings;
+    sourceElement.set(elements[0]);
+    return true;
   }
 
   static Set<PsiMember> collectTestMembers(PsiElement[] psiElements) {
@@ -115,13 +109,9 @@
     return null;
   }
 
-  public PsiElement getSourceElement() {
-    return myElements[0];
-  }
-
   @Override
-  protected Module findModule(ModuleBasedConfiguration configuration, Module contextModule) {
-    final Set<String> patterns = ((TestNGConfiguration)configuration).data.getPatterns();
+  protected Module findModule(TestNGConfiguration configuration, Module contextModule) {
+    final Set<String> patterns = configuration.data.getPatterns();
     return findModule(configuration, contextModule, patterns);
   }
 
@@ -135,20 +125,14 @@
   }
 
   @Override
-  protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location,
-                                                                 @NotNull List<RunnerAndConfigurationSettings> existingConfigurations,
-                                                                 ConfigurationContext context) {
+  public boolean isConfigurationFromContext(TestNGConfiguration testNGConfiguration, ConfigurationContext context) {
     final LinkedHashSet<String> classes = new LinkedHashSet<String>();
     collectPatternElements(context, classes);
-    for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) {
-      final TestNGConfiguration unitConfiguration = (TestNGConfiguration)existingConfiguration.getConfiguration();
-      final String type = unitConfiguration.getPersistantData().TEST_OBJECT;
-      if (Comparing.equal(type, TestType.PATTERN.getType())) {
-        if (Comparing.equal(classes, unitConfiguration.getPersistantData().getPatterns())) {
-          return existingConfiguration;
-        }
-      }
+    final String type = testNGConfiguration.getPersistantData().TEST_OBJECT;
+    if (Comparing.equal(type, TestType.PATTERN.getType()) &&
+        Comparing.equal(classes, testNGConfiguration.getPersistantData().getPatterns())) {
+      return true;
     }
-    return null;
+    return false;
   }
 }
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGSuiteConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGSuiteConfigurationProducer.java
index eeebd5a..707ebe3 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGSuiteConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGSuiteConfigurationProducer.java
@@ -26,6 +26,7 @@
 import com.intellij.execution.actions.ConfigurationContext;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -34,25 +35,19 @@
 import org.jetbrains.annotations.Nullable;
 
 public class TestNGSuiteConfigurationProducer extends TestNGConfigurationProducer{
-  private PsiElement myPsiElement = null;
 
 
-  public PsiElement getSourceElement() {
-    return myPsiElement;
-  }
-
-  @Nullable
-  protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) {
-    final PsiElement element = location.getPsiElement();
-    final PsiFile containingFile = element.getContainingFile();
-    if (containingFile == null) return null;
+  @Override
+  protected boolean setupConfigurationFromContext(TestNGConfiguration configuration,
+                                                  ConfigurationContext context,
+                                                  Ref<PsiElement> sourceElement) {
+    final PsiElement element = context.getPsiLocation();
+    final PsiFile containingFile = element != null ? element.getContainingFile() : null;
+    if (containingFile == null) return false;
     final VirtualFile virtualFile = containingFile.getVirtualFile();
-    if (virtualFile == null || !virtualFile.isValid()) return null;
-    if (!TestNGUtil.isTestngXML(virtualFile)) return null;
-    myPsiElement = containingFile;
-    final Project project = location.getProject();
-    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
-    final TestNGConfiguration configuration = (TestNGConfiguration)settings.getConfiguration();
+    if (virtualFile == null || !virtualFile.isValid()) return false;
+    if (!TestNGUtil.isTestngXML(virtualFile)) return false;
+    RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(context);
     setupConfigurationModule(context, configuration);
     final Module originalModule = configuration.getConfigurationModule().getModule();
     configuration.getPersistantData().SUITE_NAME = virtualFile.getPath();
@@ -60,11 +55,7 @@
     configuration.restoreOriginalModule(originalModule);
     configuration.setGeneratedName();
     settings.setName(configuration.getName());
-    JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location);
-    return settings;
-  }
-
-  public int compareTo(Object o) {
-    return PREFERED;
+    sourceElement.set(containingFile);
+    return true;
   }
 }
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
index 6ac43af..b83e65c 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
@@ -30,7 +30,6 @@
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vfs.*;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.javadoc.PsiDocTag;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -245,7 +244,7 @@
   private static boolean isBrokenPsiClass(PsiClass psiClass) {
     return (psiClass == null
         || psiClass instanceof PsiAnonymousClass
-        || psiClass instanceof JspClass);
+        || psiClass instanceof PsiSyntheticClass);
   }
 
   /**
diff --git a/plugins/testng/testSources/com/theoryinpractice/testng/configuration/ConfigurationsTest.java b/plugins/testng/testSources/com/theoryinpractice/testng/configuration/ConfigurationsTest.java
index e0a3054..fae7cec 100644
--- a/plugins/testng/testSources/com/theoryinpractice/testng/configuration/ConfigurationsTest.java
+++ b/plugins/testng/testSources/com/theoryinpractice/testng/configuration/ConfigurationsTest.java
@@ -20,13 +20,19 @@
  */
 package com.theoryinpractice.testng.configuration;
 
+import com.intellij.execution.Location;
 import com.intellij.execution.PsiLocation;
 import com.intellij.execution.RunManagerEx;
 import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.actions.ConfigurationFromContext;
 import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.application.PluginPathManager;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.module.ModuleUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.psi.JavaPsiFacade;
@@ -35,6 +41,7 @@
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.refactoring.RefactoringFactory;
 import com.intellij.refactoring.RenameRefactoring;
+import com.intellij.testFramework.MapDataContext;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.testFramework.fixtures.*;
 import com.intellij.util.PathUtil;
@@ -187,8 +194,16 @@
     final Project project = myProjectFixture.getProject();
     final PsiClass psiClass = findTestClass(project);
     final TestNGInClassConfigurationProducer producer = new TestNGInClassConfigurationProducer();
-    final RunnerAndConfigurationSettings config = producer.createConfigurationByElement(new PsiLocation<PsiClass>(project, psiClass), null);
-    assert config != null;
+    
+    final MapDataContext dataContext = new MapDataContext();
+    
+    dataContext.put(PlatformDataKeys.PROJECT, project);
+    dataContext.put(LangDataKeys.MODULE, ModuleUtil.findModuleForPsiElement(psiClass));
+    dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(psiClass));
+
+    final ConfigurationFromContext fromContext = producer.createConfigurationFromContext(ConfigurationContext.getFromContext(dataContext));
+    assert fromContext != null;
+    final RunnerAndConfigurationSettings config = fromContext.getConfigurationSettings();
     final RunConfiguration runConfiguration = config.getConfiguration();
     Assert.assertTrue(runConfiguration instanceof TestNGConfiguration);
 
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/psi/impl/XsltLanguage.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/psi/impl/XsltLanguage.java
index e71dd73..2667907 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/psi/impl/XsltLanguage.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/psi/impl/XsltLanguage.java
@@ -47,12 +47,12 @@
         LanguageFindUsages.INSTANCE.addExplicitExtension(this, new MyFindUsagesProvider());
         LanguageRefactoringSupport.INSTANCE.addExplicitExtension(this, new RefactoringSupportProvider() {
             @Override
-            public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) {
+            public boolean isInplaceRenameAvailable(@NotNull PsiElement element, PsiElement context) {
                 return element instanceof XsltVariable && element.getUseScope() instanceof LocalSearchScope;
             }
 
             @Override
-            public boolean isSafeDeleteAvailable(PsiElement element) {
+            public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
                 return element instanceof XPathVariable ||
                         element instanceof XsltTemplate;
             }
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XPathRefactoringSupportProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XPathRefactoringSupportProvider.java
index 677e7e1..9561b4a 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XPathRefactoringSupportProvider.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XPathRefactoringSupportProvider.java
@@ -49,7 +49,7 @@
   }
 
   @Override
-  public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) {
+  public boolean isInplaceRenameAvailable(@NotNull PsiElement element, PsiElement context) {
     return element instanceof XsltVariable && element.getUseScope() instanceof LocalSearchScope;
   }
 
@@ -69,7 +69,7 @@
   }
 
   @Override
-  public boolean isSafeDeleteAvailable(PsiElement element) {
+  public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
     return element instanceof XPathVariable ||
             element instanceof XsltTemplate;
   }
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
index 8e528e3..b45a088 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
@@ -68,7 +68,6 @@
     private static final String RELAXED_FILE_PATH_EXPR = "((?:file\\://?)?(?:/?\\p{Alpha}\\:)?(?:/\\p{Alpha}\\:)?[^:]+)";
 
     private static final String LOG_TAG = "(?:\\[[\\w ]+\\]\\:? +)?";
-    private static final VirtualFilePointerManager FILE_POINTER_MANAGER = VirtualFilePointerManager.getInstance();
 
     public enum OutputType {
         CONSOLE, STDOUT, @Deprecated FILE
@@ -173,8 +172,8 @@
     public final RunConfiguration clone() {
         final XsltRunConfiguration configuration = (XsltRunConfiguration)super.clone();
         configuration.myParameters = new ArrayList<Pair<String, String>>(myParameters);
-        if (myXsltFile != null) configuration.myXsltFile = FILE_POINTER_MANAGER.duplicate(myXsltFile, getProject(), null);
-        if (myXmlInputFile != null) configuration.myXmlInputFile = FILE_POINTER_MANAGER.duplicate(myXmlInputFile, getProject(), null);
+        if (myXsltFile != null) configuration.myXsltFile = VirtualFilePointerManager.getInstance().duplicate(myXsltFile, getProject(), null);
+        if (myXmlInputFile != null) configuration.myXmlInputFile = VirtualFilePointerManager.getInstance().duplicate(myXmlInputFile, getProject(), null);
         return configuration;
     }
 
@@ -229,14 +228,14 @@
         if (e != null) {
             final String url = e.getAttributeValue("url");
             if (url != null) {
-                myXsltFile = FILE_POINTER_MANAGER.create(url, getProject(), null);
+                myXsltFile = VirtualFilePointerManager.getInstance().create(url, getProject(), null);
             }
         }
         e = element.getChild("XmlFile");
         if (e != null) {
             final String url = e.getAttributeValue("url");
             if (url != null) {
-                myXmlInputFile = FILE_POINTER_MANAGER.create(url, getProject(), null);
+                myXmlInputFile = VirtualFilePointerManager.getInstance().create(url, getProject(), null);
             }
         }
 
@@ -349,12 +348,12 @@
         if (isEmpty(xsltFile)) {
             myXsltFile = null;
         } else {
-            myXsltFile = FILE_POINTER_MANAGER.create(VfsUtilCore.pathToUrl(xsltFile).replace(File.separatorChar, '/'), getProject(), null);
+            myXsltFile = VirtualFilePointerManager.getInstance().create(VfsUtilCore.pathToUrl(xsltFile).replace(File.separatorChar, '/'), getProject(), null);
         }
     }
 
     private void setXsltFile(VirtualFile virtualFile) {
-        myXsltFile = FILE_POINTER_MANAGER.create(virtualFile, getProject(), null);
+        myXsltFile = VirtualFilePointerManager.getInstance().create(virtualFile, getProject(), null);
     }
 
     @Nullable
@@ -400,12 +399,12 @@
         if (isEmpty(xmlInputFile)) {
             myXmlInputFile = null;
         } else {
-            myXmlInputFile = FILE_POINTER_MANAGER.create(VfsUtilCore.pathToUrl(xmlInputFile).replace(File.separatorChar, '/'), getProject(), null);
+            myXmlInputFile = VirtualFilePointerManager.getInstance().create(VfsUtilCore.pathToUrl(xmlInputFile).replace(File.separatorChar, '/'), getProject(), null);
         }
     }
 
     public void setXmlInputFile(VirtualFile xmlInputFile) {
-      myXmlInputFile = FILE_POINTER_MANAGER.create(xmlInputFile, getProject(), null);
+      myXmlInputFile = VirtualFilePointerManager.getInstance().create(xmlInputFile, getProject(), null);
     }
 
     public void setModule(Module module) {
diff --git a/resources/resources.iml b/resources/resources.iml
index cdb317e..1f8b3f2 100644
--- a/resources/resources.iml
+++ b/resources/resources.iml
@@ -12,7 +12,6 @@
     <orderEntry type="module" module-name="images" exported="" />
     <orderEntry type="module" module-name="community-resources" exported="" />
     <orderEntry type="module" module-name="util" />
-    <orderEntry type="module" module-name="remote-servers-impl" exported="" scope="RUNTIME" />
   </component>
   <component name="copyright">
     <Base>
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 27c7454..58281cf 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -222,6 +222,8 @@
     <extensionPoint name="java.compilerOutputIndex" area="IDEA_PROJECT"
                     interface="com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex"/>
     <extensionPoint name="vetoSPICondition" interface="com.intellij.openapi.util.Condition"/>
+
+    <extensionPoint name="manifest.parser.provider" interface="org.jetbrains.lang.manifest.header.HeaderParserProvider"/>
   </extensionPoints>
 
   <extensions defaultExtensionNs="com.intellij">
@@ -1376,6 +1378,9 @@
     <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.MethodBreakpointFactory"/>
     <debugger.jvmSmartStepIntoHandler implementation="com.intellij.debugger.actions.JavaSmartStepIntoHandler"/>
 
+    <applicationService serviceInterface="com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher"
+                        serviceImplementation="com.intellij.remoteServer.impl.runtime.deployment.debug.JavaDebuggerLauncherImpl"/>
+
     <dom.uiControlsProvider implementation="com.intellij.util.xml.impl.JavaDomApplicationComponent"/>
 
     <programRunner id="defaultDebugRunner" implementation="com.intellij.debugger.impl.GenericDebuggerRunner" order="last"/>
@@ -1427,10 +1432,28 @@
     <writingAccessProvider implementation="com.intellij.refactoring.util.ClsElementWritingAccessProvider"/>
 
     <welcomeScreen implementation="com.intellij.ide.ui.laf.darcula.DarculaWelcomeScreenProvider"/>
+
     <fileTypeFactory implementation="com.intellij.spi.SPIFileTypeFactory"/>
     <lang.parserDefinition language="SPI" implementationClass="com.intellij.spi.parsing.SPIParserDefinition"/>
     <lang.commenter language="SPI" implementationClass="com.intellij.spi.SPICommenter"/>
     <annotator language="SPI" implementationClass="com.intellij.spi.SPIAnnotator"/>
+
+    <fileTypeFactory implementation="org.jetbrains.lang.manifest.ManifestFileTypeFactory"/>
+    <lang.parserDefinition language="Manifest" implementationClass="org.jetbrains.lang.manifest.parser.ManifestParserDefinition"/>
+    <lang.syntaxHighlighterFactory key="Manifest" implementationClass="org.jetbrains.lang.manifest.highlighting.ManifestSyntaxHighlighterFactory"/>
+    <annotator language="Manifest" implementationClass="org.jetbrains.lang.manifest.highlighting.HeaderAnnotator"/>
+    <lang.elementManipulator forClass="org.jetbrains.lang.manifest.psi.HeaderValuePart"
+                             implementationClass="org.jetbrains.lang.manifest.psi.impl.HeaderValuePartManipulator"/>
+    <completion.contributor language="Manifest" implementationClass="org.jetbrains.lang.manifest.completion.ManifestCompletionContributor"/>
+    <manifest.parser.provider implementation="org.jetbrains.lang.manifest.header.impl.StandardManifestHeaderParsers"/>
+
+    <applicationService serviceImplementation="org.jetbrains.lang.manifest.header.HeaderParserRepository"/>
+
+    <localInspection language="Manifest" displayName="Missing Final New Line" groupName="Manifest"
+                     enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.lang.manifest.highlighting.MissingFinalNewlineInspection"/>
+    <localInspection language="Manifest" displayName="Unknown or Misspelled Header Name" groupName="Manifest"
+                     enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.lang.manifest.highlighting.MisspelledHeaderInspection"/>
+
     <gotoDeclarationHandler implementation="com.intellij.codeInsight.navigation.actions.GotoLambdaParameterHandler"/>
 
     <java.compilerOutputIndex implementation="com.intellij.compilerOutputIndex.impl.MethodsUsageIndex"/>
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index d0d63b1..c539ddb 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -78,6 +78,8 @@
 
     <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="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/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
index 8dc15ed..0d86645 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
@@ -3,6 +3,7 @@
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.psi.xml.XmlElement;
 import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ReflectionCache;
 import com.intellij.util.containers.ConcurrentFactoryMap;
 import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.NotNull;
@@ -60,4 +61,8 @@
     }
     return Arrays.asList(myType.getEnumConstants());
   }
+
+  public boolean isExhaustive() {
+    return !ReflectionCache.isAssignable(NonExhaustiveEnum.class, myType);
+  }
 }
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
index b457c9d..c36c2bf 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
@@ -24,6 +24,7 @@
 import com.intellij.util.ProcessingContext;
 import com.intellij.util.ReflectionCache;
 import com.intellij.util.xml.*;
+import com.intellij.xml.util.XmlAttributeValueReferenceProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -86,6 +87,13 @@
         }
       }
     }
+    if (references.length > 0) {
+      if (converter instanceof EnumConverter && !((EnumConverter)converter).isExhaustive()) {
+        // will be handled by core XML
+        return PsiReference.EMPTY_ARRAY;
+      }
+      context.put(XmlAttributeValueReferenceProvider.SUPPRESS, Boolean.TRUE);
+    }
     return references;
   }
 
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java b/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java
new file mode 100644
index 0000000..95b522e
--- /dev/null
+++ b/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java
@@ -0,0 +1,23 @@
+/*
+ * 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.util.xml;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 21.08.13
+ */
+public interface NonExhaustiveEnum {
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
index 00d6c1e..bf87f35 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
@@ -71,11 +71,14 @@
     }
 
     {
-      final CompletionVariant variant = new CompletionVariant(createAttributeValueCompletionFilter());
-      variant.includeScopeClass(XmlAttributeValue.class);
-      variant.addCompletion(getAttributeValueGetter(), TailType.NONE);
-      variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
-      registerVariant(variant);
+      XmlAttributeValueGetter getter = getAttributeValueGetter();
+      if (getter != null) {
+        final CompletionVariant variant = new CompletionVariant(createAttributeValueCompletionFilter());
+        variant.includeScopeClass(XmlAttributeValue.class);
+        variant.addCompletion(getter, TailType.NONE);
+        variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
+        registerVariant(variant);
+      }
     }
 
     final ElementFilter entityCompletionFilter = createXmlEntityCompletionFilter();
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
index 0fb6ef2..142e7df 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
@@ -12,7 +12,7 @@
  */
 public class DependentNSReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<DependentNSReference> {
   @Override
-  public void registerFixes(DependentNSReference ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull DependentNSReference ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new FetchExtResourceAction(ref.isForceFetchResultValid()));
     registrar.register(new ManuallySetupExtResourceAction());
     registrar.register(new IgnoreExtResourceAction());
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
index 6b8bebd..eb3d558 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
@@ -27,7 +27,7 @@
  */
 public class SchemaReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<SchemaReferencesProvider.TypeOrElementOrAttributeReference> {
   @Override
-  public void registerFixes(SchemaReferencesProvider.TypeOrElementOrAttributeReference ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull SchemaReferencesProvider.TypeOrElementOrAttributeReference ref, @NotNull QuickFixActionRegistrar registrar) {
     if (ref.getType() == SchemaReferencesProvider.TypeOrElementOrAttributeReference.ReferenceType.TypeReference) {
       registrar.register(
         new CreateXmlElementIntentionAction("xml.schema.create.complex.type.intention.name", SchemaReferencesProvider.COMPLEX_TYPE_TAG_NAME, ref)
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
index 1c63a97..13bae7b 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
@@ -27,7 +27,7 @@
  */
 public class URLReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<URLReference> {
   @Override
-  public void registerFixes(URLReference ref, QuickFixActionRegistrar registrar) {
+  public void registerFixes(@NotNull URLReference ref, @NotNull QuickFixActionRegistrar registrar) {
     registrar.register(new FetchExtResourceAction());
     registrar.register(new ManuallySetupExtResourceAction());
     registrar.register(new IgnoreExtResourceAction());
diff --git a/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java
new file mode 100644
index 0000000..33d7201
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java
@@ -0,0 +1,61 @@
+/*
+ * 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.util;
+
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import com.intellij.xml.impl.schema.XmlSchemaTagsProcessor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ *         Date: 15.08.13
+ */
+public class XmlAttributeValueReferenceProvider extends PsiReferenceProvider {
+
+  public final static Key<Boolean> SUPPRESS = Key.create("suppress attribute value references");
+
+  @NotNull
+  @Override
+  public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
+
+    if (XmlSchemaTagsProcessor.PROCESSING_FLAG.get() != null || context.get(SUPPRESS) != null) {
+      return PsiReference.EMPTY_ARRAY;
+    }
+    XmlAttributeValue value = (XmlAttributeValue)element;
+    String unquotedValue = value.getValue();
+    if (unquotedValue == null || XmlHighlightVisitor.skipValidation(value) || !XmlUtil.isSimpleXmlAttributeValue(unquotedValue, value)) {
+      return PsiReference.EMPTY_ARRAY;
+    }
+    PsiElement parent = value.getParent();
+    if (parent instanceof XmlAttribute) {
+      final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
+      if (descriptor instanceof BasicXmlAttributeDescriptor &&
+          (descriptor.isFixed() || descriptor.isEnumerated() || unquotedValue.equals(descriptor.getDefaultValue()))) { // todo case insensitive
+        return ((BasicXmlAttributeDescriptor)descriptor).getValueReferences(value);
+      }
+    }
+    return PsiReference.EMPTY_ARRAY;
+  }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
index 21d6abc..6fcd606 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
@@ -89,5 +89,6 @@
                                                        new XmlEncodingReferenceProvider());
 
     registrar.registerReferenceProvider(xmlAttributeValue(), new XmlPrefixReferenceProvider());
+    registrar.registerReferenceProvider(xmlAttributeValue(), new XmlAttributeValueReferenceProvider(), PsiReferenceRegistrar.LOWER_PRIORITY);
   }
 }
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 36760ce..db3d85e 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
@@ -17,14 +17,20 @@
 package org.intellij.plugins.relaxNG.model.descriptors;
 
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.DelimitedListProcessor;
+import com.intellij.psi.ElementManipulators;
 import com.intellij.psi.PsiElement;
 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;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.XmlAttributeValueReference;
 import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
 import gnu.trove.THashSet;
 import gnu.trove.TObjectHashingStrategy;
@@ -201,4 +207,24 @@
   private static String normalizeSpace(String value) {
     return value.replaceAll("\\s+", " ").trim();
   }
+
+  @Override
+  public PsiReference[] getValueReferences(final XmlAttributeValue value) {
+    String text = value.getValue();
+    if (text == null) return PsiReference.EMPTY_ARRAY;
+    final int offset = ElementManipulators.getValueTextRange(value).getStartOffset();
+    final List<PsiReference> list = new ArrayList<PsiReference>();
+    new DelimitedListProcessor("") {
+      @Override
+      protected boolean isDelimiter(char ch) {
+        return Character.isWhitespace(ch);
+      }
+
+      @Override
+      protected void processToken(int start, int end, boolean delimitersOnly) {
+        list.add(new XmlAttributeValueReference(value, TextRange.create(offset + start, offset + end), RngXmlAttributeDescriptor.this));
+      }
+    }.processText(text);
+    return list.toArray(new PsiReference[list.size()]);
+  }
 }
\ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/attribute-choice-3.xml b/xml/relaxng/testData/highlighting/attribute-choice-3.xml
index c095d96..312c85d 100644
--- a/xml/relaxng/testData/highlighting/attribute-choice-3.xml
+++ b/xml/relaxng/testData/highlighting/attribute-choice-3.xml
@@ -1,2 +1,2 @@
-<attribute-choice xmlns="urn:test:simple.rng" type=<error>"c"</error>>
+<attribute-choice xmlns="urn:test:simple.rng" type="<error descr="Wrong attribute value">c</error>">
 </attribute-choice>
\ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/fixed-attribute_2.xml b/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
index a7a4b23..cf6c47a 100644
--- a/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
+++ b/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
@@ -1,2 +1,2 @@
-<fixed-attribute xmlns="urn:test:simple.rng" x=<error>"2.0"</error>>
+<fixed-attribute xmlns="urn:test:simple.rng" x="<error descr="Attribute should have fixed value 1.0">2.0</error>">
 </fixed-attribute>
\ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/value-choice-2.xml b/xml/relaxng/testData/highlighting/value-choice-2.xml
index 8b026fe..fba9ef5 100644
--- a/xml/relaxng/testData/highlighting/value-choice-2.xml
+++ b/xml/relaxng/testData/highlighting/value-choice-2.xml
@@ -1,2 +1,2 @@
-<value-choice xmlns="urn:test:simple.rng" x=<error>"c"</error>>
+<value-choice xmlns="urn:test:simple.rng" x="<error descr="Wrong attribute value">c</error>">
 </value-choice>
\ No newline at end of file
diff --git a/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml b/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
index c9f2474..0ffab31 100644
--- a/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
+++ b/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
@@ -1,4 +1,4 @@
 <build number="1" xsi:noNamespaceSchemaLocation="HighlightWhenNoNsSchemaLocation.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <statusInfo status="SUCCESS"/>
-<statusInfo status=<error>"SUCCESS2"</error>/>
+<statusInfo status="<error descr="Wrong attribute value">SUCCESS2</error>"/>
 </build>
\ No newline at end of file
diff --git a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
index 2f90357..8ab43e2 100644
--- a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
+++ b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
@@ -20,8 +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)
-# 0 - attr name, 1 - expected default value
-attribute.should.have.fixed.value=Attribute {0} should have fixed value {1}
+attribute.should.have.fixed.value=Attribute should have fixed value {0}
 
 #quickfixes
 insert.required.attribute.quickfix.text=Insert Required Attribute {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 445a550..d6bbd3b 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
@@ -16,14 +16,16 @@
 package com.intellij.psi.impl.source.html.dtd;
 
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeValue;
 import com.intellij.psi.xml.XmlElement;
 import com.intellij.util.ArrayUtil;
 import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
 
 /**
  * @author Maxim.Mossienko
  */
-public class HtmlAttributeDescriptorImpl implements XmlAttributeDescriptor {
+public class HtmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor {
   private final XmlAttributeDescriptor delegate;
   private final boolean myCaseSensitive;
 
@@ -90,4 +92,9 @@
   public String toString() {
     return delegate.toString();
   }
+
+  @Override
+  protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) {
+    return super.getEnumeratedValueDeclaration(attributeValue, myCaseSensitive ? value : value.toLowerCase());
+  }
 }
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 1aa72c3..83cf70f 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
@@ -24,40 +24,18 @@
  */
 package com.intellij.xml.impl;
 
-import com.intellij.codeInsight.daemon.XmlErrorMessages;
+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.util.ArrayUtilRt;
+import com.intellij.xml.util.XmlAttributeValueReference;
 import com.intellij.xml.XmlAttributeDescriptor;
-import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.Nullable;
 
 public abstract class BasicXmlAttributeDescriptor implements XmlAttributeDescriptor {
   public String validateValue(XmlElement context, String value) {
-    if (isFixed()) {
-      String defaultValue = getDefaultValue();
-
-      if (defaultValue != null && !defaultValue.equals(value)) {
-        return XmlErrorMessages.message("attribute.should.have.fixed.value", getName(), defaultValue);
-      }
-    }
-
-    if (isEnumerated(context) && XmlUtil.isSimpleXmlAttributeValue(value, (XmlAttributeValue)context)) {
-      String[] values = getEnumeratedValues(context);
-      boolean valueWasFound = false;
-
-      for (String enumValue : values) {
-        if (enumValue.equals(value)) {
-          valueWasFound = true;
-          break;
-        }
-      }
-
-      if (!valueWasFound) {
-        return XmlErrorMessages.message("wrong.attribute.value");
-      }
-    }
-
     return null;
   }
 
@@ -78,4 +56,26 @@
   public String toString() {
     return getName();
   }
+
+  public PsiElement getValueDeclaration(XmlAttributeValue attributeValue, String value) {
+    String defaultValue = getDefaultValue();
+    if (Comparing.equal(defaultValue, value)) {
+      return getDefaultValueDeclaration();
+    }
+    return isFixed() ? null : getEnumeratedValueDeclaration(attributeValue, value);
+  }
+
+  protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) {
+    String[] values = getEnumeratedValues();
+    if (values == null || values.length == 0) return getDeclaration();
+    return ArrayUtilRt.find(values, value) != -1 ? getDeclaration() : null;
+  }
+
+  protected PsiElement getDefaultValueDeclaration() {
+    return getDeclaration();
+  }
+
+  public PsiReference[] getValueReferences(XmlAttributeValue value) {
+    return new PsiReference[] { new XmlAttributeValueReference(value, this)};
+  }
 }
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
index 195449b..2248f00 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
@@ -15,22 +15,19 @@
  */
 package com.intellij.xml.impl.schema;
 
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.meta.PsiWritableMetaData;
-import com.intellij.psi.xml.XmlElement;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.*;
 import com.intellij.xml.XmlElementDescriptor;
 import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
 import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.HashSet;
+import java.util.List;
 
 /**
  * @author Mike
@@ -38,6 +35,8 @@
 public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor implements PsiWritableMetaData {
   private XmlTag myTag;
   String myUse;
+  private boolean myExhaustiveEnum;
+
   @NonNls
   public static final String REQUIRED_ATTR_VALUE = "required";
   @NonNls
@@ -115,18 +114,7 @@
   }
 
   public boolean isEnumerated(@Nullable XmlElement context) {
-    final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
-      myTag,
-      context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
-    );
-
-    if (elementDescriptor != null &&
-        elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
-      final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
-      return data != null && data.exaustive;
-    }
-
-    return false;
+    return processEnumeration(context, PairProcessor.TRUE);
   }
 
   public boolean isEnumerated() {
@@ -138,19 +126,27 @@
   }
 
   public String[] getEnumeratedValues(XmlElement context) {
-    final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
-      myTag,
-      context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
-    );
+    final List<String> list = new SmartList<String>();
+    processEnumeration(context, new PairProcessor<PsiElement, String>() {
+      @Override
+      public boolean process(PsiElement element, String s) {
+        list.add(s);
+        return true;
+      }
+    });
+    String defaultValue = getDefaultValue();
+    if (defaultValue != null) {
+      list.add(defaultValue);
+    }
+    return ArrayUtil.toStringArray(list);
+  }
+
+  private boolean processEnumeration(XmlElement context, PairProcessor<PsiElement, String> processor) {
+    XmlTag contextTag = context != null ? PsiTreeUtil.getContextOfType(context, XmlTag.class, true) : null;
+    final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(myTag, contextTag);
 
     if (elementDescriptor!=null && elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
-      final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
-      final String s = getDefaultValue();
-
-      if (s != null && s.length() > 0 && data == null) {
-        return new String[] {s};
-      }
-      return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+      return processEnumerationImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration(), processor);
     }
 
     final String namespacePrefix = myTag.getNamespacePrefix();
@@ -159,35 +155,42 @@
     );
 
     if (type != null) {
-      final EnumerationData data = getEnumeratedValuesImpl(type);
-      return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+      return processEnumerationImpl(type, processor);
     }
 
-    return ArrayUtil.EMPTY_STRING_ARRAY;
+    return false;
   }
 
-  static class EnumerationData {
-    final String[] enumeratedValues;
-    final boolean exaustive;
-
-    EnumerationData(@NotNull String[] _values, boolean _exaustive) {
-      enumeratedValues = _values;
-      exaustive = _exaustive;
-    }
-  }
-
-  private static EnumerationData getEnumeratedValuesImpl(final XmlTag declaration) {
+  private boolean processEnumerationImpl(final XmlTag declaration, final PairProcessor<PsiElement, String> pairProcessor) {
     if ("boolean".equals(declaration.getAttributeValue("name"))) {
-      return new EnumerationData(new String[] {"true", "false"}, true);
+      XmlAttributeValue valueElement = declaration.getAttribute("name").getValueElement();
+      pairProcessor.process(valueElement, "true");
+      pairProcessor.process(valueElement, "false");
+      myExhaustiveEnum = true;
+      return true;
     }
 
-    final HashSet<String> variants = new HashSet<String>();
-    final boolean exaustive = XmlUtil.collectEnumerationValues(declaration, variants);
-
-    if (variants.size() > 0) {
-      return new EnumerationData(ArrayUtil.toStringArray(variants), exaustive);
+    else {
+      final Ref<Boolean> found = new Ref<Boolean>(Boolean.FALSE);
+      myExhaustiveEnum = XmlUtil.processEnumerationValues(declaration, new Processor<XmlTag>() {
+        @Override
+        public boolean process(XmlTag tag) {
+          found.set(Boolean.TRUE);
+          XmlAttribute name = tag.getAttribute("value");
+          return name == null || pairProcessor.process(name.getValueElement(), name.getValue());
+        }
+      });
+      return found.get();
     }
-    return null;
+  }
+
+  @Override
+  public PsiElement getValueDeclaration(XmlAttributeValue attributeValue, String value) {
+    PsiElement declaration = super.getValueDeclaration(attributeValue, value);
+    if (declaration == null && !myExhaustiveEnum) {
+      return getDeclaration();
+    }
+    return declaration;
   }
 
   public String getName(PsiElement context) {
@@ -243,4 +246,20 @@
   public void setName(String name) throws IncorrectOperationException {
     NamedObjectDescriptor.setName(myTag, name);
   }
+
+  @Override
+  protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, final String value) {
+    final Ref<PsiElement> result = new Ref<PsiElement>();
+    processEnumeration(myTag, new PairProcessor<PsiElement, String>() {
+      @Override
+      public boolean process(PsiElement element, String s) {
+        if (value.equals(s)) {
+          result.set(element);
+          return false;
+        }
+        return true;
+      }
+    });
+    return result.get();
+  }
 }
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
index 8b4c20a..4e5e37e 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
@@ -757,7 +757,7 @@
     return true;
   }
 
-  protected static boolean equalsToSchemaName(XmlTag tag, @NonNls String schemaName) {
+  protected static boolean equalsToSchemaName(@NotNull XmlTag tag, @NonNls String schemaName) {
     return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag);
   }
 
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
index b884ced..98cb0b4 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
@@ -31,6 +31,8 @@
  */
 public abstract class XmlSchemaTagsProcessor {
 
+  public final static ThreadLocal<Boolean> PROCESSING_FLAG = new ThreadLocal<Boolean>();
+
   private final Set<XmlTag> myVisited = new HashSet<XmlTag>();
   protected final XmlNSDescriptorImpl myNsDescriptor;
   private final String[] myTagsToIgnore;
@@ -41,10 +43,16 @@
   }
 
   public final void startProcessing(XmlTag tag) {
-    processTag(tag, null);
+    try {
+      PROCESSING_FLAG.set(Boolean.TRUE);
+      processTag(tag, null);
+    }
+    finally {
+      PROCESSING_FLAG.set(null);
+    }
   }
 
-  public void processTag(XmlTag tag, @Nullable XmlTag context) {
+  private void processTag(XmlTag tag, @Nullable XmlTag context) {
 
     if (myVisited.contains(tag)) return;
     myVisited.add(tag);
@@ -80,6 +88,7 @@
       if (ref == null) return;
       XmlTag group;
       XmlTag parentTag = tag.getParentTag();
+      assert parentTag != null;
       if (XmlNSDescriptorImpl.equalsToSchemaName(parentTag, "attributeGroup") &&
         ref.equals(parentTag.getAttributeValue("name"))) {
         group = resolveTagReference(tag.getAttribute("ref"));
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java
new file mode 100644
index 0000000..75a604b
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java
@@ -0,0 +1,75 @@
+/*
+ * 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.util;
+
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author Dmitry Avdeev
+*         Date: 16.08.13
+*/
+public class XmlAttributeValueReference extends PsiReferenceBase<XmlAttributeValue> implements EmptyResolveMessageProvider {
+  private final XmlAttributeDescriptor myDescriptor;
+
+  public XmlAttributeValueReference(XmlAttributeValue value, XmlAttributeDescriptor descriptor) {
+    super(value);
+    myDescriptor = descriptor;
+  }
+
+  public XmlAttributeValueReference(XmlAttributeValue element,
+                                    TextRange range,
+                                    XmlAttributeDescriptor descriptor) {
+    super(element, range);
+    myDescriptor = descriptor;
+  }
+
+  @Nullable
+  @Override
+  public PsiElement resolve() {
+    return ((BasicXmlAttributeDescriptor)myDescriptor).getValueDeclaration(getElement(), getValue());
+  }
+
+  @NotNull
+  @Override
+  public Object[] getVariants() {
+    if (myDescriptor.isFixed()) {
+      String defaultValue = myDescriptor.getDefaultValue();
+      return defaultValue == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[] {defaultValue};
+    }
+    else {
+      String[] values = myDescriptor.getEnumeratedValues();
+      return values == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : values;
+    }
+  }
+
+  @NotNull
+  @Override
+  public String getUnresolvedMessagePattern() {
+    return myDescriptor.isFixed()
+           ? XmlErrorMessages.message("attribute.should.have.fixed.value", myDescriptor.getDefaultValue())
+           : XmlErrorMessages.message("wrong.attribute.value");
+  }
+}
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 ee38a7e..e8bb8f4 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,26 +933,33 @@
     });
   }
 
+  /**
+   * @return true if enumeration is exhaustive
+   */
   public static boolean processEnumerationValues(final XmlTag element, final Processor<XmlTag> tagProcessor) {
-    boolean exaustiveEnum = true;
+    boolean exhaustiveEnum = true;
 
     for (final XmlTag tag : element.getSubTags()) {
       @NonNls final String localName = tag.getLocalName();
 
       if (localName.equals(ENUMERATION_TAG_NAME)) {
         final String attributeValue = tag.getAttributeValue(VALUE_ATTR_NAME);
-        if (attributeValue != null) tagProcessor.process(tag);
+        if (attributeValue != null) {
+          if (!tagProcessor.process(tag)) {
+            return exhaustiveEnum;
+          }
+        }
       }
       else if (localName.equals("union")) {
-        exaustiveEnum = false;
+        exhaustiveEnum = false;
         processEnumerationValues(tag, tagProcessor);
       }
       else if (!localName.equals("annotation")) {
         // don't go into annotation
-        exaustiveEnum &= processEnumerationValues(tag, tagProcessor);
+        exhaustiveEnum &= processEnumerationValues(tag, tagProcessor);
       }
     }
-    return exaustiveEnum;
+    return exhaustiveEnum;
   }
 
   /**
@@ -1063,12 +1070,15 @@
     return new Pair<XmlTagChild, XmlTagChild>(first, last);
   }
 
-  public static boolean isSimpleXmlAttributeValue(final String unquotedValue, final XmlAttributeValue context) {
+  public static boolean isSimpleXmlAttributeValue(@NotNull final String unquotedValue, final XmlAttributeValue context) {
     for (int i = 0; i < unquotedValue.length(); ++i) {
       final char ch = unquotedValue.charAt(i);
       if (!Character.isJavaIdentifierPart(ch) && ch != ':' && ch != '-') {
         final XmlFile file = PsiTreeUtil.getParentOfType(context, XmlFile.class);
-        return file != null && !tagFromTemplateFramework(file.getRootTag());
+        if (file != null) {
+          XmlTag tag = file.getRootTag();
+          return tag != null && !tagFromTemplateFramework(tag);
+        }
       }
     }
     return true;