Snapshot af729d01433bb5bbd6ca93c0fdf9778b36d624ce from master branch of git://git.jetbrains.org/idea/community.git

Change-Id: I214dd066d0d27444a26166c0eae1a5aaf3705d49
diff --git a/java/java-impl/java-impl.iml b/java/java-impl/java-impl.iml
index b7b5d03..0e65b92 100644
--- a/java/java-impl/java-impl.iml
+++ b/java/java-impl/java-impl.iml
@@ -5,6 +5,19 @@
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
     </content>
+    <content url="file://$MODULE_DIR$/../../plugins/InspectionGadgets">
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/InspectionGadgets/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/InspectionGadgets/testsrc" isTestSource="true" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../plugins/IntentionPowerPak">
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/IntentionPowerPak/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/IntentionPowerPak/testSrc" isTestSource="true" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../plugins/generate-tostring">
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/generate-tostring/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/generate-tostring/testSrc" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/../../plugins/generate-tostring/resources" isTestSource="false" />
+    </content>
     <orderEntry type="module" module-name="boot" />
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
@@ -34,6 +47,11 @@
     <orderEntry type="module" module-name="jps-model-impl" />
     <orderEntry type="module" module-name="java-analysis-impl" exported="" />
     <orderEntry type="module" module-name="external-system-api" />
+    <orderEntry type="library" name="asm4" level="project" />
+    <orderEntry type="library" name="Guava" level="project" />
+    <orderEntry type="library" name="Xerces" level="project" />
+    <orderEntry type="library" name="Velocity" level="project" />
+    <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
   </component>
   <component name="copyright">
     <Base>
diff --git a/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java b/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
index d82d51f..e7d0082 100644
--- a/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
+++ b/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
@@ -18,7 +18,6 @@
 import com.intellij.ide.highlighter.JavaHighlightingColors;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.application.ApplicationBundle;
-import com.intellij.openapi.editor.SyntaxHighlighterColors;
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.psi.codeStyle.PackageEntry;
 import com.intellij.psi.codeStyle.PackageEntryTable;
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
index 6a3d3f6..89b606e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
@@ -940,7 +940,7 @@
       }
 
       ParameterTypeInferencePolicy policy = forCompletion ? CompletionParameterTypeInferencePolicy.INSTANCE : DefaultParameterTypeInferencePolicy.INSTANCE;
-      
+
       Set<ExpectedTypeInfo> array = new LinkedHashSet<ExpectedTypeInfo>();
       for (CandidateInfo candidateInfo : methodCandidates) {
         PsiMethod method = (PsiMethod)candidateInfo.getElement();
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
index ac8297d..1bdedaf 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
@@ -140,9 +140,10 @@
     }
   };
 
-  public static void processJavaClasses(final CompletionParameters parameters,
-                                        final PrefixMatcher prefixMatcher, final boolean filterByScope,
-                                        final Consumer<PsiClass> consumer) {
+  public static void processJavaClasses(@NotNull final CompletionParameters parameters,
+                                        @NotNull final PrefixMatcher prefixMatcher,
+                                        final boolean filterByScope,
+                                        @NotNull final Consumer<PsiClass> consumer) {
     final PsiElement context = parameters.getPosition();
     final Project project = context.getProject();
     final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project);
@@ -167,10 +168,10 @@
     processJavaClasses(prefixMatcher, project, scope, processor);
   }
 
-  public static void processJavaClasses(final PrefixMatcher prefixMatcher,
-                                        Project project,
-                                        GlobalSearchScope scope,
-                                        Processor<PsiClass> processor) {
+  public static void processJavaClasses(@NotNull final PrefixMatcher prefixMatcher,
+                                        @NotNull Project project,
+                                        @NotNull GlobalSearchScope scope,
+                                        @NotNull Processor<PsiClass> processor) {
     AllClassesSearch.search(scope, project, new Condition<String>() {
       @Override
       public boolean value(String s) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
index 0440a33..bc00fa2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
@@ -16,13 +16,13 @@
 package com.intellij.codeInsight.completion;
 
 import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
-import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix;
 import com.intellij.codeInsight.lookup.Lookup;
 import com.intellij.codeInsight.lookup.LookupActionProvider;
 import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupElementAction;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Consumer;
 import org.jetbrains.annotations.Nullable;
 
@@ -39,12 +39,12 @@
     } else if (o instanceof PsiMethod) {
       final PsiMethod method = (PsiMethod)o;
       if (method.hasModifierProperty(PsiModifier.STATIC)) {
-        addExcludes(consumer, method, StaticImportMethodFix.getMemberQualifiedName(method));
+        addExcludes(consumer, method, PsiUtil.getMemberQualifiedName(method));
       }
     } else if (o instanceof PsiField) {
       final PsiField field = (PsiField)o;
       if (field.hasModifierProperty(PsiModifier.STATIC)) {
-        addExcludes(consumer, field, StaticImportMethodFix.getMemberQualifiedName(field));
+        addExcludes(consumer, field, PsiUtil.getMemberQualifiedName(field));
       }
     }
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
index eb19c57..f7140fe 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
@@ -17,7 +17,7 @@
 
 import com.intellij.codeInsight.lookup.*;
 import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
+import com.intellij.diagnostic.AttachmentFactory;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.util.ClassConditionKey;
@@ -120,7 +120,7 @@
                                          "atTail=" + atTail + "\n" +
                                          "offset=" + context.getTailOffset() + "\n" +
                                          DebugUtil.currentStackTrace(),
-                                         new Attachment(context.getDocument())));
+                                         AttachmentFactory.createAttachment(context.getDocument())));
 
     }
     document.replaceString(context.getTailOffset() - 1, context.getTailOffset(), ".");
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java
index a250010..71360e7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java
@@ -30,9 +30,11 @@
 import com.intellij.codeInsight.lookup.impl.LookupImpl;
 import com.intellij.lang.java.JavaLanguage;
 import com.intellij.patterns.PsiJavaPatterns;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
 
 public class JavaCharFilter extends CharFilter {
 
@@ -67,9 +69,16 @@
     if (c == ':') {
       PsiFile file = lookup.getPsiFile();
       PsiDocumentManager.getInstance(file.getProject()).commitDocument(lookup.getEditor().getDocument());
-      PsiElement element = lookup.getPsiElement();
-      if (PsiTreeUtil.getParentOfType(element, PsiSwitchLabelStatement.class) != null ||
-          PsiTreeUtil.getParentOfType(element, PsiConditionalExpression.class) != null) {
+      PsiElement leaf = file.findElementAt(lookup.getEditor().getCaretModel().getOffset() - 1);
+      if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_8)) {
+        PsiStatement statement = PsiTreeUtil.getParentOfType(leaf, PsiStatement.class);
+        if (statement == null ||
+            statement.getTextRange().getStartOffset() != leaf.getTextRange().getStartOffset()) { // not typing a statement label
+          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+        }
+      }
+      if (PsiTreeUtil.getParentOfType(leaf, PsiSwitchLabelStatement.class) != null ||
+          PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class) != null) {
         return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
       }
       return Result.HIDE_LOOKUP;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
index d1166c7..df113a5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
@@ -30,6 +30,7 @@
 import com.intellij.psi.filters.ClassFilter;
 import com.intellij.psi.filters.ElementFilter;
 import com.intellij.psi.filters.TrueFilter;
+import com.intellij.psi.filters.classes.AnnotationTypeFilter;
 import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
@@ -78,14 +79,16 @@
     return false;
   }
 
-  public static void addAllClasses(CompletionParameters parameters,
+  public static void addAllClasses(@NotNull CompletionParameters parameters,
                                    final boolean filterByScope,
                                    @NotNull final PrefixMatcher matcher,
                                    @NotNull final Consumer<LookupElement> consumer) {
     final PsiElement insertedElement = parameters.getPosition();
 
     final ElementFilter filter =
-      IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : TrueFilter.INSTANCE;
+      IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) :
+      JavaCompletionContributor.ANNOTATION_NAME.accepts(insertedElement) ? new AnnotationTypeFilter() :
+      TrueFilter.INSTANCE;
 
     final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier;
     final boolean afterNew = AFTER_NEW.accepts(insertedElement);
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
index 083649a..3ce6050 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
@@ -39,6 +39,7 @@
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.classes.AnnotationTypeFilter;
 import com.intellij.psi.filters.classes.AssignableFromContextFilter;
 import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
 import com.intellij.psi.filters.element.ModifierFilter;
@@ -75,6 +76,9 @@
     ourCompletionData.put(LanguageLevel.JDK_1_3, new JavaCompletionData());
   }
 
+  public static final ElementPattern<PsiElement> ANNOTATION_NAME = psiElement().
+    withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).afterLeaf("@");
+
   private static JavaCompletionData getCompletionData(LanguageLevel level) {
     final Set<Map.Entry<LanguageLevel, JavaCompletionData>> entries = ourCompletionData.entrySet();
     for (Map.Entry<LanguageLevel, JavaCompletionData> entry : entries) {
@@ -113,6 +117,10 @@
       return new AndFilter(ElementClassFilter.CLASS, new NotFilter(new AssignableFromContextFilter()));
     }
 
+    if (ANNOTATION_NAME.accepts(position)) {
+      return new AnnotationTypeFilter();
+    }
+
     if (JavaCompletionData.DECLARATION_START.accepts(position) ||
         JavaCompletionData.isInsideParameterList(position) ||
         psiElement().inside(psiElement(PsiJavaCodeReferenceElement.class).withParent(psiAnnotation())).accepts(position)) {
@@ -223,10 +231,10 @@
       result.addElement(LookupElementBuilder.create("*"));
     }
 
-    Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);
-
     addKeywords(parameters, result);
 
+    Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);
+
     if (psiElement().inside(PsiLiteralExpression.class).accepts(position)) {
       PsiReference reference = position.getContainingFile().findReferenceAt(parameters.getOffset());
       if (reference == null || reference.isSoft()) {
@@ -234,7 +242,7 @@
       }
     }
 
-    JavaOverrideCompletionContributor.fillCompletionVariants(parameters, result);
+    JavaGenerateMemberCompletionContributor.fillCompletionVariants(parameters, result);
 
     addAllClasses(parameters, result, inheritors);
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
index 1de9f59..f9405ad 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
@@ -68,7 +68,7 @@
     CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher());
     if (!smart && afterNew) {
       sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes));
-    } else {
+    } else if (PsiTreeUtil.getParentOfType(position, PsiReferenceList.class) == null) {
       sorter = ((CompletionSorterImpl)sorter).withClassifier("liftShorterClasses", true, new LiftShorterClasses(position));
     }
     if (smart) {
@@ -124,7 +124,7 @@
       public Comparable weigh(@NotNull LookupElement element) {
         final Object o = element.getObject();
         if (o instanceof PsiKeyword) return -3;
-        if (!(o instanceof PsiMember) || element.getUserData(JavaOverrideCompletionContributor.OVERRIDE_ELEMENT) != null) {
+        if (!(o instanceof PsiMember) || element.getUserData(JavaGenerateMemberCompletionContributor.GENERATE_ELEMENT) != null) {
           return 0;
         }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
index 163b2c6..6dc5928 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
@@ -20,7 +20,6 @@
 import com.intellij.codeInsight.completion.scope.CompletionElement;
 import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
 import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
-import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix;
 import com.intellij.codeInsight.guess.GuessManager;
 import com.intellij.codeInsight.lookup.*;
 import com.intellij.lang.StdLanguages;
@@ -125,7 +124,7 @@
   }
 
   public static boolean isInExcludedPackage(@NotNull final PsiMember member, boolean allowInstanceInnerClasses) {
-    final String name = StaticImportMethodFix.getMemberQualifiedName(member);
+    final String name = PsiUtil.getMemberQualifiedName(member);
     if (name == null) return false;
 
     if (!member.hasModifierProperty(PsiModifier.STATIC)) {
@@ -362,6 +361,7 @@
       PsiElement ctx = createContextWithXxxVariable(element, composite);
       javaReference = (PsiReferenceExpression) JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText("xxx.xxx", ctx);
       qualifierType = runtimeQualifier;
+      processor.setQualifierType(qualifierType);
     }
 
     javaReference.processVariants(processor);
@@ -620,6 +620,9 @@
     if (element instanceof PsiJavaCodeReferenceElement) {
       return mayHaveSideEffects(((PsiJavaCodeReferenceElement)element).getQualifier());
     }
+    if (element instanceof PsiParenthesizedExpression) {
+      return mayHaveSideEffects(((PsiParenthesizedExpression)element).getExpression());
+    }
     return true;
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
index 9e18f7b..2259d2b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
@@ -18,16 +18,15 @@
 import com.intellij.codeInsight.TailType;
 import com.intellij.codeInsight.completion.scope.CompletionElement;
 import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
+import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner;
 import com.intellij.codeInsight.lookup.*;
 import com.intellij.codeInspection.InspectionProfile;
 import com.intellij.codeInspection.SuppressionUtil;
 import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorModificationUtil;
-import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.*;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.patterns.PsiJavaPatterns;
@@ -38,20 +37,20 @@
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.filters.TrueFilter;
 import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
+import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
 import com.intellij.psi.javadoc.*;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ProcessingContext;
-import com.intellij.util.Processor;
-import com.intellij.util.SystemProperties;
+import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.text.CharArrayUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import java.util.StringTokenizer;
 
 /**
@@ -113,13 +112,80 @@
     });
   }
 
+  private static PsiParameter getDocTagParam(PsiElement tag) {
+    if (tag instanceof PsiDocTag && "param".equals(((PsiDocTag)tag).getName())) {
+      PsiDocTagValue value = ((PsiDocTag)tag).getValueElement();
+      if (value instanceof PsiDocParamRef) {
+        final PsiReference psiReference = value.getReference();
+        PsiElement target = psiReference != null ? psiReference.resolve() : null;
+        if (target instanceof PsiParameter) {
+          return (PsiParameter)target;
+        }
+      }
+    }
+    return null;
+  }
+
   @Override
   public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
-    if (PsiJavaPatterns.psiElement(JavaDocTokenType.DOC_COMMENT_DATA).accepts(parameters.getPosition())) return;
+
+    PsiElement position = parameters.getPosition();
+    if (PsiJavaPatterns.psiElement(JavaDocTokenType.DOC_COMMENT_DATA).accepts(position)) {
+      final PsiParameter param = getDocTagParam(position.getParent());
+      if (param != null) {
+        suggestSimilarParameterDescriptions(result, position, param);
+      }
+
+      return;
+    }
 
     super.fillCompletionVariants(parameters, result);
   }
 
+  private static void suggestSimilarParameterDescriptions(CompletionResultSet result, PsiElement position, final PsiParameter param) {
+    final Set<String> descriptions = ContainerUtil.newHashSet();
+    position.getContainingFile().accept(new PsiRecursiveElementWalkingVisitor() {
+      @Override
+      public void visitElement(PsiElement element) {
+        PsiParameter param1 = getDocTagParam(element);
+        if (param1 != null && param1 != param &&
+            Comparing.equal(param1.getName(), param.getName()) && Comparing.equal(param1.getType(), param.getType())) {
+          String text = "";
+          for (PsiElement psiElement : ((PsiDocTag)element).getDataElements()) {
+            if (psiElement != ((PsiDocTag)element).getValueElement()) {
+              text += psiElement.getText();
+            }
+          }
+          text = text.trim();
+          if (text.contains(" ")) {
+            descriptions.add(text);
+          }
+        }
+
+        super.visitElement(element);
+      }
+    });
+    for (String description : descriptions) {
+      result.addElement(LookupElementBuilder.create(description).withInsertHandler(new InsertHandler<LookupElement>() {
+        @Override
+        public void handleInsert(InsertionContext context, LookupElement item) {
+          if (context.getCompletionChar() != Lookup.REPLACE_SELECT_CHAR) return;
+          
+          context.commitDocument();
+          PsiDocTag docTag = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiDocTag.class, false);
+          if (docTag != null) {
+            Document document = context.getDocument();
+            int tagEnd = DocTagSelectioner.getDocTagRange(docTag, document.getCharsSequence(), 0).getEndOffset();
+            int tail = context.getTailOffset();
+            if (tail < tagEnd) {
+              document.deleteString(tail, tagEnd);
+            }
+          }
+        }
+      }));
+    }
+  }
+
   private static class TagChooser extends CompletionProvider<CompletionParameters> {
 
     @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
new file mode 100644
index 0000000..ee7a96a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
+import com.intellij.codeInsight.generation.OverrideImplementUtil;
+import com.intellij.codeInsight.generation.PsiGenerationInfo;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.*;
+import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
+import com.intellij.ui.RowIcon;
+import com.intellij.util.VisibilityUtil;
+import com.intellij.util.containers.ContainerUtil;
+
+import javax.swing.*;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+
+/**
+ * @author peter
+ */
+public class JavaGenerateMemberCompletionContributor {
+  static final Key<Boolean> GENERATE_ELEMENT = Key.create("GENERATE_ELEMENT");
+
+  public static void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
+    if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) {
+      return;
+    }
+
+    PsiElement position = parameters.getPosition();
+    if (psiElement(PsiIdentifier.class).withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class).
+      andNot(JavaCompletionData.AFTER_DOT).
+      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);
+      }
+    }
+
+  }
+
+  private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent) {
+    List<PsiMethod> prototypes = ContainerUtil.newArrayList();
+    for (PsiField field : parent.getFields()) {
+      if (!(field instanceof PsiEnumConstant)) {
+        prototypes.add(GenerateMembersUtil.generateGetterPrototype(field));
+        prototypes.add(GenerateMembersUtil.generateSetterPrototype(field));
+      }
+    }
+    for (final PsiMethod prototype : prototypes) {
+      if (parent.findMethodBySignature(prototype, false) == null) {
+        Icon icon = prototype.getIcon(Iconable.ICON_FLAG_VISIBILITY);
+        result.addElement(createGenerateMethodElement(prototype, PsiSubstitutor.EMPTY, icon, "", new InsertHandler<LookupElement>() {
+          @Override
+          public void handleInsert(InsertionContext context, LookupElement item) {
+            removeLookupString(context);
+
+            insertGenerationInfos(context, Arrays.asList(new PsiGenerationInfo<PsiMethod>(prototype)));
+          }
+        }));
+      }
+    }
+  }
+
+  private static void removeLookupString(InsertionContext context) {
+    context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
+    context.commitDocument();
+  }
+
+  private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
+    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()));
+      }
+    }
+  }
+
+  private static LookupElementBuilder createOverridingLookupElement(final PsiClass parent,
+                                                                    boolean implemented,
+                                                                    final PsiMethod baseMethod,
+                                                                    PsiClass baseClass, PsiSubstitutor substitutor) {
+
+    RowIcon icon = new RowIcon(2);
+    icon.setIcon(baseMethod.getIcon(0), 0);
+    icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
+
+    return createGenerateMethodElement(baseMethod, substitutor, icon, baseClass.getName(), new InsertHandler<LookupElement>() {
+      @Override
+      public void handleInsert(InsertionContext context, LookupElement item) {
+        removeLookupString(context);
+
+        List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
+        insertGenerationInfos(context, OverrideImplementUtil.convert2GenerationInfos(prototypes));
+      }
+    });
+  }
+
+  private static void insertGenerationInfos(InsertionContext context, List<PsiGenerationInfo<PsiMethod>> infos) {
+    List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil
+      .insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
+    if (!newInfos.isEmpty()) {
+      newInfos.get(0).positionCaret(context.getEditor(), true);
+    }
+  }
+
+  private static LookupElementBuilder createGenerateMethodElement(PsiMethod prototype,
+                                                                  PsiSubstitutor substitutor,
+                                                                  Icon icon,
+                                                                  String typeText, InsertHandler<LookupElement> insertHandler) {
+    String methodName = prototype.getName();
+
+    String visibility = VisibilityUtil.getVisibilityModifier(prototype.getModifierList());
+    String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
+
+    PsiType type = substitutor.substitute(prototype.getReturnType());
+    String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
+
+    String parameters = PsiFormatUtil.formatMethod(prototype, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
+
+    LookupElementBuilder element = LookupElementBuilder.create(prototype, signature).withLookupString(methodName).
+      withLookupString(signature).withInsertHandler(insertHandler).
+      appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(typeText).withIcon(icon);
+    element.putUserData(GENERATE_ELEMENT, true);
+    return element;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java
index b2896f3..d995a9e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java
@@ -17,6 +17,7 @@
 
 import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
 import com.intellij.codeInsight.lookup.*;
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
 import com.intellij.featureStatistics.FeatureUsageTracker;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
@@ -66,6 +67,10 @@
       return;
     }
 
+    if (parameters.getInvocationCount() == 0 && TemplateManagerImpl.getTemplateState(parameters.getEditor()) != null) {
+      return;
+    }
+
     PsiElement position = parameters.getPosition();
     final Set<LookupElement> lookupSet = new THashSet<LookupElement>();
     if (psiElement(PsiIdentifier.class).andNot(INSIDE_TYPE_PARAMS_PATTERN).withParent(
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
index e099338..c28c807 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
@@ -51,14 +51,13 @@
 
     if (empty) {
       delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result));
-    } else if (Registry.is("ide.completion.show.all.classes") || Registry.is("ide.completion.show.better.matching.classes")) {
-      if (parameters.getInvocationCount() <= 1 &&
+    } else if (Registry.is("ide.completion.show.better.matching.classes")) {
+      if (parameters.getCompletionType() == CompletionType.BASIC &&
+          parameters.getInvocationCount() <= 1 &&
           JavaCompletionContributor.mayStartClassName(result) &&
           JavaCompletionContributor.isClassNamePossible(parameters) &&
           !JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition())) {
-        if (Registry.is("ide.completion.show.better.matching.classes")) {
-          result = result.withPrefixMatcher(new BetterPrefixMatcher(result.getPrefixMatcher(), BetterPrefixMatcher.getBestMatchingDegree(plainResults))); 
-        }
+        result = result.withPrefixMatcher(new BetterPrefixMatcher(result.getPrefixMatcher(), BetterPrefixMatcher.getBestMatchingDegree(plainResults)));
         suggestNonImportedClasses(parameters, result);
       }
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java
deleted file mode 100644
index 7467edc..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java
+++ /dev/null
@@ -1,110 +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.codeInsight.completion;
-
-import com.intellij.codeInsight.generation.GenerateMembersUtil;
-import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
-import com.intellij.codeInsight.generation.OverrideImplementUtil;
-import com.intellij.codeInsight.generation.PsiGenerationInfo;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementBuilder;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.util.Key;
-import com.intellij.psi.*;
-import com.intellij.psi.infos.CandidateInfo;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiFormatUtilBase;
-import com.intellij.ui.RowIcon;
-import com.intellij.util.VisibilityUtil;
-
-import java.util.List;
-
-import static com.intellij.patterns.PlatformPatterns.psiElement;
-
-/**
- * @author peter
- */
-public class JavaOverrideCompletionContributor {
-  static final Key<Boolean> OVERRIDE_ELEMENT = Key.create("OVERRIDE_ELEMENT");
-
-  public static void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
-    if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) {
-      return;
-    }
-
-    PsiElement position = parameters.getPosition();
-    if (psiElement(PsiIdentifier.class).withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class).
-      andNot(JavaCompletionData.AFTER_DOT).
-      andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
-      final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
-      if (parent != null) {
-        addSuperSignatureElements(parent, true, result);
-        addSuperSignatureElements(parent, false, result);
-      }
-    }
-
-  }
-
-  private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
-    for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
-      PsiMethod baseMethod = (PsiMethod)candidate.getElement();
-      PsiClass baseClass = baseMethod.getContainingClass();
-      if (!baseMethod.isConstructor() && baseClass != null) {
-        result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor()));
-      }
-    }
-  }
-
-  private static LookupElementBuilder createOverridingLookupElement(final PsiClass parent,
-                                                                    boolean implemented,
-                                                                    final PsiMethod baseMethod,
-                                                                    PsiClass baseClass, PsiSubstitutor substitutor) {
-    String methodName = baseMethod.getName();
-
-    String visibility = VisibilityUtil.getVisibilityModifier(baseMethod.getModifierList());
-    String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
-
-    PsiType type = substitutor.substitute(baseMethod.getReturnType());
-    String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
-
-    String parameters = PsiFormatUtil.formatMethod(baseMethod, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
-
-    InsertHandler<LookupElement> insertHandler = new InsertHandler<LookupElement>() {
-      @Override
-      public void handleInsert(InsertionContext context, LookupElement item) {
-        context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
-        context.commitDocument();
-
-        List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
-        List<PsiGenerationInfo<PsiMethod>> infos = OverrideImplementUtil.convert2GenerationInfos(prototypes);
-        List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
-        if (!newInfos.isEmpty()) {
-          newInfos.get(0).positionCaret(context.getEditor(), true);
-        }
-      }
-    };
-
-    RowIcon icon = new RowIcon(2);
-    icon.setIcon(baseMethod.getIcon(0), 0);
-    icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
-
-    LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(methodName).
-      withLookupString(signature).withInsertHandler(insertHandler).
-      appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon);
-    element.putUserData(OVERRIDE_ELEMENT, true);
-    return element;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
index 5e7af80..9710f75 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
@@ -474,10 +474,10 @@
         return;
       }
       if (parent instanceof PsiParenthesizedExpression) {
-        context.setDummyIdentifier("xxx)yyy "); // to handle type cast
+        context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + ")" + CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + " "); // to handle type cast
         return;
       }
     }
-    context.setDummyIdentifier("xxx");
+    context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
index f316b0a..f4adccc 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
@@ -284,7 +284,9 @@
       final PsiType expectedType = parameters.getExpectedType();
       if (!OBJECT_METHOD_PATTERN.accepts(object) || allowGetClass(object, parameters)) {
         if (parameters.getParameters().getInvocationCount() >= 3 || !itemType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
-          addChainedCallVariants(element, baseItem, result, itemType, expectedType, parameters);
+          if (!(object instanceof PsiMethod && ((PsiMethod)object).getParameterList().getParametersCount() > 0)) {
+            addChainedCallVariants(element, baseItem, result, itemType, expectedType, parameters);
+          }
         }
       }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
new file mode 100644
index 0000000..688fada
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
@@ -0,0 +1,94 @@
+package com.intellij.codeInsight.completion.methodChains;
+
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionStringUtil {
+  private ChainCompletionStringUtil() {}
+
+  public static boolean isPrimitiveOrArray(final @Nullable String typeQName) {
+    return typeQName != null && (typeQName.endsWith("[]") || PRIMITIVES_NAMES.contains(typeQName));
+  }
+
+  /**
+   * CAUTION: isPrimitiveOrArrayOfPrimitives("java.lang.String") == true,
+   *          isPrimitiveOrArrayOfPrimitives("java.lang.Object") == true
+   *          isPrimitiveOrArrayOfPrimitives("java.lang.Class") == true
+   */
+  public static boolean isPrimitiveOrArrayOfPrimitives(final String typeQName) {
+    if (typeQName == null) {
+      return false;
+    }
+    return PRIMITIVES_NAMES.contains(deleteArraySigns(typeQName));
+  }
+
+  public static boolean isShortNamePrimitiveOrArrayOfPrimitives(final @Nullable String shortName) {
+    if (shortName == null) {
+      return false;
+    }
+    return PRIMITIVES_SHORT_NAMES.contains(deleteArraySigns(shortName));
+  }
+
+  private static String deleteArraySigns(final @NotNull String typeName) {
+    String nameWithoutArraySign = typeName;
+    while (nameWithoutArraySign.endsWith("[]")) {
+      nameWithoutArraySign = nameWithoutArraySign.substring(0, nameWithoutArraySign.length() - 2);
+    }
+    return nameWithoutArraySign;
+  }
+
+  private static final Set<String> PRIMITIVES_NAMES = new HashSet<String>();
+
+  static {
+    fillPrimitivesNames(PsiType.BOOLEAN);
+    fillPrimitivesNames(PsiType.INT);
+    fillPrimitivesNames(PsiType.LONG);
+    fillPrimitivesNames(PsiType.DOUBLE);
+    fillPrimitivesNames(PsiType.FLOAT);
+    fillPrimitivesNames(PsiType.SHORT);
+    fillPrimitivesNames(PsiType.CHAR);
+    fillPrimitivesNames(PsiType.BYTE);
+    fillPrimitivesNames(PsiType.VOID);
+    PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_STRING);
+    PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_OBJECT);
+    PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_CLASS);
+  }
+
+  private static void fillPrimitivesNames(final PsiPrimitiveType type) {
+    PRIMITIVES_NAMES.add(type.getBoxedTypeName());
+    PRIMITIVES_NAMES.add(type.getCanonicalText());
+  }
+
+  private static final Set<String> PRIMITIVES_SHORT_NAMES = new HashSet<String>();
+
+  static {
+    fillPrimitivesShortNames(PsiType.BOOLEAN);
+    fillPrimitivesShortNames(PsiType.INT);
+    fillPrimitivesShortNames(PsiType.LONG);
+    fillPrimitivesShortNames(PsiType.DOUBLE);
+    fillPrimitivesShortNames(PsiType.FLOAT);
+    fillPrimitivesShortNames(PsiType.SHORT);
+    fillPrimitivesShortNames(PsiType.CHAR);
+    fillPrimitivesShortNames(PsiType.BYTE);
+    fillPrimitivesShortNames(PsiType.VOID);
+    PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_STRING));
+    PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_OBJECT));
+    PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_CLASS));
+  }
+
+  private static void fillPrimitivesShortNames(final PsiPrimitiveType type) {
+    PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(type.getBoxedTypeName()));
+    PRIMITIVES_SHORT_NAMES.add(type.getCanonicalText());
+  }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java
new file mode 100644
index 0000000..7a326a7
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java
@@ -0,0 +1,20 @@
+package com.intellij.codeInsight.completion.methodChains;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class Constants {
+
+  private Constants() {
+  }
+
+  /**
+   * magic numbers
+   */
+  public static final int SINGLETON_MAGIC_RATIO = 100;
+
+  public static final int SINGLETON_MAGIC_RATIO2 = 5;
+
+  public static final int CHAIN_SEARCH_MAGIC_RATIO = 12;
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
new file mode 100644
index 0000000..f020afa
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
@@ -0,0 +1,33 @@
+package com.intellij.codeInsight.completion.methodChains.completion;
+
+import com.intellij.codeInsight.completion.CompletionInitializationContext;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
+
+import static com.intellij.patterns.PsiJavaPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.or;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class CompletionContributorPatternUtil {
+
+  private CompletionContributorPatternUtil() {}
+
+  @SuppressWarnings("unchecked")
+  public static ElementPattern<PsiElement> patternForVariableAssignment() {
+    final ElementPattern<PsiElement> patternForParent = or(psiElement().withText(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)
+                                                             .afterSiblingSkipping(psiElement(PsiWhiteSpace.class),
+                                                                                   psiElement(PsiJavaToken.class).withText("=")));
+
+    return psiElement().withParent(patternForParent).withSuperParent(2, or(psiElement(PsiAssignmentExpression.class),
+                                                                           psiElement(PsiLocalVariable.class)
+                                                                             .inside(PsiDeclarationStatement.class)))
+                                                                             .inside(PsiMethod.class);
+  }
+
+  public static ElementPattern<PsiElement> patternForMethodParameter() {
+    return psiElement().withSuperParent(3, PsiMethodCallExpressionImpl.class);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
new file mode 100644
index 0000000..27c63a0
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
@@ -0,0 +1,206 @@
+package com.intellij.codeInsight.completion.methodChains.completion;
+
+import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextUtil;
+import com.intellij.codeInsight.completion.methodChains.search.ChainsSearcher;
+import com.intellij.codeInsight.completion.methodChains.search.MethodChainsSearchService;
+import com.intellij.codeInsight.completion.methodChains.search.MethodsChain;
+import com.intellij.codeInsight.completion.methodChains.search.MethodsChainLookupRangingHelper;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ProcessingContext;
+import com.intellij.util.Processor;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static com.intellij.patterns.PsiJavaPatterns.or;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsCompletionContributor extends CompletionContributor {
+  public static final int INVOCATIONS_THRESHOLD = 3;
+
+  private final static int MAX_SEARCH_RESULT_SIZE = 20;
+  private final static int MAX_CHAIN_SIZE = 4;
+  private final static int FILTER_RATIO = 10;
+
+  @Override
+  public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
+    if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD && CompilerOutputIndexer.getInstance(parameters.getPosition().getProject()).isEnabled()) {
+      super.fillCompletionVariants(parameters, result);
+      if (ApplicationManager.getApplication().isUnitTestMode()) {
+        result.stopHere();
+      }
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public MethodsChainsCompletionContributor() {
+    final ElementPattern<PsiElement> pattern =
+      or(CompletionContributorPatternUtil.patternForMethodParameter(), CompletionContributorPatternUtil.patternForVariableAssignment());
+    extend(CompletionType.BASIC, pattern, new CompletionProvider<CompletionParameters>() {
+      @Override
+      protected void addCompletions(final @NotNull CompletionParameters parameters,
+                                    final ProcessingContext context,
+                                    final @NotNull CompletionResultSet result) {
+
+        final ChainCompletionContext completionContext = extractContext(parameters);
+        if (completionContext == null) return;
+
+
+        final String targetClassQName = completionContext.getTargetQName();
+        final Set<String> contextTypesKeysSet = completionContext.getContextTypes();
+        final Set<String> contextRelevantTypes = new HashSet<String>(contextTypesKeysSet.size() + 1);
+        for (final String type : contextTypesKeysSet) {
+          if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(type)) {
+            contextRelevantTypes.add(type);
+          }
+        }
+        contextRelevantTypes.remove(targetClassQName);
+
+        final List<LookupElement> foundedElements = searchForLookups(targetClassQName, contextRelevantTypes, completionContext);
+        result.addAllElements(foundedElements);
+      }
+    });
+  }
+
+  private static List<LookupElement> searchForLookups(final String targetClassQName,
+                                                      final Set<String> contextRelevantTypes,
+                                                      final ChainCompletionContext completionContext) {
+    final MethodChainsSearchService searchService = new MethodChainsSearchService(completionContext.getProject());
+    final List<MethodsChain> searchResult =
+      searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, searchService);
+    if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) {
+      final PsiClass aClass = JavaPsiFacade.getInstance(completionContext.getProject())
+        .findClass(targetClassQName, GlobalSearchScope.allScope(completionContext.getProject()));
+      if (aClass != null) {
+        DirectClassInheritorsSearch.search(aClass).forEach(new Processor<PsiClass>() {
+          @Override
+          public boolean process(final PsiClass psiClass) {
+            final String inheritorQName = psiClass.getQualifiedName();
+            if (!StringUtil.isEmpty(inheritorQName)) {
+              final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>();
+              //noinspection ConstantConditions
+              for (final MethodsChain chain : searchChains(inheritorQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE,
+                                                           completionContext, searchService)) {
+                boolean insert = true;
+                for (final MethodsChain baseChain : searchResult) {
+                  if (baseChain.weakContains(chain)) {
+                    insert = false;
+                    break;
+                  }
+                }
+                if (insert) {
+                  inheritorFilteredSearchResult.add(chain);
+                }
+              }
+              searchResult.addAll(inheritorFilteredSearchResult);
+            }
+            return true;
+          }
+        });
+      }
+    }
+    return MethodsChainLookupRangingHelper.chainsToWeightableLookupElements(filterTailAndGetSumLastMethodOccurrence(searchResult),
+                                                                             completionContext);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Nullable
+  private static ChainCompletionContext extractContext(final CompletionParameters parameters) {
+    final PsiElement parent = PsiTreeUtil
+      .getParentOfType(parameters.getPosition(), PsiAssignmentExpression.class, PsiLocalVariable.class, PsiMethodCallExpression.class);
+    if (parent == null) {
+      return null;
+    }
+
+    if (parent instanceof PsiAssignmentExpression) {
+      return tryExtractContextFromAssignment((PsiAssignmentExpression)parent);
+    }
+    if (parent instanceof PsiLocalVariable) {
+      final PsiLocalVariable localVariable = (PsiLocalVariable)parent;
+      return ContextUtil.createContext(localVariable.getType(), localVariable.getName(),
+                                       PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class));
+    }
+    final PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
+    if (method == null) return null;
+    final PsiExpression expression = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpression.class);
+    final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpressionList.class);
+    if (expressionList == null) return null;
+    final int exprPosition = Arrays.asList(expressionList.getExpressions()).indexOf(expression);
+    final PsiParameter[] methodParameters = method.getParameterList().getParameters();
+    if (exprPosition < methodParameters.length) {
+      final PsiParameter methodParameter = methodParameters[exprPosition];
+      return ContextUtil
+        .createContext(methodParameter.getType(), null, PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class));
+    }
+    return null;
+  }
+
+  @Nullable
+  private static ChainCompletionContext tryExtractContextFromAssignment(final PsiAssignmentExpression assignmentExpression) {
+    final PsiType type = assignmentExpression.getLExpression().getType();
+    final PsiIdentifier identifier = PsiTreeUtil.getChildOfType(assignmentExpression.getLExpression(), PsiIdentifier.class);
+    if (identifier == null) return null;
+    final String identifierText = identifier.getText();
+    return ContextUtil.createContext(type, identifierText, assignmentExpression);
+  }
+
+  private static List<MethodsChain> filterTailAndGetSumLastMethodOccurrence(final List<MethodsChain> chains) {
+    int maxWeight = 0;
+    for (final MethodsChain chain : chains) {
+      final int chainWeight = chain.getChainWeight();
+      if (chainWeight > maxWeight) {
+        maxWeight = chainWeight;
+      }
+    }
+
+    final List<MethodsChain> filteredResult = new ArrayList<MethodsChain>();
+    for (final MethodsChain chain : chains) {
+      final int chainWeight = chain.getChainWeight();
+      if (chainWeight * FILTER_RATIO >= maxWeight) {
+        filteredResult.add(chain);
+      }
+    }
+    return filteredResult;
+  }
+
+  private static List<MethodsChain> searchChains(final String targetQName,
+                                                 final Set<String> contextVarsQNames,
+                                                 final int maxResultSize,
+                                                 final int maxChainSize,
+                                                 final ChainCompletionContext context,
+                                                 final MethodChainsSearchService searchService) {
+    return ChainsSearcher.search(searchService, targetQName, contextVarsQNames, maxResultSize, maxChainSize,
+                                 createNotDeprecatedMethodsResolver(JavaPsiFacade.getInstance(context.getProject()),
+                                                                    context.getResolveScope()),
+                                 context.getExcludedQNames(), context.getContextMethodName());
+  }
+
+  private static FactoryMap<MethodIncompleteSignature, PsiMethod[]> createNotDeprecatedMethodsResolver(final JavaPsiFacade javaPsiFacade,
+                                                                                                       final GlobalSearchScope scope) {
+    return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
+      @Nullable
+      @Override
+      protected PsiMethod[] create(final MethodIncompleteSignature signature) {
+        return signature.resolveNotDeprecated(javaPsiFacade, scope);
+      }
+    };
+  }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
new file mode 100644
index 0000000..57293ca
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion.methodChains.completion;
+
+import com.intellij.codeInsight.completion.CompletionLocation;
+import com.intellij.codeInsight.completion.CompletionWeigher;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsWeigher extends CompletionWeigher {
+  @Override
+  public Comparable weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
+    if (element instanceof WeightableChainLookupElement) {
+      return ((WeightableChainLookupElement)element).getChainRelevance();
+    }
+    return ChainRelevance.LOWEST;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
new file mode 100644
index 0000000..bb8d92d
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
@@ -0,0 +1,156 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.methodChains.search.CachedRelevantStaticMethodSearcher;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionContext {
+  private final NotNullLazyValue<String> myContextMethodName = new NotNullLazyValue<String>() {
+    @NotNull
+    @Override
+    protected String compute() {
+      return myContextMethod.getName();
+    }
+  };
+  private final PsiMethod myContextMethod;
+  private final String myTargetQName;
+  private final Set<String> myContainingClassQNames;
+  private final MultiMap<String, PsiVariable> myContextVars;
+  private final MultiMap<String, PsiMethod> myContainingClassGetters;
+  private final MultiMap<String, ContextRelevantVariableGetter> myContextVarsGetters;
+  private final Map<String, PsiVariable> myStringVars;
+  private final CachedRelevantStaticMethodSearcher myStaticMethodSearcher;
+  private final Set<String> myExcludedQNames;
+  private final GlobalSearchScope myResolveScope;
+  private final Project myProject;
+
+  private final NotNullLazyValue<Set<String>> contextTypesQNames = new NotNullLazyValue<Set<String>>() {
+    @SuppressWarnings("unchecked")
+    @NotNull
+    @Override
+    protected Set<String> compute() {
+      return unionToHashSet(myContainingClassQNames, myContextVars.keySet(), myContainingClassGetters.keySet(),
+                            myContextVarsGetters.keySet());
+    }
+  };
+
+  public Set<String> getExcludedQNames() {
+    return myExcludedQNames;
+  }
+
+  ChainCompletionContext(final PsiMethod contextMethod,
+                         final String targetQName,
+                         final Set<String> containingClassQNames,
+                         final MultiMap<String, PsiVariable> contextVars,
+                         final MultiMap<String, PsiMethod> containingClassGetters,
+                         final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters,
+                         final Map<String, PsiVariable> stringVars,
+                         final Set<String> excludedQNames,
+                         final Project project,
+                         final GlobalSearchScope resolveScope) {
+    myContextMethod = contextMethod;
+    myTargetQName = targetQName;
+    myContainingClassQNames = containingClassQNames;
+    myContextVars = contextVars;
+    myContainingClassGetters = containingClassGetters;
+    myContextVarsGetters = contextVarsGetters;
+    myStringVars = stringVars;
+    myExcludedQNames = excludedQNames;
+    myResolveScope = resolveScope;
+    myProject = project;
+    myStaticMethodSearcher = new CachedRelevantStaticMethodSearcher(project, resolveScope);
+  }
+
+  public PsiMethod getContextMethod() {
+    return myContextMethod;
+  }
+
+  public String getContextMethodName() {
+    return myContextMethodName.getValue();
+  }
+
+  public String getTargetQName() {
+    return myTargetQName;
+  }
+
+  @Nullable
+  public PsiVariable findRelevantStringInContext(@Nullable final String stringParamName) {
+    if (stringParamName == null) {
+      return null;
+    }
+    for (final Map.Entry<String, PsiVariable> e : myStringVars.entrySet()) {
+      if (ChainCompletionContextStringUtil.isSimilar(e.getKey(), stringParamName)) {
+        return e.getValue();
+      }
+    }
+    return null;
+  }
+
+  public Set<String> getContainingClassQNames() {
+    return myContainingClassQNames;
+  }
+
+  public Collection<PsiVariable> getVariables(final String typeQName) {
+    return myContextVars.get(typeQName);
+  }
+
+  public Collection<PsiMethod> getContainingClassMethods(final String typeQName) {
+    return myContainingClassGetters.get(typeQName);
+  }
+
+  public Collection<ContextRelevantStaticMethod> getRelevantStaticMethods(final String typeQName, final int weight) {
+    return myStaticMethodSearcher.getRelevantStaticMethods(typeQName, weight, this);
+  }
+
+  public Collection<ContextRelevantVariableGetter> getRelevantVariablesGetters(final String typeQName) {
+    return myContextVarsGetters.get(typeQName);
+  }
+
+  public Collection<?> getContextRefElements(final String typeQName) {
+    final Collection<PsiVariable> variables = getVariables(typeQName);
+    final Collection<PsiMethod> containingClassMethods = getContainingClassMethods(typeQName);
+    final Collection<UserDataHolder> refElements = new ArrayList<UserDataHolder>(variables.size() + containingClassMethods.size());
+    refElements.addAll(variables);
+    refElements.addAll(containingClassMethods);
+    for (final ContextRelevantVariableGetter contextRelevantVariableGetter : getRelevantVariablesGetters(typeQName)) {
+      refElements.add(contextRelevantVariableGetter.createLookupElement());
+    }
+    return refElements;
+  }
+
+  public boolean contains(@Nullable final String typeQualifierName) {
+    return typeQualifierName != null && contextTypesQNames.getValue().contains(typeQualifierName);
+  }
+
+  public Set<String> getContextTypes() {
+    return contextTypesQNames.getValue();
+  }
+
+  public GlobalSearchScope getResolveScope() {
+    return myResolveScope;
+  }
+
+  public Project getProject() {
+    return myProject;
+  }
+
+  private static <T> HashSet<T> unionToHashSet(final Collection<T>... collections) {
+    final HashSet<T> res = new HashSet<T>();
+    for (final Collection<T> set : collections) {
+      res.addAll(set);
+    }
+    return res;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
new file mode 100644
index 0000000..a9b1903
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
@@ -0,0 +1,36 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+class ChainCompletionContextStringUtil {
+
+  private ChainCompletionContextStringUtil(){}
+
+  private final static int COMMON_PART_MIN_LENGTH = 3;
+
+  public static boolean isSimilar(@NotNull final String varName,
+                                  @NotNull final String parameterName) {
+    final String sanitizedParamName = sanitizedToLowerCase(parameterName);
+    if (StringUtil.commonPrefix(varName, sanitizedParamName).length() >= COMMON_PART_MIN_LENGTH) {
+      return true;
+    }
+    final String suffix = StringUtil.commonSuffix(varName, sanitizedParamName);
+    return suffix.length() >= COMMON_PART_MIN_LENGTH;
+  }
+
+  @NotNull
+  public static String sanitizedToLowerCase(@NotNull final String name) {
+    final StringBuilder result = new StringBuilder();
+    for (int i = 0; i < name.length(); i++) {
+      final char ch = name.charAt(i);
+      if (Character.isLetter(ch)) {
+        result.append(Character.toLowerCase(ch));
+      }
+    }
+    return result.toString();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
new file mode 100644
index 0000000..23b1c26
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
@@ -0,0 +1,45 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.StaticMethodSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ContextRelevantStaticMethod {
+  private final PsiMethod psiMethod;
+  @Nullable
+  private final TIntObjectHashMap<SubLookupElement> parameters;
+
+  public ContextRelevantStaticMethod(final PsiMethod psiMethod, @Nullable final TIntObjectHashMap<PsiVariable> parameters) {
+    this.psiMethod = psiMethod;
+    if (parameters == null) {
+      this.parameters = null;
+    } else {
+      this.parameters = new TIntObjectHashMap<SubLookupElement>(parameters.size());
+      parameters.forEachEntry(new TIntObjectProcedure<PsiVariable>() {
+        @SuppressWarnings("ConstantConditions")
+        @Override
+        public boolean execute(final int pos, final PsiVariable var) {
+          ContextRelevantStaticMethod.this.parameters.put(pos, new VariableSubLookupElement(var));
+          return false;
+        }
+      });
+    }
+  }
+
+  private SubLookupElement cachedLookupElement;
+
+  public SubLookupElement createLookupElement() {
+    if (cachedLookupElement == null) {
+      cachedLookupElement = new StaticMethodSubLookupElement(psiMethod, parameters);
+    }
+    return cachedLookupElement;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
new file mode 100644
index 0000000..fec1cfd
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
@@ -0,0 +1,31 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ContextRelevantVariableGetter {
+  private final PsiVariable myVariable;
+  private final PsiMethod myMethod;
+
+  public ContextRelevantVariableGetter(final PsiVariable variable, final PsiMethod method) {
+    myVariable = variable;
+    myMethod = method;
+  }
+
+  public SubLookupElement createSubLookupElement() {
+    return new GetterLookupSubLookupElement(myVariable.getName(), myMethod.getName());
+  }
+
+  public LookupElement createLookupElement() {
+    return new JavaChainLookupElement(new VariableLookupItem(myVariable), new JavaMethodCallElement(myMethod));
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
new file mode 100644
index 0000000..481c5f8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
@@ -0,0 +1,245 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ContextUtil {
+  @Nullable
+  public static ChainCompletionContext createContext(final @Nullable PsiType variableType,
+                                                     final @Nullable String variableName,
+                                                     final @Nullable PsiElement containingElement) {
+    if (variableType == null || containingElement == null) {
+      return null;
+    }
+    if (variableType instanceof PsiClassType) {
+      final PsiClass aClass = ((PsiClassType)variableType).resolve();
+      if (aClass != null) {
+        if (aClass.hasTypeParameters()) {
+          return null;
+        }
+      }
+      else {
+        return null;
+      }
+    }
+
+    final String targetQName = variableType.getCanonicalText();
+    if (targetQName == null || targetQName.endsWith("[]")) {
+      return null;
+    }
+
+    final PsiMethod method = PsiTreeUtil.getParentOfType(containingElement, PsiMethod.class);
+    if (method == null) {
+      return null;
+    }
+    final PsiClass aClass = method.getContainingClass();
+    if (aClass == null) {
+      return null;
+    }
+    final Set<String> containingClassQNames = resolveSupersNamesRecursively(aClass);
+
+    final List<PsiVariable> contextVars = new SmartList<PsiVariable>();
+    for (final PsiField field : aClass.getFields()) {
+      final PsiClass containingClass = field.getContainingClass();
+      if (containingClass != null) {
+        if ((field.hasModifierProperty(PsiModifier.PUBLIC) ||
+             field.hasModifierProperty(PsiModifier.PROTECTED) ||
+             ((field.hasModifierProperty(PsiModifier.PRIVATE) || field.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) &&
+              aClass.isEquivalentTo(containingClass))) && !field.getName().equals(variableName)) {
+          contextVars.add(field);
+        }
+      }
+    }
+    Collections.addAll(contextVars, method.getParameterList().getParameters());
+
+    final PsiCodeBlock methodBody = method.getBody();
+    assert methodBody != null;
+    boolean processMethodTail = false;
+    final List<PsiElement> afterElements = new ArrayList<PsiElement>();
+    for (final PsiElement element : methodBody.getChildren()) {
+      if (element.isEquivalentTo(containingElement)) {
+        if (variableType instanceof PsiClassType) {
+          processMethodTail = true;
+          continue;
+        }
+        else {
+          break;
+        }
+      }
+      if (element instanceof PsiDeclarationStatement) {
+        if (processMethodTail) {
+          afterElements.add(element);
+        }
+        else {
+          for (final PsiElement declaredElement : ((PsiDeclarationStatement)element).getDeclaredElements()) {
+            if (declaredElement instanceof PsiLocalVariable &&
+                (variableName == null || !variableName.equals(((PsiLocalVariable)declaredElement).getName()))) {
+              contextVars.add((PsiVariable)declaredElement);
+            }
+          }
+        }
+      }
+    }
+
+    final Set<String> excludedQNames = processMethodTail
+                                       ? generateExcludedQNames(afterElements, ((PsiClassType)variableType).resolve(), variableName,
+                                                                contextVars)
+                                       : Collections.<String>emptySet();
+
+    final List<PsiMethod> contextMethods = new ArrayList<PsiMethod>();
+    for (final PsiMethod psiMethod : aClass.getMethods()) {
+      if ((psiMethod.hasModifierProperty(PsiModifier.PROTECTED) || psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) &&
+          psiMethod.getParameterList().getParametersCount() == 0) {
+        contextMethods.add(psiMethod);
+      }
+    }
+
+    return create(method, targetQName, contextVars, contextMethods, containingClassQNames, containingElement.getProject(),
+                  containingElement.getResolveScope(), excludedQNames);
+  }
+
+  private static Set<String> generateExcludedQNames(final List<PsiElement> tailElements,
+                                                    final @Nullable PsiClass psiClass,
+                                                    final @Nullable String varName,
+                                                    final List<PsiVariable> contextVars) {
+    if (psiClass == null) {
+      return Collections.emptySet();
+    }
+    final String classQName = psiClass.getQualifiedName();
+    if (classQName == null) {
+      return Collections.emptySet();
+    }
+
+    final Set<String> excludedQNames = new HashSet<String>();
+    if (!tailElements.isEmpty()) {
+      final Set<String> contextVarTypes = new HashSet<String>();
+      final Map<String, PsiVariable> contextVarNamesToVar = new HashMap<String, PsiVariable>();
+      for (final PsiVariable var : contextVars) {
+        contextVarTypes.add(var.getType().getCanonicalText());
+        contextVarNamesToVar.put(var.getName(), var);
+      }
+      for (final PsiElement element : tailElements) {
+        final Collection<PsiMethodCallExpression> methodCallExpressions =
+          PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression.class);
+        for (final PsiMethodCallExpression methodCallExpression : methodCallExpressions) {
+          final PsiExpressionList args = methodCallExpression.getArgumentList();
+          final PsiMethod resolvedMethod = methodCallExpression.resolveMethod();
+          if (resolvedMethod != null) {
+            final PsiType returnType = resolvedMethod.getReturnType();
+            if (returnType != null) {
+              final String returnTypeAsString = returnType.getCanonicalText();
+              for (final PsiExpression expression : args.getExpressions()) {
+                final String qVarName = expression.getText();
+                if (qVarName != null) {
+                  if (contextVarNamesToVar.containsKey(qVarName) || qVarName.equals(varName)) {
+                    excludedQNames.add(returnTypeAsString);
+                  }
+                }
+              }
+              if (!contextVarTypes.contains(returnTypeAsString)) {
+                excludedQNames.add(returnTypeAsString);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return excludedQNames;
+  }
+
+  @Nullable
+  private static ChainCompletionContext create(final PsiMethod contextMethod,
+                                               final String targetQName,
+                                               final List<PsiVariable> contextVars,
+                                               final List<PsiMethod> contextMethods,
+                                               final Set<String> containingClassQNames,
+                                               final Project project,
+                                               final GlobalSearchScope resolveScope,
+                                               final Set<String> excludedQNames) {
+    final MultiMap<String, PsiVariable> classQNameToVariable = new MultiMap<String, PsiVariable>();
+    final MultiMap<String, PsiMethod> containingClassGetters = new MultiMap<String, PsiMethod>();
+    final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters = new MultiMap<String, ContextRelevantVariableGetter>();
+    final Map<String, PsiVariable> stringVars = new HashMap<String, PsiVariable>();
+
+    for (final PsiMethod method : contextMethods) {
+      final String returnTypeQName = method.getReturnType().getCanonicalText();
+      if (returnTypeQName != null) {
+        containingClassGetters.putValue(returnTypeQName, method);
+      }
+    }
+
+    for (final PsiVariable var : contextVars) {
+      final PsiType type = var.getType();
+      final Set<String> classQNames = new HashSet<String>();
+      if (type instanceof PsiClassType) {
+        if (JAVA_LANG_STRING_SHORT_NAME.equals(((PsiClassType)type).getClassName())) {
+          final String varName = var.getName();
+          if (varName != null) {
+            stringVars.put(ChainCompletionContextStringUtil.sanitizedToLowerCase(varName), var);
+            continue;
+          }
+        }
+
+        final PsiClass aClass = ((PsiClassType)type).resolve();
+        if (aClass != null) {
+          final String classQName = type.getCanonicalText();
+          if (!targetQName.equals(classQName)) {
+            classQNames.add(classQName);
+            classQNames.addAll(resolveSupersNamesRecursively(aClass));
+            for (final PsiMethod method : aClass.getAllMethods()) {
+              if (method.getParameterList().getParametersCount() == 0 && method.getName().startsWith("get")) {
+                final String getterReturnTypeQName = method.getReturnType().getCanonicalText();
+                if (getterReturnTypeQName != null) {
+                  contextVarsGetters.putValue(getterReturnTypeQName, new ContextRelevantVariableGetter(var, method));
+                }
+              }
+            }
+          }
+        }
+      }
+      else {
+        final String classQName = type.getCanonicalText();
+        if (classQName != null) {
+          classQNames.add(classQName);
+        }
+      }
+      for (final String qName : classQNames) {
+        classQNameToVariable.putValue(qName, var);
+      }
+    }
+    return new ChainCompletionContext(contextMethod, targetQName, containingClassQNames, classQNameToVariable, containingClassGetters,
+                                      contextVarsGetters, stringVars, excludedQNames, project, resolveScope);
+  }
+
+  @NotNull
+  private static Set<String> resolveSupersNamesRecursively(@Nullable final PsiClass psiClass) {
+    final Set<String> result = new HashSet<String>();
+    if (psiClass != null) {
+      for (final PsiClass superClass : psiClass.getSupers()) {
+        final String qualifiedName = superClass.getQualifiedName();
+        if (!CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
+          if (qualifiedName != null) {
+            result.add(qualifiedName);
+          }
+          result.addAll(resolveSupersNamesRecursively(superClass));
+        }
+      }
+    }
+    return result;
+  }
+
+  private final static String JAVA_LANG_STRING_SHORT_NAME = StringUtil.getShortName(CommonClassNames.JAVA_LANG_STRING);
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
new file mode 100644
index 0000000..65be892
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
@@ -0,0 +1,53 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.psi.PsiKeyword;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.PsiParameter;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionLookupElementUtil {
+  private ChainCompletionLookupElementUtil() {
+  }
+
+  public static LookupElement createLookupElement(final PsiMethod method,
+                                                  final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+    if (method.isConstructor()) {
+      //noinspection ConstantConditions
+      return LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
+    } else if (method.hasModifierProperty(PsiModifier.STATIC)) {
+      return new ChainCompletionMethodCallLookupElement(method, replaceElements, false, true);
+    } else {
+      return new ChainCompletionMethodCallLookupElement(method, replaceElements);
+    }
+  }
+
+  public static String fillMethodParameters(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+    final TIntObjectHashMap<SubLookupElement> notNullReplaceElements = replaceElements == null ?
+        new TIntObjectHashMap<SubLookupElement>(0) :
+        replaceElements;
+
+    final PsiParameter[] parameters = method.getParameterList().getParameters();
+    final StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < parameters.length; i++) {
+      if (i != 0) {
+        sb.append(", ");
+      }
+      final PsiParameter parameter = parameters[i];
+      final SubLookupElement replaceElement = notNullReplaceElements.get(i);
+      if (replaceElement != null) {
+        sb.append(replaceElement.getInsertString());
+      } else {
+        sb.append(parameter.getName());
+      }
+    }
+    return sb.toString();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
new file mode 100644
index 0000000..f7a62d6
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
@@ -0,0 +1,88 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.codeInsight.completion.StaticallyImportable;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionMethodCallLookupElement extends JavaMethodCallElement implements StaticallyImportable {
+  public static final String PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION = "methods.chain.completion.autoCompletion";
+
+  private final PsiMethod myMethod;
+  @Nullable
+  private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+  private final boolean myMergedOverloads;
+
+  public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+                                                final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements,
+                                                final boolean shouldImportStatic,
+                                                final boolean mergedOverloads) {
+    super(method, shouldImportStatic, mergedOverloads);
+    myMethod = method;
+    myReplaceElements = replaceElements;
+    myMergedOverloads = mergedOverloads;
+    configureAutoCompletionPolicy();
+  }
+
+  public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+                                                final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+    super(method);
+    myMethod = method;
+    myReplaceElements = replaceElements;
+    myMergedOverloads = true;
+    configureAutoCompletionPolicy();
+  }
+
+  private void configureAutoCompletionPolicy() {
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      if (PropertiesComponent.getInstance(myMethod.getProject()).getBoolean(PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, false)) {
+        setAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
+      }
+    }
+  }
+
+  @Override
+  public void handleInsert(final InsertionContext context) {
+    super.handleInsert(context);
+    if (!myMergedOverloads || isUniqueMethod(myMethod)) {
+      context.commitDocument();
+      context.getDocument()
+        .insertString(context.getTailOffset() - 1, ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+      final PsiFile file = context.getFile();
+      assert file instanceof PsiJavaFile;
+      final PsiJavaFile javaFile = (PsiJavaFile)file;
+      if (myReplaceElements != null) {
+        myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+          @Override
+          public boolean execute(final SubLookupElement subLookupElement) {
+            subLookupElement.doImport(javaFile);
+            return true;
+          }
+        });
+      }
+      context.commitDocument();
+      context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
+      context.commitDocument();
+    }
+  }
+
+
+  private static boolean isUniqueMethod(@NotNull final PsiMethod method) {
+    final PsiClass containingClass = method.getContainingClass();
+    return containingClass == null || containingClass.findMethodsByName(method.getName(), true).length == 1;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
new file mode 100644
index 0000000..53dc9bc
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
@@ -0,0 +1,79 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.codeStyle.SuggestedNameInfo;
+import com.intellij.psi.codeStyle.VariableKind;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainCompletionNewVariableLookupElement extends LookupItem<PsiClass> {
+
+  private final PsiClass psiClass;
+  private final String newVarName;
+
+  public ChainCompletionNewVariableLookupElement(final PsiClass psiClass, final String newVarName) {
+    super(psiClass, newVarName);
+    this.newVarName = newVarName;
+    this.psiClass = psiClass;
+  }
+
+  public static ChainCompletionNewVariableLookupElement create(final PsiClass psiClass) {
+    final Project project = psiClass.getProject();
+    final SuggestedNameInfo suggestedNameInfo = JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, JavaPsiFacade .getElementFactory( project).createType(psiClass));
+    return new ChainCompletionNewVariableLookupElement(psiClass, chooseLongest(suggestedNameInfo.names));
+  }
+
+  @Override
+  public void handleInsert(final InsertionContext context) {
+    final PsiFile file = context.getFile();
+    ((PsiJavaFile) file).importClass(psiClass);
+    final PsiStatement statement = PsiTreeUtil.getParentOfType(file.findElementAt(context.getEditor().getCaretModel().getOffset()), PsiStatement.class);
+    final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(statement, PsiCodeBlock.class);
+    assert codeBlock != null;
+    final Project project = context.getProject();
+    new WriteCommandAction.Simple(project, file) {
+      @Override
+      protected void run() throws Throwable {
+        codeBlock.addBefore(
+            JavaPsiFacade.getElementFactory(
+                project).
+                createStatementFromText(String.format("%s %s = null;", psiClass.getName(), newVarName), null), statement);
+      }
+    }.execute();
+    PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument());
+  }
+
+  @NotNull
+  @Override
+  public String getLookupString() {
+    return newVarName;
+  }
+
+  @Override
+  public void renderElement(final LookupElementPresentation presentation) {
+    super.renderElement(presentation);
+    presentation.setItemText(newVarName);
+  }
+
+  private static String chooseLongest(final String[] names) {
+    String longestWord = names[0];
+    int maxLength = longestWord.length();
+    for (int i = 1; i < names.length; i++) {
+      final int length = names[i].length();
+      if (length > maxLength) {
+        maxLength = length;
+        longestWord = names[i];
+      }
+    }
+    return longestWord;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
new file mode 100644
index 0000000..e58d2c8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
@@ -0,0 +1,22 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
+  private final ChainRelevance myChainRelevance;
+
+  public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
+    super(delegate);
+    myChainRelevance = relevance;
+  }
+
+  public ChainRelevance getChainRelevance() {
+    return myChainRelevance;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
new file mode 100644
index 0000000..e6b8410
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
@@ -0,0 +1,35 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class GetterLookupSubLookupElement implements SubLookupElement {
+  private final String myVariableName;
+  private final String myMethodName;
+
+  public GetterLookupSubLookupElement(final String methodName) {
+    this(null, methodName);
+  }
+
+  public GetterLookupSubLookupElement(@Nullable final String variableName, final String methodName) {
+    myVariableName = variableName;
+    myMethodName = methodName;
+  }
+
+  @Override
+  public void doImport(final PsiJavaFile javaFile) {
+  }
+
+  @Override
+  public String getInsertString() {
+    final StringBuilder sb = new StringBuilder();
+    if (myVariableName != null) {
+      sb.append(myVariableName).append(".");
+    }
+    sb.append(myMethodName).append("()");
+    return sb.toString();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
new file mode 100644
index 0000000..88d8b01
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
@@ -0,0 +1,51 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class StaticMethodSubLookupElement implements SubLookupElement {
+
+  private final PsiMethod myMethod;
+  private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+
+  public StaticMethodSubLookupElement(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+    assert method.hasModifierProperty(PsiModifier.STATIC);
+    myReplaceElements = replaceElements;
+    myMethod = method;
+  }
+
+  @Override
+  public void doImport(final PsiJavaFile javaFile) {
+    final PsiClass containingClass = myMethod.getContainingClass();
+    if (containingClass != null) {
+      if (javaFile.findImportReferenceTo(containingClass) == null) {
+        javaFile.importClass(containingClass);
+      }
+    }
+    if (myReplaceElements != null) {
+      myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+        @Override
+        public boolean execute(final SubLookupElement subLookupElement) {
+          subLookupElement.doImport(javaFile);
+          return false;
+        }
+      });
+    }
+  }
+
+  @Override
+  public String getInsertString() {
+    //noinspection ConstantConditions
+    return String.format("%s.%s(%s)", myMethod.getContainingClass().getName(), myMethod.getName(),
+                         ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
new file mode 100644
index 0000000..7046012
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
@@ -0,0 +1,13 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public interface SubLookupElement {
+
+  void doImport(final PsiJavaFile javaFile);
+
+  String getInsertString();
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
new file mode 100644
index 0000000..894f10b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
@@ -0,0 +1,25 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class VariableSubLookupElement implements SubLookupElement {
+
+  private final String myVarName;
+
+  public VariableSubLookupElement(final PsiVariable variable) {
+    myVarName = variable.getName();
+  }
+
+  @Override
+  public void doImport(final PsiJavaFile javaFile) {
+  }
+
+  @Override
+  public String getInsertString() {
+    return myVarName;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java
new file mode 100644
index 0000000..018065a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java
@@ -0,0 +1,36 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class CachedNotDeprecatedMethodsResolver {
+  private final Map<MethodIncompleteSignature, PsiMethod[]> myResolveLocalCache = new HashMap<MethodIncompleteSignature, PsiMethod[]>();
+  private final JavaPsiFacade myJavaPsiFacade;
+  private final GlobalSearchScope myScope;
+
+  public CachedNotDeprecatedMethodsResolver(final Project project, final GlobalSearchScope scope) {
+    myScope = scope;
+    myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+  }
+
+  @NotNull
+  public PsiMethod[] resolveNotDeprecated(@NotNull final MethodIncompleteSignature methodInvocation) {
+    final PsiMethod[] cached = myResolveLocalCache.get(methodInvocation);
+    if (cached != null) {
+      return cached;
+    }
+    final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myScope);
+    myResolveLocalCache.put(methodInvocation, methods);
+    return methods;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
new file mode 100644
index 0000000..ef11e72
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
@@ -0,0 +1,122 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CachedRelevantStaticMethodSearcher {
+  private final HashMap<MethodIncompleteSignature, PsiMethod> myCachedResolveResults = new HashMap<MethodIncompleteSignature, PsiMethod>();
+  private final MethodsUsageIndex myIndex;
+  private final JavaPsiFacade myJavaPsiFacade;
+  private final GlobalSearchScope myAllScope;
+  private final GlobalSearchScope myResolveScope;
+
+  public CachedRelevantStaticMethodSearcher(final Project project, final GlobalSearchScope resolveScope) {
+    myIndex = MethodsUsageIndex.getInstance(project);
+    myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+    myAllScope = GlobalSearchScope.allScope(project);
+    myResolveScope = resolveScope;
+  }
+
+  @NotNull
+  public List<ContextRelevantStaticMethod> getRelevantStaticMethods(final String resultQualifiedClassName,
+                                                                    final int minOccurrence,
+                                                                    final ChainCompletionContext completionContext) {
+    if (resultQualifiedClassName == null ||
+        ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(resultQualifiedClassName) ||
+        completionContext.getTargetQName().equals(resultQualifiedClassName)) {
+      return Collections.emptyList();
+    }
+    final TreeSet<UsageIndexValue> indexValues = myIndex.getValues(resultQualifiedClassName);
+    if (indexValues != null) {
+      int occurrences = 0;
+      final List<ContextRelevantStaticMethod> relevantMethods = new ArrayList<ContextRelevantStaticMethod>();
+      for (final UsageIndexValue indexValue : extractStaticMethods(indexValues)) {
+        final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+        final PsiMethod method;
+        if (myCachedResolveResults.containsKey(methodInvocation)) {
+          method = myCachedResolveResults.get(methodInvocation);
+        }
+        else {
+          final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myAllScope);
+          method = MethodChainsSearchUtil
+            .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTargetQName()));
+          myCachedResolveResults.put(methodInvocation, method);
+          if (method == null) {
+            return Collections.emptyList();
+          }
+        }
+        if (method == null) {
+          return Collections.emptyList();
+        }
+        if (method.hasModifierProperty(PsiModifier.PUBLIC)) {
+          if (isMethodValid(method, completionContext, resultQualifiedClassName)) {
+            occurrences += indexValue.getOccurrences();
+            if (myResolveScope.contains(method.getContainingFile().getVirtualFile())) {
+              relevantMethods.add(new ContextRelevantStaticMethod(method, null));
+            }
+            if (occurrences >= minOccurrence) {
+              return relevantMethods;
+            }
+          }
+        }
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  private static List<UsageIndexValue> extractStaticMethods(final TreeSet<UsageIndexValue> indexValues) {
+    final List<UsageIndexValue> relevantStaticMethods = new SmartList<UsageIndexValue>();
+    for (final UsageIndexValue indexValue : indexValues) {
+      if (indexValue.getMethodIncompleteSignature().isStatic()) {
+        relevantStaticMethods.add(indexValue);
+      }
+    }
+    return relevantStaticMethods;
+  }
+
+  private static boolean isMethodValid(final @Nullable PsiMethod method,
+                                       final ChainCompletionContext completionContext,
+                                       final String targetTypeShortName) {
+    if (method == null) return false;
+    for (final PsiParameter parameter : method.getParameterList().getParameters()) {
+      final PsiType type = parameter.getType();
+      final String shortClassName = typeAsString(type);
+      if (targetTypeShortName.equals(shortClassName)) return false;
+      if (!ChainCompletionStringUtil.isShortNamePrimitiveOrArrayOfPrimitives(shortClassName) &&
+          !completionContext.contains(type.getCanonicalText())) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+
+  @Nullable
+  public static String typeAsString(final PsiType type) {
+    if (type instanceof PsiClassType)
+      return ((PsiClassType) type).getClassName();
+    else if (type instanceof PsiPrimitiveType)
+      return type.getCanonicalText();
+    else if (type instanceof PsiArrayType) {
+      final String componentTypeAsString = typeAsString(((PsiArrayType) type).getComponentType());
+      if (componentTypeAsString == null) return null;
+      return String.format("%s[]", componentTypeAsString);
+    }
+    return null;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
new file mode 100644
index 0000000..09e008a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
@@ -0,0 +1,91 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainRelevance implements Comparable<ChainRelevance> {
+  public static final ChainRelevance LOWEST = new ChainRelevance(Integer.MAX_VALUE, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false);
+
+  private final int myChainSize;
+  private final int myLastMethodOccurrences;
+  private final int myUnreachableParametersCount;
+  private final int myNotMatchedStringVars;
+  private final boolean myHasCallingVariableInContext;
+  private final boolean myFirstMethodStatic;
+
+  public ChainRelevance(final int chainSize,
+                        final int lastMethodOccurrences,
+                        final int unreachableParametersCount,
+                        final int notMatchedStringVars,
+                        final boolean hasCallingVariableInContext,
+                        final boolean firstMethodStatic) {
+    myChainSize = chainSize;
+    myLastMethodOccurrences = lastMethodOccurrences;
+    myUnreachableParametersCount = unreachableParametersCount;
+    myNotMatchedStringVars = notMatchedStringVars;
+    myHasCallingVariableInContext = hasCallingVariableInContext;
+    myFirstMethodStatic = firstMethodStatic;
+  }
+
+  @TestOnly
+  public boolean hasCallingVariableInContext() {
+    return myHasCallingVariableInContext;
+  }
+
+  @TestOnly
+  public int getChainSize() {
+    return myChainSize;
+  }
+
+  @TestOnly
+  public int getLastMethodOccurrences() {
+    return myLastMethodOccurrences;
+  }
+
+  @TestOnly
+  public int getUnreachableParametersCount() {
+    return myUnreachableParametersCount;
+  }
+
+  @TestOnly
+  public int getNotMatchedStringVars() {
+    return myNotMatchedStringVars;
+  }
+
+  @TestOnly
+  public boolean isFirstMethodStatic() {
+    return myFirstMethodStatic;
+  }
+
+  @Override
+  public int compareTo(@NotNull final ChainRelevance that) {
+    if (myFirstMethodStatic && !that.myFirstMethodStatic) {
+      return -1;
+    }
+    if (that.myFirstMethodStatic && !myFirstMethodStatic) {
+      return 1;
+    }
+    if (myHasCallingVariableInContext && !that.myHasCallingVariableInContext) {
+      return 1;
+    }
+    if (that.myHasCallingVariableInContext && !myHasCallingVariableInContext) {
+      return -1;
+    }
+    int sub = myLastMethodOccurrences - that.myLastMethodOccurrences;
+    if (sub != 0) return sub;
+    sub = myUnreachableParametersCount - that.myUnreachableParametersCount;
+    if (sub != 0) return -sub;
+    return 0;
+  }
+
+  @Override
+  public String toString() {
+    return (myFirstMethodStatic ? "1" : "0") + 
+           (myHasCallingVariableInContext ? "1" : "0") + "_" + 
+           myLastMethodOccurrences + "_" + 
+           myUnreachableParametersCount;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
new file mode 100644
index 0000000..b47095a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
@@ -0,0 +1,206 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainsSearcher {
+
+  public static List<MethodsChain> search(final MethodChainsSearchService searchService,
+                                          final String targetQName,
+                                          final Set<String> contextQNames,
+                                          final int maxResultSize,
+                                          final int pathMaximalLength,
+                                          final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+                                          final String contextMethodName) {
+    return search(searchService, targetQName, contextQNames, maxResultSize, pathMaximalLength, resolver,
+                  Collections.<String>singleton(targetQName), contextMethodName);
+  }
+
+  public static List<MethodsChain> search(final MethodChainsSearchService searchService,
+                                          final String targetQName,
+                                          final Set<String> contextQNames,
+                                          final int maxResultSize,
+                                          final int pathMaximalLength,
+                                          final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+                                          final Set<String> excludedParamsTypesQNames,
+                                          final String contextMethodName) {
+    final SearchInitializer initializer = createInitializer(targetQName, resolver, searchService, excludedParamsTypesQNames);
+    final ArrayList<MethodsChain> methodsChains = new ArrayList<MethodsChain>(maxResultSize);
+    final MethodsChain firstBestMethodsChain =
+      search(searchService, initializer, contextQNames, Collections.<String>emptySet(), pathMaximalLength, resolver, targetQName,
+             excludedParamsTypesQNames, contextMethodName);
+    if (firstBestMethodsChain != null) {
+      methodsChains.add(firstBestMethodsChain);
+      Set<Set<String>> excludedCombinations = MethodsChain.edgeCombinations(Collections.<Set<String>>emptySet(), firstBestMethodsChain);
+      while (methodsChains.size() <= maxResultSize) {
+        final Set<Set<String>> localExcludedCombinations = excludedCombinations;
+        boolean allLocalsIsNull = true;
+        final int beforeStepChainsCount = methodsChains.size();
+        for (final Set<String> excludedEdges : localExcludedCombinations) {
+          final MethodsChain local =
+            search(searchService, initializer, contextQNames, excludedEdges, pathMaximalLength, resolver, targetQName,
+                   excludedParamsTypesQNames, contextMethodName);
+          if (local != null) {
+            allLocalsIsNull = false;
+          }
+          else {
+            continue;
+          }
+          boolean add = true;
+          for (int i = 0; i < methodsChains.size(); i++) {
+            final MethodsChain chain = methodsChains.get(i);
+            final MethodsChain.CompareResult compareResult = MethodsChain.compare(local, chain);
+            if (compareResult == MethodsChain.CompareResult.EQUAL || compareResult == MethodsChain.CompareResult.RIGHT_CONTAINS_LEFT) {
+              add = false;
+              break;
+            }
+            else if (compareResult == MethodsChain.CompareResult.LEFT_CONTAINS_RIGHT) {
+              methodsChains.set(i, local);
+              add = false;
+              break;
+            }
+          }
+          if (add) {
+            methodsChains.add(local);
+            if (methodsChains.size() >= maxResultSize) {
+              return methodsChains;
+            }
+            excludedCombinations = MethodsChain.edgeCombinations(excludedCombinations, local);
+          }
+        }
+        if (allLocalsIsNull || beforeStepChainsCount == methodsChains.size()) {
+          return methodsChains;
+        }
+      }
+    }
+    return methodsChains;
+  }
+
+  private static SearchInitializer createInitializer(final String targetQName,
+                                                     final FactoryMap<MethodIncompleteSignature, PsiMethod[]> context,
+                                                     final MethodChainsSearchService searchService,
+                                                     final Set<String> excludedParamsTypesQNames) {
+    return new SearchInitializer(searchService.getMethods(targetQName), context, targetQName, excludedParamsTypesQNames);
+  }
+
+  @Nullable
+  private static MethodsChain search(final MethodChainsSearchService searchService,
+                                     final SearchInitializer initializer,
+                                     final Set<String> toSet,
+                                     final Set<String> excludedEdgeNames,
+                                     final int pathMaximalLength,
+                                     final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+                                     final String targetQName,
+                                     final Set<String> excludedParamsTypesQNames,
+                                     final String contextMethodName) {
+    final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName);
+    ProgressManager.checkCanceled();
+    final SearchInitializer.InitResult initResult = initializer.init(excludedEdgeNames, toSet, searchService, contextMethodName);
+    final Map<MethodIncompleteSignature, MethodsChain> knownDistance = initResult.getChains();
+    final PriorityQueue<WeightAware<MethodIncompleteSignature>> q =
+      new PriorityQueue<WeightAware<MethodIncompleteSignature>>(initResult.getVertexes());
+    MethodsChain result = initResult.getCurrentBestTargetChain();
+
+    int maxWeight = 0;
+    for (final MethodsChain methodsChain : knownDistance.values()) {
+      if (methodsChain.getChainWeight() > maxWeight) {
+        maxWeight = methodsChain.getChainWeight();
+      }
+    }
+
+    final WeightAware<MethodIncompleteSignature> maxVertex = q.peek();
+    final int maxDistance;
+    if (maxVertex != null) {
+      maxDistance = maxVertex.getWeight();
+    }
+    else {
+      return null;
+    }
+
+    while (!q.isEmpty()) {
+      final WeightAware<MethodIncompleteSignature> currentVertex = q.poll();
+      final int currentVertexDistance = currentVertex.getWeight();
+      if (currentVertexDistance * Constants.CHAIN_SEARCH_MAGIC_RATIO < maxDistance) {
+        return result;
+      }
+      final MethodIncompleteSignature currentVertexUnderlying = currentVertex.getUnderlying();
+      final MethodsChain currentVertexMethodsChain = knownDistance.get(currentVertexUnderlying);
+      if (currentVertexDistance != currentVertexMethodsChain.getChainWeight()) {
+        continue;
+      }
+      final SortedSet<UsageIndexValue> bigrams = searchService.getBigram(currentVertexUnderlying);
+      int bigramsSumWeight = 0;
+      int maxUpdatedWeight = 0;
+      for (final UsageIndexValue indexValue : bigrams) {
+        final MethodIncompleteSignature vertex = indexValue.getMethodIncompleteSignature();
+        final int occurrences = indexValue.getOccurrences();
+        bigramsSumWeight += occurrences;
+        final boolean canBeResult = vertex.isStatic() || toSet.contains(vertex.getOwner());
+        if (!vertex.getOwner().equals(targetQName) || canBeResult) {
+          final int vertexDistance = Math.min(currentVertexDistance, occurrences);
+          final MethodsChain knownVertexMethodsChain = knownDistance.get(vertex);
+          if ((knownVertexMethodsChain == null || knownVertexMethodsChain.getChainWeight() < vertexDistance) &&
+              (result == null || result.getChainWeight() < vertexDistance)) {
+            if (occurrences * Constants.CHAIN_SEARCH_MAGIC_RATIO >= currentVertexMethodsChain.getChainWeight()) {
+              final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+              final PsiMethod[] psiMethods = resolver.get(methodInvocation);
+
+              if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
+                final MethodsChain newBestMethodsChain = currentVertexMethodsChain.addEdge(psiMethods);
+                if (canBeResult) {
+                  result = newBestMethodsChain;
+                }
+                else if (newBestMethodsChain.size() < pathMaximalLength - 1) {
+                  maxUpdatedWeight = Math.max(maxUpdatedWeight, newBestMethodsChain.getChainWeight());
+                  q.add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(),
+                                                                   newBestMethodsChain.getChainWeight()));
+                }
+                knownDistance.put(vertex, newBestMethodsChain);
+              }
+            }
+            else if (!allExcludedNames.contains(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName()) &&
+                     searchService.isSingleton(currentVertexMethodsChain.getFirstQualifierClass(), contextMethodName) &&
+                     (searchService.isRelevantMethodForNotOverriden(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+                                                                    currentVertexMethodsChain.getOneOfFirst().getName()) ||
+                      searchService.isRelevantMethodForField(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+                                                             currentVertexMethodsChain.getOneOfFirst().getName()))) {
+              result = currentVertexMethodsChain;
+            }
+          }
+        }
+      }
+      //if ((result == null ||  maxUpdatedWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO2 <= bigramsSumWeight)
+      //    && bigramsSumWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO >= currentVertexMethodsChain.getChainWeight()) {
+      //  return currentVertexMethodsChain;
+      //}
+
+      if ((currentVertexMethodsChain.isStaticChain() ||
+           !allExcludedNames.contains(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName())) &&
+          bigramsSumWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO <= currentVertexDistance &&
+          (result == null || result.getChainWeight() < currentVertexDistance) &&
+          (currentVertexMethodsChain.isStaticChain() ||
+           searchService.isSingleton(currentVertexMethodsChain.getFirstQualifierClass(), contextMethodName) &&
+          (searchService.isRelevantMethodForNotOverriden(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+                                                         currentVertexMethodsChain.getOneOfFirst().getName()) ||
+           searchService.isRelevantMethodForField(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+                                                  currentVertexMethodsChain.getOneOfFirst().getName())))) {
+        result = currentVertexMethodsChain;
+      }
+    }
+
+    if (result != null && result.getChainWeight() * Constants.CHAIN_SEARCH_MAGIC_RATIO >= maxWeight) {
+      return result;
+    }
+    return null;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
new file mode 100644
index 0000000..0bc1991
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
@@ -0,0 +1,93 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.compilerOutputIndex.impl.bigram.BigramMethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodNameAndQualifier;
+import com.intellij.codeInsight.completion.methodChains.search.service.OverridenMethodsService;
+import com.intellij.codeInsight.completion.methodChains.search.service.SingletonService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodChainsSearchService {
+  private final static SortedSet EMPTY_SORTED_SET = new TreeSet();
+
+  private final MethodsUsageIndex myMethodsUsageIndex;
+  private final BigramMethodsUsageIndex myBigramMethodsUsageIndex;
+  private final SingletonService mySingletonService;
+  private final OverridenMethodsService myOverridenMethodsService;
+  private final Project myProject;
+  private final Map<String, Boolean> mySingletonLocalCache;
+
+  public MethodChainsSearchService(final Project project) {
+    myOverridenMethodsService = new OverridenMethodsService(project);
+    myMethodsUsageIndex = MethodsUsageIndex.getInstance(project);
+    myBigramMethodsUsageIndex = BigramMethodsUsageIndex.getInstance(project);
+    mySingletonService = new SingletonService(project);
+    myProject = project;
+
+    mySingletonLocalCache = new HashMap<String, Boolean>();
+    mySingletonLocalCache.put(null, false);
+  }
+
+  public Project getProject() {
+    return myProject;
+  }
+
+  @NotNull
+  @SuppressWarnings("unchecked")
+  public SortedSet<UsageIndexValue> getBigram(final MethodIncompleteSignature methodIncompleteSignature) {
+    final TreeSet<UsageIndexValue> value = myBigramMethodsUsageIndex.getValues(methodIncompleteSignature);
+    if (value != null) {
+      return value;
+    }
+    return EMPTY_SORTED_SET;
+  }
+
+  @NotNull
+  @SuppressWarnings("unchecked")
+  public SortedSet<UsageIndexValue> getMethods(final String targetQName) {
+    final TreeSet<UsageIndexValue> value = myMethodsUsageIndex.getValues(targetQName);
+    if (value != null) {
+      return value;
+    }
+    return EMPTY_SORTED_SET;
+  }
+
+  public boolean isSingleton(@NotNull final PsiClass psiClass, final String contextMethodName) {
+    return isSingleton(psiClass.getQualifiedName(), contextMethodName);
+  }
+
+  public boolean isSingleton(@Nullable final String typeQName, final String methodName) {
+    Boolean isSingleton = mySingletonLocalCache.get(typeQName);
+    if (isSingleton == null) {
+      isSingleton = mySingletonService.isSingleton(typeQName, methodName);
+      mySingletonLocalCache.put(typeQName, isSingleton);
+    }
+    return isSingleton;
+  }
+
+  public boolean isRelevantMethodForField(@NotNull final String className, @NotNull final String methodName) {
+    final Pair<Integer, Integer> occurrences =
+      myOverridenMethodsService.getMethodUsageInFieldContext(new MethodNameAndQualifier(methodName, className));
+    return occurrences.getFirst() > occurrences.getSecond();
+  }
+
+  public boolean isRelevantMethodForNotOverriden(@NotNull final String className, @NotNull final String methodName) {
+    final Pair<Integer, Integer> occurrences =
+      myOverridenMethodsService.getMethodsUsageInOverridenContext(new MethodNameAndQualifier(methodName, className));
+    return occurrences.getFirst() < occurrences.getSecond();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
new file mode 100644
index 0000000..ae0df95
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
@@ -0,0 +1,80 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiParameterList;
+import com.intellij.psi.PsiPrimitiveType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class MethodChainsSearchUtil {
+  private MethodChainsSearchUtil() {
+  }
+
+  @Nullable
+  public static PsiMethod getMethodWithMinNotPrimitiveParameters(final @NotNull PsiMethod[] methods,
+                                                                 final Set<String> excludedParamsQNames) {
+    PsiMethod minMethod = null;
+    int minParametersCount = Integer.MAX_VALUE;
+    for (final PsiMethod method : methods) {
+      final PsiParameterList parameterList = method.getParameterList();
+      boolean doContinue = false;
+      int parametersCount = parameterList.getParametersCount();
+      for (final PsiParameter p : parameterList.getParameters()) {
+        if (!(p.getType() instanceof PsiPrimitiveType)) {
+          if (excludedParamsQNames.contains(p.getType().getCanonicalText())) {
+            doContinue = true;
+            break;
+          }
+          parametersCount++;
+        }
+      }
+      if (doContinue) {
+        continue;
+      }
+      if (parametersCount < minParametersCount) {
+        if (parametersCount == 0) {
+          return method;
+        }
+        minParametersCount = parametersCount;
+        minMethod = method;
+      }
+    }
+    return minMethod;
+  }
+
+  public static boolean checkParametersForTypesQNames(final PsiMethod[] psiMethods, final Set<String> excludedTypesQNames) {
+    if (psiMethods.length == 0) {
+      return true;
+    }
+    for (final PsiMethod method : psiMethods) {
+      boolean hasTargetInParams = false;
+      for (final PsiParameter param : method.getParameterList().getParameters()) {
+        final String paramType = param.getType().getCanonicalText();
+        if (excludedTypesQNames.contains(paramType)) {
+          hasTargetInParams = true;
+          break;
+        }
+      }
+      if (!hasTargetInParams) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static <T> HashSet<T> unionToHashSet(final Collection<T> collection, final T... items) {
+    final HashSet<T> result = new HashSet<T>();
+    result.addAll(collection);
+    Collections.addAll(result, items);
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
new file mode 100644
index 0000000..c7f11c3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
@@ -0,0 +1,160 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static com.intellij.util.containers.ContainerUtil.reverse;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChain {
+  private final List<PsiMethod[]> myRevertedPath;
+  private final int myWeight;
+
+  public MethodsChain(final PsiMethod[] methods, final int weight) {
+    this(ContainerUtil.<PsiMethod[]>newArrayList(methods), weight);
+  }
+
+  public MethodsChain(final List<PsiMethod[]> revertedPath, final int weight) {
+    myRevertedPath = revertedPath;
+    myWeight = weight;
+  }
+
+  public int size() {
+    return myRevertedPath.size();
+  }
+
+  public boolean isStaticChain() {
+    return myRevertedPath.get(myRevertedPath.size() - 1)[0].hasModifierProperty(PsiModifier.STATIC);
+  }
+
+  @Nullable
+  public PsiClass getFirstQualifierClass() {
+    return myRevertedPath.isEmpty() ? null : myRevertedPath.get(myRevertedPath.size() - 1)[0].getContainingClass();
+  }
+
+  @Nullable
+  public PsiMethod getOneOfFirst() {
+    return (myRevertedPath.isEmpty() || myRevertedPath.get(0).length == 0) ? null : myRevertedPath.get(myRevertedPath.size() - 1)[0];
+  }
+
+  public List<PsiMethod[]> getPath() {
+    return reverse(myRevertedPath);
+  }
+
+  public int getChainWeight() {
+    return myWeight;
+  }
+
+  public MethodsChain addEdge(final PsiMethod[] psiMethods) {
+    final List<PsiMethod[]> newRevertedPath = new ArrayList<PsiMethod[]>(myRevertedPath.size() + 1);
+    newRevertedPath.addAll(myRevertedPath);
+    newRevertedPath.add(psiMethods);
+    return new MethodsChain(newRevertedPath, myWeight);
+  }
+
+  /**
+   * checking only method names
+   */
+  public boolean weakContains(final MethodsChain otherChain) {
+    if (otherChain.myRevertedPath.isEmpty()) {
+      return true;
+    }
+    if (myRevertedPath.isEmpty()) {
+      return false;
+    }
+    final Iterator<PsiMethod[]> otherChainIterator = otherChain.myRevertedPath.iterator();
+    String otherChainCurrentName = otherChainIterator.next()[0].getName();
+    boolean checkingStarted = false;
+    for (final PsiMethod[] methods : myRevertedPath) {
+      final String thisCurrentName = methods[0].getName();
+      if (!checkingStarted && thisCurrentName.equals(otherChainCurrentName)) {
+        checkingStarted = true;
+      }
+      if (checkingStarted) {
+        if (otherChainIterator.hasNext()) {
+          otherChainCurrentName = otherChainIterator.next()[0].getName();
+          if (!otherChainCurrentName.equals(thisCurrentName)) {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      }
+    }
+    return !otherChainIterator.hasNext();
+  }
+
+  @Override
+  public String toString() {
+    return StringUtil.join(myRevertedPath, "<-");
+  }
+
+  public static Set<Set<String>> edgeCombinations(final Set<Set<String>> oldCombinations,
+                                                  final MethodsChain methodsChain) {
+    if (oldCombinations.isEmpty()) {
+      final Set<Set<String>> result = new HashSet<Set<String>>(methodsChain.myRevertedPath.size());
+      for (final PsiMethod[] e : methodsChain.myRevertedPath) {
+        final Set<String> set = new HashSet<String>();
+        set.add(e[0].getName());
+        result.add(set);
+      }
+      return result;
+    } else {
+      final Set<Set<String>> newTail = new HashSet<Set<String>>(oldCombinations.size() * methodsChain.size());
+      for (final PsiMethod[] e : methodsChain.myRevertedPath) {
+        final String methodName = e[0].getName();
+        for (final Set<String> tailSet : oldCombinations) {
+          final Set<String> newSet = new HashSet<String>(tailSet);
+          newSet.add(methodName);
+          if (!oldCombinations.contains(newSet)) {
+            newTail.add(newSet);
+          }
+        }
+      }
+      return newTail;
+    }
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  public static CompareResult compare(final MethodsChain left, final MethodsChain right) {
+    if (left.size() == 0) {
+      return CompareResult.RIGHT_CONTAINS_LEFT;
+    }
+    if (right.size() == 0) {
+      return CompareResult.LEFT_CONTAINS_RIGHT;
+    }
+    final Iterator<PsiMethod[]> leftIterator = left.myRevertedPath.iterator();
+    final Iterator<PsiMethod[]> rightIterator = right.myRevertedPath.iterator();
+
+    final PsiManager psiManager = PsiManager.getInstance(left.getFirstQualifierClass().getProject());
+    while (leftIterator.hasNext() && rightIterator.hasNext()) {
+      final PsiMethod thisNext = leftIterator.next()[0];
+      final PsiMethod thatNext = rightIterator.next()[0];
+      if (((thisNext.isConstructor() != thatNext.isConstructor()))
+          || !thisNext.getName().equals(thatNext.getName())
+          || !psiManager.areElementsEquivalent(thisNext.getContainingClass(), thatNext.getContainingClass())) {
+        return CompareResult.NOT_EQUAL;
+      }
+    }
+    if (leftIterator.hasNext() && !rightIterator.hasNext()) {
+      return CompareResult.LEFT_CONTAINS_RIGHT;
+    }
+    if (!leftIterator.hasNext() && rightIterator.hasNext()) {
+      return CompareResult.RIGHT_CONTAINS_LEFT;
+    }
+    return CompareResult.EQUAL;
+  }
+
+  public enum CompareResult {
+    LEFT_CONTAINS_RIGHT,
+    RIGHT_CONTAINS_LEFT,
+    EQUAL,
+    NOT_EQUAL
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
new file mode 100644
index 0000000..58a7693
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
@@ -0,0 +1,230 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantVariableGetter;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionNewVariableLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsChainLookupRangingHelper {
+
+  public static List<LookupElement> chainsToWeightableLookupElements(final List<MethodsChain> chains,
+                                                                     final ChainCompletionContext context) {
+    final List<LookupElement> lookupElements = new ArrayList<LookupElement>(chains.size());
+    for (final MethodsChain chain : chains) {
+      final LookupElement lookupElement = chainToWeightableLookupElement(chain, context);
+      if (lookupElement != null) {
+        lookupElements.add(lookupElement);
+      }
+    }
+    return lookupElements;
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  @Nullable
+  private static WeightableChainLookupElement chainToWeightableLookupElement(final MethodsChain chain,
+                                                                             final ChainCompletionContext context) {
+    final int chainSize = chain.size();
+    assert chainSize != 0;
+    final int lastMethodWeight = chain.getChainWeight();
+    int unreachableParametersCount = 0;
+    int notMatchedStringVars = 0;
+    Boolean isFirstMethodStatic = null;
+    Boolean hasCallingVariableInContext = null;
+    LookupElement chainLookupElement = null;
+
+    final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(context.getProject());
+
+    for (final PsiMethod[] psiMethods : chain.getPath()) {
+      final PsiMethod method =
+        MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTargetQName()));
+      if (method == null) {
+        return null;
+      }
+      if (isFirstMethodStatic == null) {
+        isFirstMethodStatic = psiMethods[0].hasModifierProperty(PsiModifier.STATIC);
+      }
+      final MethodProcResult procResult =
+        processMethod(method, context, lastMethodWeight, chainLookupElement == null, nullableNotNullManager);
+      if (procResult == null) {
+        return null;
+      }
+      if (hasCallingVariableInContext == null) {
+        hasCallingVariableInContext = procResult.hasCallingVariableInContext();
+      }
+      unreachableParametersCount += procResult.getUnreachableParametersCount();
+      notMatchedStringVars += procResult.getNotMatchedStringVars();
+      chainLookupElement = chainLookupElement == null
+                           ? procResult.getLookupElement()
+                           : new JavaChainLookupElement(chainLookupElement, procResult.getLookupElement());
+    }
+
+    final ChainRelevance relevance = new ChainRelevance(chainSize,
+                                                        lastMethodWeight,
+                                                        unreachableParametersCount,
+                                                        notMatchedStringVars,
+                                                        hasCallingVariableInContext,
+                                                        isFirstMethodStatic);
+
+    return new WeightableChainLookupElement(chainLookupElement, relevance);
+  }
+
+
+  private static MethodProcResult processMethod(@NotNull final PsiMethod method,
+                                                final ChainCompletionContext context,
+                                                final int weight,
+                                                final boolean isHeadMethod,
+                                                final NullableNotNullManager nullableNotNullManager) {
+    int unreachableParametersCount = 0;
+    int notMatchedStringVars = 0;
+    boolean hasCallingVariableInContext = false;
+    final PsiParameterList parameterList = method.getParameterList();
+    final TIntObjectHashMap<SubLookupElement> parametersMap = new TIntObjectHashMap<SubLookupElement>(parameterList.getParametersCount());
+    final PsiParameter[] parameters = parameterList.getParameters();
+    for (int i = 0; i < parameters.length; i++) {
+      final PsiParameter parameter = parameters[i];
+      final String typeQName = parameter.getType().getCanonicalText();
+      if (typeQName != null) {
+        if (JAVA_LANG_STRING.equals(typeQName)) {
+          final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName());
+          if (relevantStringVar == null) {
+            notMatchedStringVars++;
+          }
+          else {
+            parametersMap.put(i, new VariableSubLookupElement(relevantStringVar));
+          }
+        }
+        else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) {
+          final Collection<PsiVariable> contextVariables = context.getVariables(typeQName);
+          final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null);
+          if (contextVariable != null) {
+            if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable));
+            continue;
+          }
+          final Collection<ContextRelevantVariableGetter> relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName);
+          final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null);
+          if (contextVariableGetter != null) {
+            if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement());
+            continue;
+          }
+          final Collection<PsiMethod> containingClassMethods = context.getContainingClassMethods(typeQName);
+          final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null);
+          if (contextRelevantGetter != null) {
+            if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName()));
+            continue;
+          }
+          final ContextRelevantStaticMethod contextRelevantStaticMethod =
+            ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null);
+          if (contextRelevantStaticMethod != null) {
+            //
+            // In most cases it is not really relevant
+            //
+            //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement());
+            continue;
+          }
+          if (!nullableNotNullManager.isNullable(parameter, true)) {
+            unreachableParametersCount++;
+          }
+        }
+      }
+    }
+    final LookupElement lookupElement;
+    if (isHeadMethod) {
+      if (method.hasModifierProperty(PsiModifier.STATIC)) {
+        lookupElement = createLookupElement(method, parametersMap);
+      }
+      else if (method.isConstructor()) {
+        return null;
+      }
+      else {
+        final PsiClass containingClass = method.getContainingClass();
+        final String classQName = containingClass.getQualifiedName();
+        if (classQName == null) return null;
+        final Object e = ContainerUtil.getFirstItem(context.getContextRefElements(classQName), null);
+        if (e != null) {
+          final LookupElement firstChainElement;
+          if (e instanceof PsiVariable) {
+            hasCallingVariableInContext = true;
+            firstChainElement = new VariableLookupItem((PsiVariable)e);
+          }
+          else if (e instanceof PsiMethod) {
+            firstChainElement = createLookupElement((PsiMethod)e, null);
+          }
+          else if (e instanceof LookupElement) {
+            firstChainElement = (LookupElement)e;
+          }
+          else {
+            throw new AssertionError();
+          }
+          lookupElement = new JavaChainLookupElement(firstChainElement, createLookupElement(method, parametersMap));
+        }
+        else lookupElement = context.getContainingClassQNames().contains(classQName)
+                             ? createLookupElement(method, parametersMap)
+                             : new JavaChainLookupElement(ChainCompletionNewVariableLookupElement.create(containingClass),
+                                                          createLookupElement(method, parametersMap));
+      }
+    }
+    else {
+      lookupElement = createLookupElement(method, parametersMap);
+    }
+    return new MethodProcResult(lookupElement, unreachableParametersCount, notMatchedStringVars, hasCallingVariableInContext);
+  }
+
+  private static class MethodProcResult {
+    private final LookupElement myMethodLookup;
+    private final int myUnreachableParametersCount;
+    private final int myNotMatchedStringVars;
+    private final boolean myHasCallingVariableInContext;
+
+    private MethodProcResult(final LookupElement methodLookup,
+                             final int unreachableParametersCount,
+                             final int notMatchedStringVars,
+                             final boolean hasCallingVariableInContext) {
+      myMethodLookup = methodLookup;
+      myUnreachableParametersCount = unreachableParametersCount;
+      myNotMatchedStringVars = notMatchedStringVars;
+      myHasCallingVariableInContext = hasCallingVariableInContext;
+    }
+
+    private boolean hasCallingVariableInContext() {
+      return myHasCallingVariableInContext;
+    }
+
+    private LookupElement getLookupElement() {
+      return myMethodLookup;
+    }
+
+    private int getUnreachableParametersCount() {
+      return myUnreachableParametersCount;
+    }
+
+    private int getNotMatchedStringVars() {
+      return myNotMatchedStringVars;
+    }
+  }
+}
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
new file mode 100644
index 0000000..1f98313
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
@@ -0,0 +1,128 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class SearchInitializer {
+  private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
+  private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
+  private final Map<MethodIncompleteSignature, Integer> myOccurrencesMap;
+  private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myResolver;
+
+  public SearchInitializer(final SortedSet<UsageIndexValue> indexValues,
+                           final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+                           final String targetQName,
+                           final Set<String> excludedParamsTypesQNames) {
+    myResolver = resolver;
+    final int size = indexValues.size();
+    myVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
+    myChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
+    myOccurrencesMap = new HashMap<MethodIncompleteSignature, Integer>(size);
+    add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName));
+  }
+
+  private void add(final Collection<UsageIndexValue> indexValues, final Set<String> excludedParamsTypesQNames) {
+    int bestOccurrences = -1;
+    for (final UsageIndexValue indexValue : indexValues) {
+      if (add(indexValue, excludedParamsTypesQNames)) {
+        final int occurrences = indexValue.getOccurrences();
+        if (bestOccurrences == -1) {
+          bestOccurrences = occurrences;
+        } else if (bestOccurrences > occurrences * Constants.CHAIN_SEARCH_MAGIC_RATIO) {
+          return;
+        }
+      }
+    }
+  }
+
+  private boolean add(final UsageIndexValue indexValue, final Set<String> excludedParamsTypesQNames) {
+    final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+    final PsiMethod[] psiMethods = myResolver.get(methodInvocation);
+    if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, excludedParamsTypesQNames)) {
+      final int occurrences = indexValue.getOccurrences();
+      final MethodsChain methodsChain = new MethodsChain(psiMethods, occurrences);
+      myChains.put(methodInvocation, methodsChain);
+      myVertexes.add(new WeightAware<MethodIncompleteSignature>(methodInvocation, occurrences));
+      myOccurrencesMap.put(methodInvocation, occurrences);
+      return true;
+    }
+    return false;
+  }
+
+  public InitResult init(final Set<String> excludedEdgeNames,
+                         final Set<String> contextQNames,
+                         final MethodChainsSearchService searchService,
+                         final String contextMethodName) {
+    final int size = myVertexes.size();
+    int bestOccurrences = 0;
+    MethodsChain bestTargetMethodChain = null;
+    final List<WeightAware<MethodIncompleteSignature>> initedVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
+    final LinkedHashMap<MethodIncompleteSignature, MethodsChain> initedChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
+    final Iterator<Map.Entry<MethodIncompleteSignature, MethodsChain>> chainsIterator = myChains.entrySet().iterator();
+    for (final WeightAware<MethodIncompleteSignature> vertex : myVertexes) {
+      final Map.Entry<MethodIncompleteSignature, MethodsChain> chainEntry = chainsIterator.next();
+      final MethodIncompleteSignature method = vertex.getUnderlying();
+      if (!excludedEdgeNames.contains(method.getName())) {
+        initedVertexes.add(vertex);
+        final MethodsChain methodsChain = chainEntry.getValue();
+        initedChains.put(chainEntry.getKey(), methodsChain);
+        if (contextQNames.contains(method.getOwner())) {
+          final Integer occurrences = myOccurrencesMap.get(method);
+          if (occurrences > bestOccurrences) {
+            final PsiMethod oneOfFirst = methodsChain.getOneOfFirst();
+            if (oneOfFirst != null && oneOfFirst.hasModifierProperty(PsiModifier.STATIC)) {
+              bestTargetMethodChain = methodsChain;
+              bestOccurrences = occurrences;
+              continue;
+            }
+            final PsiClass firstQualifierClass = methodsChain.getFirstQualifierClass();
+            if (firstQualifierClass != null && (searchService.isSingleton(firstQualifierClass, contextMethodName)
+                || contextQNames.contains(firstQualifierClass.getQualifiedName()))) {
+              bestTargetMethodChain = methodsChain;
+              bestOccurrences = occurrences;
+            }
+          }
+        }
+      }
+    }
+    return new InitResult(initedVertexes, initedChains, bestTargetMethodChain);
+  }
+
+  public static class InitResult {
+    private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
+    private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
+    private final MethodsChain myCurrentBestTargetChain;
+
+    private InitResult(final List<WeightAware<MethodIncompleteSignature>> vertexes,
+                       final LinkedHashMap<MethodIncompleteSignature, MethodsChain> chains,
+                       final @Nullable MethodsChain currentBestTargetChain) {
+      this.myVertexes = vertexes;
+      this.myChains = chains;
+      this.myCurrentBestTargetChain = currentBestTargetChain;
+    }
+
+    public List<WeightAware<MethodIncompleteSignature>> getVertexes() {
+      return myVertexes;
+    }
+
+    public LinkedHashMap<MethodIncompleteSignature, MethodsChain> getChains() {
+      return myChains;
+    }
+
+    @Nullable
+    public MethodsChain getCurrentBestTargetChain() {
+      return myCurrentBestTargetChain;
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
new file mode 100644
index 0000000..617053d
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
@@ -0,0 +1,29 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class WeightAware<V> implements Comparable<WeightAware<V>> {
+  private final V myUnderlying;
+  private final int myWeight;
+
+  public WeightAware(final V underlying, final int weight) {
+    myUnderlying = underlying;
+    myWeight = weight;
+  }
+
+  public V getUnderlying() {
+    return myUnderlying;
+  }
+
+  public int getWeight() {
+    return myWeight;
+  }
+
+  @Override
+  public int compareTo(@NotNull final WeightAware<V> that) {
+    return -getWeight() + that.getWeight();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java
new file mode 100644
index 0000000..f310a46
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java
@@ -0,0 +1,65 @@
+package com.intellij.codeInsight.completion.methodChains.search.service;
+
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.callingLocation.CallingLocation;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodCallingLocationIndex;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodNameAndQualifier;
+import com.intellij.compilerOutputIndex.impl.callingLocation.VariableType;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickInheritanceIndex;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickMethodsIndex;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickOverrideUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class OverridenMethodsService {
+
+  private final QuickMethodsIndex myQuickMethodsIndex;
+  private final QuickInheritanceIndex myQuickInheritanceIndex;
+  private final MethodCallingLocationIndex myMethodCallingLocationIndex;
+
+  public OverridenMethodsService(final Project project) {
+    myQuickInheritanceIndex = QuickInheritanceIndex.getInstance(project);
+    myQuickMethodsIndex = QuickMethodsIndex.getInstance(project);
+    myMethodCallingLocationIndex = MethodCallingLocationIndex.getInstance(project);
+  }
+
+  public boolean isMethodOverriden(final String classQName, final String methodName) {
+    return QuickOverrideUtil.isMethodOverriden(classQName, methodName, myQuickInheritanceIndex, myQuickMethodsIndex);
+  }
+
+  public Pair<Integer, Integer> getMethodsUsageInOverridenContext(final MethodNameAndQualifier method) {
+    final Multiset<MethodIncompleteSignature> locationsAsParam = myMethodCallingLocationIndex.getLocationsAsParam(method);
+    int overridenOccurrences = 0;
+    int nonOverridenOccurrences = 0;
+    for (final Multiset.Entry<MethodIncompleteSignature> e : locationsAsParam.entrySet()) {
+      final MethodIncompleteSignature sign = e.getElement();
+      final boolean methodOverriden = isMethodOverriden(sign.getOwner(), sign.getName());
+      if (methodOverriden) {
+        overridenOccurrences++;
+      }
+      else {
+        nonOverridenOccurrences++;
+      }
+    }
+
+    return Pair.create(overridenOccurrences, nonOverridenOccurrences);
+  }
+
+  public Pair<Integer, Integer> getMethodUsageInFieldContext(final MethodNameAndQualifier method) {
+    int asField = 0;
+    int notField = 0;
+    for (final CallingLocation callingLocation : myMethodCallingLocationIndex.getAllLocations(method)) {
+      if (callingLocation.getVariableType().equals(VariableType.FIELD)) {
+        asField++;
+      }
+      else {
+        notField++;
+      }
+    }
+    return Pair.create(asField, notField);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java
new file mode 100644
index 0000000..4f27ad2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java
@@ -0,0 +1,89 @@
+package com.intellij.codeInsight.completion.methodChains.search.service;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.singleton.MethodShortSignatureWithWeight;
+import com.intellij.compilerOutputIndex.impl.singleton.ParamsInMethodOccurrencesIndex;
+import com.intellij.compilerOutputIndex.impl.singleton.TwinVariablesIndex;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class SingletonService {
+  private final TwinVariablesIndex myTwinVariablesIndex;
+  private final ParamsInMethodOccurrencesIndex myParamsInMethodOccurrencesIndex;
+  private final GlobalSearchScope myAllScope;
+  private final JavaPsiFacade myJavaPsiFacade;
+
+  private final Map<String, Boolean> myLocalCache;
+
+  public SingletonService(final Project project) {
+    myTwinVariablesIndex = TwinVariablesIndex.getInstance(project);
+    myParamsInMethodOccurrencesIndex = ParamsInMethodOccurrencesIndex.getInstance(project);
+    myAllScope = GlobalSearchScope.allScope(project);
+    myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+
+    myLocalCache =  new HashMap<String, Boolean>();
+    myLocalCache.put(null, false);
+  }
+
+  public boolean isSingleton(@Nullable final String typeQName, final @NotNull String contextMethodName) {
+    final Boolean isSingletonCached = myLocalCache.get(typeQName);
+    if (isSingletonCached == null) {
+      assert typeQName != null;
+      final PsiClass aClass = myJavaPsiFacade.findClass(typeQName, myAllScope);
+      if (aClass == null) {
+        myLocalCache.put(typeQName, false);
+        return false;
+      }
+      for (final PsiClass psiClass : aClass.getInterfaces()) {
+        final String qualifiedName = psiClass.getQualifiedName();
+        if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName) || !isSingleton(qualifiedName, contextMethodName)) {
+          myLocalCache.put(typeQName, false);
+          return false;
+        }
+      }
+      final boolean isSingleton = hasTwinsFeature(typeQName) && isSuitableTypeFor(typeQName, contextMethodName);
+      myLocalCache.put(typeQName, isSingleton);
+      return isSingleton;
+    }
+    return isSingletonCached;
+  }
+
+  public boolean hasTwinsFeature(final String typeQName) {
+    final List<Integer> twinInfo = myTwinVariablesIndex.getTwinInfo(typeQName);
+    if (twinInfo.isEmpty()) {
+      return false;
+    }
+    int ones = 0;
+    for (final int i : twinInfo) {
+      if (i == 1) {
+        ones++;
+      }
+    }
+    return (twinInfo.size() - ones) * Constants.SINGLETON_MAGIC_RATIO < twinInfo.size();
+  }
+
+  private boolean isSuitableTypeFor(final String typeName, final String methodName) {
+    final Pair<List<MethodShortSignatureWithWeight>, Integer> parameterOccurrences =
+      myParamsInMethodOccurrencesIndex.getParameterOccurrences(typeName);
+    if (parameterOccurrences.getSecond() == 0) {
+      return true;
+    }
+    final List<MethodShortSignatureWithWeight> contextMethods = parameterOccurrences.getFirst();
+    final MethodShortSignatureWithWeight last = contextMethods.get(contextMethods.size() - 1);
+    return last.getMethodShortSignature().getName().equals(methodName) || last.getWeight() * Constants.SINGLETON_MAGIC_RATIO2 <= parameterOccurrences.getSecond();
+  }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
index 16fad58..2ec4c48 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
@@ -95,8 +95,7 @@
         }
       }
       else if (qualifier != null) {
-        myQualifierType = qualifier.getType();
-        myQualifierClass = PsiUtil.resolveClassInType(myQualifierType);
+        setQualifierType(qualifier.getType());
         if (myQualifierType == null && qualifier instanceof PsiJavaCodeReferenceElement) {
           final PsiElement target = ((PsiJavaCodeReferenceElement)qualifier).resolve();
           if (target instanceof PsiClass) {
@@ -256,6 +255,11 @@
     return false;
   }
 
+  public void setQualifierType(@Nullable PsiType qualifierType) {
+    myQualifierType = qualifierType;
+    myQualifierClass = PsiUtil.resolveClassInClassTypeOnly(qualifierType);
+  }
+
   @Nullable
   public PsiType getQualifierType() {
     return myQualifierType;
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 43a7037..10de8bf 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
@@ -27,8 +27,7 @@
 import com.intellij.codeInsight.intention.EmptyIntentionAction;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInsight.intention.IntentionManager;
-import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.*;
 import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
 import com.intellij.codeInspection.ex.InspectionManagerEx;
 import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
@@ -36,8 +35,8 @@
 import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
 import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
 import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
+import com.intellij.diagnostic.AttachmentFactory;
 import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
 import com.intellij.find.FindManager;
 import com.intellij.find.findUsages.*;
 import com.intellij.find.impl.FindManagerImpl;
@@ -83,6 +82,8 @@
 
 import java.util.*;
 
+import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*;
+
 public class PostHighlightingPass extends TextEditorHighlightingPass {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
   private RefCountHolder myRefCountHolder;
@@ -211,7 +212,7 @@
           String afterText = file.getText();
           if (Comparing.strEqual(beforeText, afterText)) {
             LOG.error(LogMessageEx.createEvent("Import optimizer  hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
-                                               new Attachment(file.getViewProvider().getVirtualFile())));
+                                               AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
           }
         }
       }
@@ -312,7 +313,7 @@
       return processField((PsiField)parent, identifier, progress, helper);
     }
     if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
-      if (InspectionManagerEx.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
+      if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
       return processParameter((PsiParameter)parent, identifier, progress);
     }
     if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
@@ -499,10 +500,11 @@
         if (UnusedSymbolLocalInspection.isInjected(method)) return null;
         HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
         if (highlightInfo != null) {
-          final ArrayList<IntentionAction> options = new ArrayList<IntentionAction>();
+          List<IntentionAction> options = new ArrayList<IntentionAction>();
           options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile));
           if (myUnusedParametersInspection != null) {
-            Collections.addAll(options, myUnusedParametersInspection.getSuppressActions(parameter));
+            SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter);
+            Collections.addAll(options, SuppressManagerImpl.convertBatchToSuppressIntentionActions(batchSuppressActions));
           }
           //need suppress from Unused Parameters but settings from Unused Symbol
           QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter),
@@ -623,16 +625,28 @@
         useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
       }
 
-      PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(project).isCheapEnoughToSearch(name, (GlobalSearchScope)useScope,
-                                                                                                                        helper.isCurrentFileAlreadyChecked() ? member.getContainingFile() : null,
-                                                                                                                        progress);
-      if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
+      PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
+      PsiFile file = member.getContainingFile();
+      PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null;
+      PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
+      if (cheapEnough == TOO_MANY_OCCURRENCES) return false;
 
       //search usages if it cheap
       //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
-      if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
+      if (cheapEnough == ZERO_OCCURRENCES) {
         if (!canBeReferencedViaWeirdNames(member)) return true;
       }
+
+      if (member instanceof PsiMethod) {
+        String propertyName = PropertyUtil.getPropertyName(member);
+        if (propertyName != null && file != null) {
+          SearchScope fileScope = file.getUseScope();
+          if (fileScope instanceof GlobalSearchScope &&
+              searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) {
+            return false;
+          }
+        }
+      }
     }
     FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
     FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java
deleted file mode 100644
index a473bef..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.daemon.impl;
-
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.SuppressManager;
-import com.intellij.codeInspection.SuppressionUtil;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.javadoc.PsiDocComment;
-import com.intellij.psi.javadoc.PsiDocTag;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class RemoveSuppressWarningAction implements LocalQuickFix {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction");
-
-  private final String myID;
-  private final String myProblemLine;
-
-  public RemoveSuppressWarningAction(final String ID, final String problemLine) {
-    myID = ID;
-    myProblemLine = problemLine;
-  }
-
-  public RemoveSuppressWarningAction(String id) {
-    final int idx = id.indexOf(";");
-    if (idx > -1) {
-      myID = id.substring(0, idx);
-      myProblemLine = id.substring(idx);
-    }
-    else {
-      myID = id;
-      myProblemLine = null;
-    }
-  }
-
-  @Override
-  @NotNull
-  public String getFamilyName() {
-    return QuickFixBundle.message("remove.suppression.action.family");
-  }
-
-  @Override
-  public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
-    PsiElement element = descriptor.getPsiElement();
-    try {
-      if (element instanceof PsiIdentifier) {
-        if (!FileModificationService.getInstance().prepareFileForWrite(element.getContainingFile())) return;
-        final PsiIdentifier identifier = (PsiIdentifier)element;
-        final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(identifier, PsiDocCommentOwner.class);
-        if (commentOwner != null) {
-          final PsiElement psiElement = SuppressManager.getInstance().getElementMemberSuppressedIn(commentOwner, myID);
-          if (psiElement instanceof PsiAnnotation) {
-            removeFromAnnotation((PsiAnnotation)psiElement);
-          } else if (psiElement instanceof PsiDocComment) {
-            removeFromJavaDoc((PsiDocComment)psiElement);
-          } else { //try to remove from all comments
-            final Set<PsiComment> comments = new HashSet<PsiComment>();
-            commentOwner.accept(new PsiRecursiveElementWalkingVisitor() {
-              @Override public void visitComment(final PsiComment comment) {
-                super.visitComment(comment);
-                if (comment.getText().contains(myID)) {
-                  comments.add(comment);
-                }
-              }
-            });
-            for (PsiComment comment : comments) {
-              try {
-                removeFromComment(comment, comments.size() > 1);
-              }
-              catch (IncorrectOperationException e) {
-                LOG.error(e);
-              }
-            }
-          }
-        }
-      }
-    }
-    catch (IncorrectOperationException e) {
-      LOG.error(e);
-    }
-  }
-
-  @Override
-  @NotNull
-  public String getName() {
-    return QuickFixBundle.message("remove.suppression.action.name", myID);
-  }
-
-  private void removeFromComment(final PsiComment comment, final boolean checkLine) throws IncorrectOperationException {
-    if (checkLine) {
-      final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(comment, PsiStatement.class);
-      if (statement != null && !Comparing.strEqual(statement.getText(), myProblemLine)) return;
-    }
-    String newText = removeFromElementText(comment);
-    if (newText != null) {
-      if (newText.length() == 0) {
-        comment.delete();
-      }
-      else {
-        PsiComment newComment = JavaPsiFacade.getInstance(comment.getProject()).getElementFactory()
-          .createCommentFromText("// " + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME+" "+newText, comment);
-        comment.replace(newComment);
-      }
-    }
-  }
-
-  private void removeFromJavaDoc(PsiDocComment docComment) throws IncorrectOperationException {
-    PsiDocTag tag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
-    if (tag == null) return;
-    String newText = removeFromElementText(tag.getDataElements());
-    if (newText != null && newText.length() == 0) {
-      tag.delete();
-    }
-    else if (newText != null) {
-      newText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + newText;
-      PsiDocTag newTag = JavaPsiFacade.getInstance(tag.getProject()).getElementFactory().createDocTagFromText(newText);
-      tag.replace(newTag);
-    }
-  }
-
-  @Nullable
-  private String removeFromElementText(final PsiElement... elements) {
-    String text = "";
-    for (PsiElement element : elements) {
-      text += StringUtil.trimStart(element.getText(), "//").trim();
-    }
-    text = StringUtil.trimStart(text, "@").trim();
-    text = StringUtil.trimStart(text, SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME).trim();
-    List<String> ids = StringUtil.split(text, ",");
-    int i = ArrayUtil.find(ids.toArray(), myID);
-    if (i==-1) return null;
-    ids.remove(i);
-    return StringUtil.join(ids, ",");
-  }
-
-  private void removeFromAnnotation(final PsiAnnotation annotation) throws IncorrectOperationException {
-    PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
-    for (PsiNameValuePair attribute : attributes) {
-      PsiAnnotationMemberValue value = attribute.getValue();
-      if (value instanceof PsiArrayInitializerMemberValue) {
-        PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers();
-        for (PsiAnnotationMemberValue initializer : initializers) {
-          if (removeFromValue(annotation, initializer, initializers.length==1)) return;
-        }
-      }
-      if (removeFromValue(annotation, value, attributes.length==1)) return;
-    }
-  }
-
-  private boolean removeFromValue(final PsiAnnotationMemberValue parent, final PsiAnnotationMemberValue value, final boolean removeParent) throws IncorrectOperationException {
-    String text = value.getText();
-    text = StringUtil.trimStart(text, "\"");
-    text = StringUtil.trimEnd(text, "\"");
-    if (myID.equals(text)) {
-      if (removeParent) {
-        parent.delete();
-      }
-      else {
-        value.delete();
-      }
-      return true;
-    }
-    return false;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
index b1cbfe0..6c97236 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
@@ -27,6 +27,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.patterns.ElementPattern;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.PsiClassReferenceType;
@@ -295,7 +296,7 @@
   );
 
   @Nullable
-  public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation) {
+  public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
     if (ANY_ANNOTATION_ALLOWED.accepts(annotation)) {
       return null;
     }
@@ -311,7 +312,7 @@
     }
 
     if (!(owner instanceof PsiModifierList)) {
-      HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation);
+      HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation, languageLevel,containingFile);
       if (info != null) return info;
     }
 
@@ -465,23 +466,23 @@
     LOG.assertTrue(aClass.isAnnotationType());
     PsiType type = typeElement.getType();
     final Set<PsiClass> checked = new HashSet<PsiClass>();
-    if (cyclicDependencies(aClass, type, checked)) {
+    if (cyclicDependencies(aClass, type, checked, aClass.getManager())) {
       String description = JavaErrorMessages.message("annotation.cyclic.element.type");
       return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create();
     }
     return null;
   }
 
-  private static boolean cyclicDependencies(PsiClass aClass, PsiType type, Set<PsiClass> checked) {
+  private static boolean cyclicDependencies(PsiClass aClass, PsiType type, @NotNull Set<PsiClass> checked,@NotNull PsiManager manager) {
     final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
     if (resolvedClass != null && resolvedClass.isAnnotationType()) {
       if (aClass == resolvedClass) {
         return true;
       }
-      if (!checked.add(resolvedClass) || !resolvedClass.getManager().isInProject(resolvedClass)) return false;
+      if (!checked.add(resolvedClass) || !manager.isInProject(resolvedClass)) return false;
       final PsiMethod[] methods = resolvedClass.getMethods();
       for (PsiMethod method : methods) {
-        if (cyclicDependencies(aClass, method.getReturnType(), checked)) return true;
+        if (cyclicDependencies(aClass, method.getReturnType(), checked,manager)) return true;
       }
     }
     return false;
@@ -572,10 +573,10 @@
   }
 
   @Nullable
-  public static HighlightInfo checkFunctionalInterface(PsiAnnotation annotation) {
-    final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation);
+  public static HighlightInfo checkFunctionalInterface(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel) {
+    final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation, languageLevel);
     if (errorMessage != null) {
-      return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create();
+      return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(annotation).descriptionAndTooltip(errorMessage).create();
     }
     return null;
   }
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 48e10ee..55990a6 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
@@ -68,7 +68,7 @@
       for (PsiClassType type : extendsTypes) {
         PsiType extendsType = substitutor.substitute(type);
         if (substituted instanceof PsiWildcardType) {
-          if (!((PsiWildcardType)substituted).isExtends()) {
+          if (((PsiWildcardType)substituted).isSuper()) {
             continue;
           }
           final PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
@@ -110,17 +110,19 @@
   @Nullable
   public static HighlightInfo checkParameterizedReferenceTypeArguments(final PsiElement resolved,
                                                                        final PsiJavaCodeReferenceElement referenceElement,
-                                                                       final PsiSubstitutor substitutor) {
+                                                                       final PsiSubstitutor substitutor,
+                                                                       @NotNull JavaSdkVersion javaSdkVersion) {
     if (!(resolved instanceof PsiTypeParameterListOwner)) return null;
     final PsiTypeParameterListOwner typeParameterListOwner = (PsiTypeParameterListOwner)resolved;
-    return checkReferenceTypeArgumentList(typeParameterListOwner, referenceElement.getParameterList(), substitutor, true);
+    return checkReferenceTypeArgumentList(typeParameterListOwner, referenceElement.getParameterList(), substitutor, true, javaSdkVersion);
   }
 
   @Nullable
   public static HighlightInfo checkReferenceTypeArgumentList(final PsiTypeParameterListOwner typeParameterListOwner,
                                                              final PsiReferenceParameterList referenceParameterList,
                                                              final PsiSubstitutor substitutor,
-                                                             boolean registerIntentions) {
+                                                             boolean registerIntentions,
+                                                             @NotNull JavaSdkVersion javaSdkVersion) {
     PsiDiamondType.DiamondInferenceResult inferenceResult = null;
     PsiTypeElement[] referenceElements = null;
     if (referenceParameterList != null) {
@@ -150,7 +152,7 @@
       if (targetParametersNum == 0) {
         if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
             typeParameterListOwner instanceof PsiMethod &&
-            JavaVersionService.getInstance().isAtLeast(referenceParameterList, JavaSdkVersion.JDK_1_7)) {
+            javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) {
           description = null;
         }
         else {
@@ -388,7 +390,8 @@
   public static HighlightInfo checkElementInTypeParameterExtendsList(@NotNull PsiReferenceList referenceList,
                                                                      @NotNull PsiClass aClass,
                                                                      @NotNull JavaResolveResult resolveResult,
-                                                                     @NotNull PsiElement element) {
+                                                                     @NotNull PsiElement element,
+                                                                     @NotNull LanguageLevel languageLevel) {
     final PsiJavaCodeReferenceElement[] referenceElements = referenceList.getReferenceElements();
     PsiClass extendFrom = (PsiClass)resolveResult.getElement();
     if (extendFrom == null) return null;
@@ -408,7 +411,7 @@
       IntentionAction fix = QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false);
       QuickFixAction.registerQuickFixAction(errorResult, fix, null);
     }
-    if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
+    if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
         referenceElements.length > 1) {
       //todo suppress erased methods which come from the same class
       return checkOverrideEquivalentMethods(aClass);
@@ -736,7 +739,7 @@
 
   //http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
   @Nullable
-  public static HighlightInfo checkAccessStaticFieldFromEnumConstructor(PsiReferenceExpression expr, JavaResolveResult result) {
+  public static HighlightInfo checkAccessStaticFieldFromEnumConstructor(@NotNull PsiReferenceExpression expr, @NotNull JavaResolveResult result) {
     final PsiElement resolved = result.getElement();
 
     if (!(resolved instanceof PsiField)) return null;
@@ -806,10 +809,10 @@
   }
 
   @Nullable
-  public static HighlightInfo checkTypeParametersList(PsiTypeParameterList parameterList) {
+  public static HighlightInfo checkTypeParametersList(PsiTypeParameterList parameterList, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
     PsiTypeParameter[] typeParameters = parameterList.getTypeParameters();
     if (typeParameters.length == 0) return null;
-    HighlightInfo info = HighlightUtil.checkGenericsFeature(parameterList, typeParameters.length);
+    HighlightInfo info = HighlightUtil.checkGenericsFeature(parameterList, typeParameters.length, languageLevel, containingFile);
     if (info != null) return info;
 
     final PsiElement parent = parameterList.getParent();
@@ -839,7 +842,7 @@
           return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeParameter2).descriptionAndTooltip(message).create();
         }
       }
-      if (!JavaVersionService.getInstance().isAtLeast(parameterList, JavaSdkVersion.JDK_1_7)) {
+      if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
         for (PsiJavaCodeReferenceElement referenceElement : typeParameter1.getExtendsList().getReferenceElements()) {
           final PsiElement resolve = referenceElement.resolve();
           if (resolve instanceof PsiTypeParameter && ArrayUtilRt.find(typeParameters, resolve) > i) {
@@ -941,7 +944,7 @@
   }
 
   @Nullable
-  public static HighlightInfo checkOverrideAnnotation(PsiMethod method) {
+  public static HighlightInfo checkOverrideAnnotation(PsiMethod method, final LanguageLevel languageLevel) {
     PsiModifierList list = method.getModifierList();
     final PsiAnnotation overrideAnnotation = list.findAnnotation("java.lang.Override");
     if (overrideAnnotation == null) {
@@ -962,7 +965,6 @@
         PullAsAbstractUpFix.registerQuickFix(highlightInfo, method);
         return highlightInfo;
       }
-      LanguageLevel languageLevel = PsiUtil.getLanguageLevel(method);
       PsiClass superClass = superMethod.getMethod().getContainingClass();
       if (languageLevel.equals(LanguageLevel.JDK_1_5) &&
           superClass != null &&
@@ -1023,7 +1025,9 @@
     }
   }
 
-  static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant, final HighlightInfoHolder holder) {
+  static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant,
+                                                      final HighlightInfoHolder holder,
+                                                      @NotNull JavaSdkVersion javaSdkVersion) {
     PsiClass containingClass = enumConstant.getContainingClass();
     if (enumConstant.getInitializingClass() == null) {
       HighlightInfo highlightInfo = HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, enumConstant.getNameIdentifier());
@@ -1040,7 +1044,7 @@
     }
     PsiClassType type = JavaPsiFacade.getInstance(holder.getProject()).getElementFactory().createType(containingClass);
 
-    HighlightMethodUtil.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, holder);
+    HighlightMethodUtil.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, holder, javaSdkVersion);
   }
 
   @Nullable
@@ -1061,12 +1065,12 @@
   }
 
   @Nullable
-  public static HighlightInfo checkVarArgParameterIsLast(PsiParameter parameter) {
+  public static HighlightInfo checkVarArgParameterIsLast(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
     PsiElement declarationScope = parameter.getDeclarationScope();
     if (declarationScope instanceof PsiMethod) {
       PsiParameter[] params = ((PsiMethod)declarationScope).getParameterList().getParameters();
       if (parameter.isVarArgs()) {
-        HighlightInfo info = HighlightUtil.checkVarargFeature(parameter);
+        HighlightInfo info = HighlightUtil.checkVarargFeature(parameter, languageLevel,containingFile);
         if (info != null) return info;
 
         if (params[params.length - 1] != parameter) {
@@ -1097,8 +1101,9 @@
   }
 
   @Nullable
-  public static HighlightInfo checkParametersAllowed(PsiReferenceParameterList refParamList) {
-    HighlightInfo info = HighlightUtil.checkGenericsFeature(refParamList, refParamList.getTypeParameterElements().length);
+  public static HighlightInfo checkParametersAllowed(PsiReferenceParameterList refParamList, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    HighlightInfo info = HighlightUtil.checkGenericsFeature(refParamList, refParamList.getTypeParameterElements().length,
+                                                            languageLevel, containingFile);
     if (info != null) return info;
 
     if (refParamList.getTextLength() != 0) {
@@ -1148,7 +1153,7 @@
           if (qualifier instanceof PsiReferenceExpression){
             final PsiClass typeParameter = PsiUtil.resolveClassInType(((PsiReferenceExpression)qualifier).getType());
             if (typeParameter instanceof PsiTypeParameter) {
-              if (JavaVersionService.getInstance().isAtLeast(element, JavaSdkVersion.JDK_1_7)) return null;
+              if (JavaVersionService.getInstance().isAtLeast(containingClass, JavaSdkVersion.JDK_1_7)) return null;
               for (PsiClassType classType : typeParameter.getExtendsListTypes()) {
                 final PsiClass resolve = classType.resolve();
                 if (resolve != 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 ae32b61..449df8e 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
@@ -377,7 +377,7 @@
       .parent(PsiMatchers.hasClass(PsiModifierList.class))
       .parent(PsiMatchers.hasClass(parentClass))
       .parent(PsiMatchers.hasClass(PsiClass.class))
-      .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false))
+      .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, false))
       .parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class))
       .getElement();
   }
@@ -387,9 +387,9 @@
     // keyword points to 'class' or 'interface' or 'enum'
     if (new PsiMatcherImpl(keyword)
       .parent(PsiMatchers.hasClass(PsiClass.class))
-      .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, true))
+      .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, true))
       .parent(PsiMatchers.hasClass(PsiClass.class))
-      .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false))
+      .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, false))
       .parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class))
       .getElement() == null) {
       return null;
@@ -626,7 +626,7 @@
   }
 
   @Nullable
-  public static HighlightInfo checkExtendsDuplicate(PsiJavaCodeReferenceElement element, PsiElement resolved) {
+  public static HighlightInfo checkExtendsDuplicate(PsiJavaCodeReferenceElement element, PsiElement resolved, @NotNull PsiFile containingFile) {
     if (!(element.getParent() instanceof PsiReferenceList)) return null;
     PsiReferenceList list = (PsiReferenceList)element.getParent();
     if (!(list.getParent() instanceof PsiClass)) return null;
@@ -634,9 +634,10 @@
     PsiClass aClass = (PsiClass)resolved;
     PsiClassType[] referencedTypes = list.getReferencedTypes();
     int dupCount = 0;
+    PsiManager manager = containingFile.getManager();
     for (PsiClassType referencedType : referencedTypes) {
       PsiClass resolvedElement = referencedType.resolve();
-      if (resolvedElement != null && list.getManager().areElementsEquivalent(resolvedElement, aClass)) {
+      if (resolvedElement != null && manager.areElementsEquivalent(resolvedElement, aClass)) {
         dupCount++;
       }
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 5a0f156..f74f6f9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -29,8 +29,6 @@
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.PsiMatcherImpl;
-import com.intellij.psi.util.PsiMatchers;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Processor;
@@ -141,7 +139,7 @@
       for (PsiMethod constructor : constructors) {
         PsiCodeBlock ctrBody = constructor.getBody();
         if (ctrBody == null) return false;
-        final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+        final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
         for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
           PsiMethod redirectedConstructor = redirectedConstructors.get(j);
           final PsiCodeBlock body = redirectedConstructor.getBody();
@@ -170,21 +168,9 @@
     return false;
   }
 
-  /**
-   * return all constructors which are referred from this constructor by
-   *  this (...) at the beginning of the constructor body
-   * @return referring constructor
-   */
-  @Nullable public static List<PsiMethod> getChainedConstructors(PsiMethod constructor) {
-    final ConstructorVisitorInfo info = new ConstructorVisitorInfo();
-    visitConstructorChain(constructor, info);
-    if (info.visitedConstructors != null) info.visitedConstructors.remove(constructor);
-    return info.visitedConstructors;
-  }
-
   public static boolean isRecursivelyCalledConstructor(PsiMethod constructor) {
-    final ConstructorVisitorInfo info = new ConstructorVisitorInfo();
-    visitConstructorChain(constructor, info);
+    final JavaHighlightUtil.ConstructorVisitorInfo info = new JavaHighlightUtil.ConstructorVisitorInfo();
+    JavaHighlightUtil.visitConstructorChain(constructor, info);
     if (info.recursivelyCalledConstructor == null) return false;
     // our constructor is reached from some other constructor by constructor chain
     return info.visitedConstructors.indexOf(info.recursivelyCalledConstructor) <=
@@ -214,42 +200,6 @@
     }
   }
 
-  private static class ConstructorVisitorInfo {
-    List<PsiMethod> visitedConstructors;
-    PsiMethod recursivelyCalledConstructor;
-  }
-
-  private static void visitConstructorChain(PsiMethod constructor, ConstructorVisitorInfo info) {
-    while (true) {
-      if (constructor == null) return;
-      final PsiCodeBlock body = constructor.getBody();
-      if (body == null) return;
-      final PsiStatement[] statements = body.getStatements();
-      if (statements.length == 0) return;
-      final PsiStatement statement = statements[0];
-      final PsiElement element = new PsiMatcherImpl(statement)
-          .dot(PsiMatchers.hasClass(PsiExpressionStatement.class))
-          .firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
-          .firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
-          .firstChild(PsiMatchers.hasClass(PsiKeyword.class))
-          .dot(PsiMatchers.hasText(PsiKeyword.THIS))
-          .parent(null)
-          .parent(null)
-          .getElement();
-      if (element == null) return;
-      PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
-      PsiMethod method = methodCall.resolveMethod();
-      if (method == null) return;
-      if (info.visitedConstructors != null && info.visitedConstructors.contains(method)) {
-        info.recursivelyCalledConstructor = method;
-        return;
-      }
-      if (info.visitedConstructors == null) info.visitedConstructors = new ArrayList<PsiMethod>(5);
-      info.visitedConstructors.add(method);
-      constructor = method;
-    }
-  }
-
   /**
    * see JLS chapter 16
    * @return true if variable assigned (maybe more than once)
@@ -298,7 +248,7 @@
   @Nullable
   public static HighlightInfo checkVariableInitializedBeforeUsage(PsiReferenceExpression expression,
                                                                   PsiVariable variable,
-                                                                  Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems) {
+                                                                  Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems, @NotNull PsiFile containingFile) {
     if (variable instanceof ImplicitVariable) return null;
     if (!PsiUtil.isAccessedForReading(expression)) return null;
     final int startOffset = expression.getTextRange().getStartOffset();
@@ -326,18 +276,18 @@
           return null;
         }
         // access to final fields from inner classes always allowed
-        if (inInnerClass(expression, ((PsiField)variable).getContainingClass())) return null;
+        if (inInnerClass(expression, ((PsiField)variable).getContainingClass(),containingFile)) return null;
         if (topBlock == null) return null;
         final PsiElement parent = topBlock.getParent();
         final PsiCodeBlock block;
         final PsiClass aClass;
         if (parent instanceof PsiMethod) {
           PsiMethod constructor = (PsiMethod)parent;
-          if (!parent.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
+          if (!containingFile.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
           // static variables already initialized in class initializers
           if (variable.hasModifierProperty(PsiModifier.STATIC)) return null;
           // as a last chance, field may be initialized in this() call
-          final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+          final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
           for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
             PsiMethod redirectedConstructor = redirectedConstructors.get(j);
             // variable must be initialized before its usage
@@ -353,7 +303,7 @@
         }
         else if (parent instanceof PsiClassInitializer) {
           final PsiClassInitializer classInitializer = (PsiClassInitializer)parent;
-          if (!parent.getManager().areElementsEquivalent(classInitializer.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
+          if (!containingFile.getManager().areElementsEquivalent(classInitializer.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
           block = classInitializer.getBody();
           aClass = classInitializer.getContainingClass();
         }
@@ -377,7 +327,7 @@
               return null;
             }
             // as a last chance, field may be initialized in this() call
-            final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+            final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
             for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
               PsiMethod redirectedConstructor = redirectedConstructors.get(j);
               // variable must be initialized before its usage
@@ -435,9 +385,9 @@
     return null;
   }
 
-  private static boolean inInnerClass(PsiElement element, PsiClass containingClass) {
+  private static boolean inInnerClass(PsiElement element, PsiClass containingClass, @NotNull PsiFile containingFile) {
     while (element != null) {
-      if (element instanceof PsiClass) return !element.getManager().areElementsEquivalent(element, containingClass);
+      if (element instanceof PsiClass) return !containingFile.getManager().areElementsEquivalent(element, containingClass);
       element = element.getParent();
     }
     return false;
@@ -536,7 +486,7 @@
         final PsiMethod ctr = codeBlock.getParent() instanceof PsiMethod ?
                               (PsiMethod)codeBlock.getParent() : null;
         // assignment to final field in several constructors threatens us only if these are linked (there is this() call in the beginning)
-        final List<PsiMethod> redirectedConstructors = ctr != null && ctr.isConstructor() ? getChainedConstructors(ctr) : null;
+        final List<PsiMethod> redirectedConstructors = ctr != null && ctr.isConstructor() ? JavaHighlightUtil.getChainedConstructors(ctr) : null;
         for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
           PsiMethod redirectedConstructor = redirectedConstructors.get(j);
           if (redirectedConstructor.getBody() != null &&
@@ -593,7 +543,7 @@
 
 
   @Nullable
-  public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression) {
+  public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression, @NotNull PsiFile containingFile) {
     PsiReferenceExpression reference = null;
     if (expression instanceof PsiAssignmentExpression) {
       final PsiExpression left = ((PsiAssignmentExpression)expression).getLExpression();
@@ -618,7 +568,7 @@
     final PsiElement resolved = reference == null ? null : reference.resolve();
     PsiVariable variable = resolved instanceof PsiVariable ? (PsiVariable)resolved : null;
     if (variable == null || !variable.hasModifierProperty(PsiModifier.FINAL)) return null;
-    if (!canWriteToFinal(variable, expression, reference)) {
+    if (!canWriteToFinal(variable, expression, reference,containingFile)) {
       final String name = variable.getName();
       String description = JavaErrorMessages.message("assignment.to.final.variable", name);
       final HighlightInfo highlightInfo =
@@ -637,7 +587,7 @@
     return null;
   }
 
-  private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference) {
+  private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference, @NotNull PsiFile containingFile) {
     if (variable.hasInitializer()) return false;
     if (variable instanceof PsiParameter) return false;
     PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression);
@@ -646,9 +596,9 @@
       if (HighlightUtil.findEnclosingFieldInitializer(expression) != null) return true;
       // assignment from within inner class is illegal always
       PsiField field = (PsiField)variable;
-      if (innerClass != null && !innerClass.getManager().areElementsEquivalent(innerClass, field.getContainingClass())) return false;
+      if (innerClass != null && !containingFile.getManager().areElementsEquivalent(innerClass, field.getContainingClass())) return false;
       final PsiMember enclosingCtrOrInitializer = PsiUtil.findEnclosingConstructorOrInitializer(expression);
-      return enclosingCtrOrInitializer != null && isSameField(variable, enclosingCtrOrInitializer, field, reference);
+      return enclosingCtrOrInitializer != null && isSameField(variable, enclosingCtrOrInitializer, field, reference,containingFile);
     }
     if (variable instanceof PsiLocalVariable) {
       boolean isAccessedFromOtherClass = innerClass != null;
@@ -662,16 +612,18 @@
   private static boolean isSameField(final PsiVariable variable,
                                      final PsiMember enclosingCtrOrInitializer,
                                      final PsiField field,
-                                     final PsiReferenceExpression reference) {
+                                     final PsiReferenceExpression reference, @NotNull PsiFile containingFile) {
 
-    if (!variable.getManager().areElementsEquivalent(enclosingCtrOrInitializer.getContainingClass(), field.getContainingClass())) return false;
+    if (!containingFile.getManager().areElementsEquivalent(enclosingCtrOrInitializer.getContainingClass(), field.getContainingClass())) return false;
     PsiExpression qualifierExpression = reference.getQualifierExpression();
     return qualifierExpression == null || qualifierExpression instanceof PsiThisExpression;
   }
 
 
   @Nullable
-  static HighlightInfo checkVariableMustBeFinal(PsiVariable variable, PsiJavaCodeReferenceElement context) {
+  static HighlightInfo checkVariableMustBeFinal(PsiVariable variable,
+                                                PsiJavaCodeReferenceElement context,
+                                                @NotNull LanguageLevel languageLevel) {
     if (variable.hasModifierProperty(PsiModifier.FINAL)) return null;
     final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context);
     if (innerClass != null) {
@@ -682,8 +634,7 @@
           return null;
         }
       }
-      if (PsiUtil.getLanguageLevel(variable).isAtLeast(LanguageLevel.JDK_1_8) &&
-          isEffectivelyFinal(variable, innerClass, context)) {
+      if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && isEffectivelyFinal(variable, innerClass, context)) {
         return null;
       }
       final String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
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 2d1a4db..9631960 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
@@ -26,9 +26,11 @@
 import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.IndexNotReadyException;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.infos.CandidateInfo;
 import com.intellij.psi.infos.MethodCandidateInfo;
@@ -312,7 +314,10 @@
   }
 
   @Nullable
-  static HighlightInfo checkMethodCall(PsiMethodCallExpression methodCall, PsiResolveHelper resolveHelper) {
+  static HighlightInfo checkMethodCall(@NotNull PsiMethodCallExpression methodCall,
+                                       @NotNull PsiResolveHelper resolveHelper,
+                                       @NotNull LanguageLevel languageLevel,
+                                       @NotNull JavaSdkVersion javaSdkVersion) {
     PsiExpressionList list = methodCall.getArgumentList();
     PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
     JavaResolveResult[] results = referenceToMethod.multiResolve(true);
@@ -327,7 +332,7 @@
     if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
       TextRange fixRange = getFixRange(methodCall);
       highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
-      if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression())) {
+      if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), languageLevel)) {
         highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
       }
     }
@@ -364,7 +369,7 @@
             highlightInfo = GenericsHighlightUtil.checkInferredTypeArguments(resolvedMethod, methodCall, substitutor);
           }
           else {
-            highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, substitutor);
+            highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, substitutor, javaSdkVersion);
           }
         }
       }
@@ -384,7 +389,8 @@
       }
     }
     if (highlightInfo == null) {
-      highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor);
+      highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor,
+                                                                                     javaSdkVersion);
     }
     return highlightInfo;
   }
@@ -860,7 +866,7 @@
   }
 
   @Nullable
-  static HighlightInfo checkMethodCanHaveBody(PsiMethod method) {
+  static HighlightInfo checkMethodCanHaveBody(PsiMethod method, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
     PsiClass aClass = method.getContainingClass();
     boolean hasNoBody = method.getBody() == null;
     boolean isInterface = aClass != null && aClass.isInterface();
@@ -887,7 +893,7 @@
         }
       }
       else if (isExtension) {
-        return HighlightUtil.checkExtensionMethodsFeature(method);
+        return HighlightUtil.checkExtensionMethodsFeature(method, languageLevel,containingFile);
       }
     }
     else if (isExtension) {
@@ -983,7 +989,7 @@
    * @return error if static method overrides instance method or
    *         instance method overrides static. see JLS 8.4.6.1, 8.4.6.2
    */
-  static HighlightInfo checkStaticMethodOverride(PsiMethod method) {
+  static HighlightInfo checkStaticMethodOverride(@NotNull PsiMethod method,@NotNull PsiFile containingFile) {
     // constructors are not members and therefor don't override class methods
     if (method.isConstructor()) {
       return null;
@@ -997,7 +1003,7 @@
                             : MethodSignatureUtil.findMethodBySignature(superClass, method, true);
 
     boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC);
-    HighlightInfo highlightInfo = checkStaticMethodOverride(aClass, method, isStatic,superClass, superMethod);
+    HighlightInfo highlightInfo = checkStaticMethodOverride(aClass, method, isStatic,superClass, superMethod,containingFile);
     if (highlightInfo != null) return highlightInfo;
     if (!isStatic) {
       // all methods in interface are instance, so no possible errors in this case
@@ -1007,15 +1013,15 @@
     for (PsiClass aInterfaces : interfaces) {
         superClass = aInterfaces;
         superMethod = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(aClass, superClass, method.getSignature(PsiSubstitutor.EMPTY), true);
-        highlightInfo = checkStaticMethodOverride(aClass, method, true, superClass, superMethod);
+        highlightInfo = checkStaticMethodOverride(aClass, method, true, superClass, superMethod,containingFile);
         if (highlightInfo != null) return highlightInfo;
       }
     return null;
   }
 
-  private static HighlightInfo checkStaticMethodOverride(PsiClass aClass, PsiMethod method, boolean isMethodStatic, PsiClass superClass, PsiMethod superMethod) {
+  private static HighlightInfo checkStaticMethodOverride(PsiClass aClass, PsiMethod method, boolean isMethodStatic, PsiClass superClass, PsiMethod superMethod,@NotNull PsiFile containingFile) {
     if (superMethod == null) return null;
-    PsiManager manager = superMethod.getManager();
+    PsiManager manager = containingFile.getManager();
     PsiModifierList superModifierList = superMethod.getModifierList();
     PsiModifierList modifierList = method.getModifierList();
     if (superModifierList.hasModifierProperty(PsiModifier.PRIVATE)) return null;
@@ -1208,7 +1214,7 @@
   }
 
 
-  static void checkNewExpression(@NotNull PsiNewExpression expression, @NotNull HighlightInfoHolder holder) {
+  static void checkNewExpression(@NotNull PsiNewExpression expression, @NotNull HighlightInfoHolder holder, @NotNull JavaSdkVersion javaSdkVersion) {
     PsiType type = expression.getType();
     if (!(type instanceof PsiClassType)) return;
     PsiClassType.ClassResolveResult typeResult = ((PsiClassType)type).resolveGenerics();
@@ -1222,15 +1228,16 @@
     }
 
     PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
-    checkConstructorCall(typeResult, expression, type, classReference, holder);
+    checkConstructorCall(typeResult, expression, type, classReference, holder, javaSdkVersion);
   }
 
 
   public static void checkConstructorCall(PsiClassType.ClassResolveResult typeResolveResult,
-                                                   PsiConstructorCall constructorCall,
-                                                   PsiType type,
-                                                   PsiJavaCodeReferenceElement classReference,
-                                                   final HighlightInfoHolder holder) {
+                                          PsiConstructorCall constructorCall,
+                                          PsiType type,
+                                          PsiJavaCodeReferenceElement classReference,
+                                          final HighlightInfoHolder holder,
+                                          @NotNull JavaSdkVersion javaSdkVersion) {
     PsiExpressionList list = constructorCall.getArgumentList();
     if (list == null) return;
     PsiClass aClass = typeResolveResult.getElement();
@@ -1343,12 +1350,10 @@
         }
         else {
           if (constructorCall instanceof PsiNewExpression) {
-            HighlightInfo highlightInfo = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor,
-                                                                                               ((PsiNewExpression)constructorCall)
-                                                                                                 .getTypeArgumentList(),
-                                                                                               result.getSubstitutor(), false);
-            if (highlightInfo != null) {
-              holder.add(highlightInfo);
+            PsiReferenceParameterList typeArgumentList = ((PsiNewExpression)constructorCall).getTypeArgumentList();
+            HighlightInfo info = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor(), false, javaSdkVersion);
+            if (info != null) {
+              holder.add(info);
             }
           }
         }
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 dc8aaa9..a8c041e 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
@@ -28,6 +28,7 @@
 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;
@@ -51,14 +52,14 @@
   public static HighlightInfo highlightMethodName(@NotNull PsiMethod method,
                                                   final PsiElement elementToHighlight,
                                                   final boolean isDeclaration,
-                                                  @NotNull EditorColorsScheme colorsScheme) {
+                                                  @NotNull TextAttributesScheme colorsScheme) {
     return highlightMethodName(method, elementToHighlight, elementToHighlight.getTextRange(), colorsScheme, isDeclaration);
   }
 
   @Nullable
   public static HighlightInfo highlightMethodName(@NotNull PsiMethod method,
                                                   final PsiElement elementToHighlight,
-                                                  TextRange range, @NotNull EditorColorsScheme colorsScheme, final boolean isDeclaration) {
+                                                  TextRange range, @NotNull TextAttributesScheme colorsScheme, final boolean isDeclaration) {
     boolean isInherited = false;
 
     if (!isDeclaration) {
@@ -93,7 +94,7 @@
 
   private static TextAttributes mergeWithScopeAttributes(final PsiElement element,
                                                          @NotNull HighlightInfoType type,
-                                                         @NotNull EditorColorsScheme colorsScheme) {
+                                                         @NotNull TextAttributesScheme colorsScheme) {
     TextAttributes regularAttributes = HighlightInfo.getAttributesByType(element, type, colorsScheme);
     if (element == null) return regularAttributes;
     TextAttributes scopeAttributes = getScopeAttributes(element, colorsScheme);
@@ -101,7 +102,7 @@
   }
 
   @Nullable
-  public static HighlightInfo highlightClassName(PsiClass aClass, PsiElement elementToHighlight, @NotNull EditorColorsScheme colorsScheme) {
+  public static HighlightInfo highlightClassName(PsiClass aClass, PsiElement elementToHighlight, @NotNull TextAttributesScheme colorsScheme) {
     HighlightInfoType type = getClassNameHighlightType(aClass, elementToHighlight);
     if (elementToHighlight != null) {
       TextAttributes attributes = mergeWithScopeAttributes(aClass, type, colorsScheme);
@@ -136,7 +137,7 @@
   @Nullable
   public static HighlightInfo highlightVariableName(final PsiVariable variable,
                                                     final PsiElement elementToHighlight,
-                                                    @NotNull EditorColorsScheme colorsScheme) {
+                                                    @NotNull TextAttributesScheme colorsScheme) {
     HighlightInfoType varType = getVariableNameHighlightType(variable);
     if (varType != null) {
       if (variable instanceof PsiField) {
@@ -154,7 +155,7 @@
 
   @Nullable
   public static HighlightInfo highlightClassNameInQualifier(final PsiJavaCodeReferenceElement element,
-                                                            @NotNull EditorColorsScheme colorsScheme) {
+                                                            @NotNull TextAttributesScheme colorsScheme) {
     PsiExpression qualifierExpression = null;
     if (element instanceof PsiReferenceExpression) {
       qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression();
@@ -228,7 +229,7 @@
     return null;
   }
 
-  private static TextAttributes getScopeAttributes(@NotNull PsiElement element, @NotNull EditorColorsScheme colorsScheme) {
+  private static TextAttributes getScopeAttributes(@NotNull PsiElement element, @NotNull TextAttributesScheme colorsScheme) {
     PsiFile file = element.getContainingFile();
     if (file == null) return null;
     TextAttributes result = null;
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 e7b3d6b..3181bed 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
@@ -34,7 +34,6 @@
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaVersionService;
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Condition;
@@ -46,7 +45,9 @@
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
+import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
 import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl;
+import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.jsp.JspFile;
 import com.intellij.psi.scope.processor.VariablesNotProcessor;
@@ -336,7 +337,7 @@
 
 
   @Nullable
-  static HighlightInfo checkAssignmentOperatorApplicable(@NotNull PsiAssignmentExpression assignment) {
+  static HighlightInfo checkAssignmentOperatorApplicable(@NotNull PsiAssignmentExpression assignment,@NotNull PsiFile containingFile) {
     PsiJavaToken operationSign = assignment.getOperationSign();
     IElementType eqOpSign = operationSign.getTokenType();
     IElementType opSign = TypeConversionUtil.convertEQtoOperation(eqOpSign);
@@ -347,7 +348,7 @@
     final PsiType rType = rExpression.getType();
     HighlightInfo errorResult = null;
     if (!TypeConversionUtil.isBinaryOperatorApplicable(opSign, lType, rType, true) ||
-        PsiType.getJavaLangObject(assignment.getManager(), assignment.getResolveScope()).equals(lType)) {
+        PsiType.getJavaLangObject(containingFile.getManager(), assignment.getResolveScope()).equals(lType)) {
       String operatorText = operationSign.getText().substring(0, operationSign.getText().length() - 1);
       String message = JavaErrorMessages.message("binary.operator.not.applicable", operatorText,
                                                  JavaHighlightUtil.formatType(lType),
@@ -621,6 +622,22 @@
     return null;
   }
 
+  @Nullable
+  public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable) {
+    if ("_".equals(variable.getName()) && PsiUtil.isLanguageLevel8OrHigher(variable)) {
+      if (variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) {
+        String message = JavaErrorMessages.message("underscore.lambda.identifier");
+        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create();
+      }
+      else {
+        String message = JavaErrorMessages.message("underscore.identifier");
+        return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create();
+      }
+    }
+
+    return null;
+  }
+
   @NotNull
   public static String formatClass(@NotNull PsiClass aClass) {
     return formatClass(aClass, true);
@@ -845,7 +862,8 @@
   }
 
   @Nullable
-  public static HighlightInfo checkLiteralExpressionParsingError(@NotNull final PsiLiteralExpression expression) {
+  public static HighlightInfo checkLiteralExpressionParsingError(@NotNull final PsiLiteralExpression expression,
+                                                                 @NotNull LanguageLevel languageLevel, @NotNull PsiFile containingFile) {
     PsiElement literal = expression.getFirstChild();
     assert literal instanceof PsiJavaToken : literal;
     IElementType type = ((PsiJavaToken)literal).getTokenType();
@@ -860,19 +878,19 @@
 
     if (isFP) {
       if (text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX)) {
-        final HighlightInfo info = checkFeature(expression, Feature.HEX_FP_LITERALS);
+        final HighlightInfo info = checkFeature(expression, Feature.HEX_FP_LITERALS, languageLevel, containingFile);
         if (info != null) return info;
       }
     }
     if (isInt) {
       if (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX)) {
-        final HighlightInfo info = checkFeature(expression, Feature.BIN_LITERALS);
+        final HighlightInfo info = checkFeature(expression, Feature.BIN_LITERALS, languageLevel, containingFile);
         if (info != null) return info;
       }
     }
     if (isInt || isFP) {
       if (text.contains("_")) {
-        HighlightInfo info = checkFeature(expression, Feature.UNDERSCORES);
+        HighlightInfo info = checkFeature(expression, Feature.UNDERSCORES, languageLevel, containingFile);
         if (info != null) return info;
         info = checkUnderscores(expression, text, isInt);
         if (info != null) return info;
@@ -1176,7 +1194,7 @@
 
   @Nullable
   static Collection<HighlightInfo> checkWithImprovedCatchAnalysis(@NotNull final PsiParameter parameter,
-                                                                  @NotNull final Collection<PsiClassType> thrownInTryStatement) {
+                                                                  @NotNull final Collection<PsiClassType> thrownInTryStatement,@NotNull PsiFile containingFile) {
     final PsiElement scope = parameter.getDeclarationScope();
     if (!(scope instanceof PsiCatchSection)) return null;
 
@@ -1186,8 +1204,10 @@
     if (idx <= 0) return null;
 
     final Collection<PsiClassType> thrownTypes = ContainerUtil.newHashSet(thrownInTryStatement);
-    thrownTypes.add(PsiType.getJavaLangError(parameter.getManager(), parameter.getResolveScope()));
-    thrownTypes.add(PsiType.getJavaLangRuntimeException(parameter.getManager(), parameter.getResolveScope()));
+    PsiManager manager = containingFile.getManager();
+    GlobalSearchScope parameterResolveScope = parameter.getResolveScope();
+    thrownTypes.add(PsiType.getJavaLangError(manager, parameterResolveScope));
+    thrownTypes.add(PsiType.getJavaLangRuntimeException(manager, parameterResolveScope));
     final Collection<HighlightInfo> result = ContainerUtil.newArrayList();
 
     final List<PsiTypeElement> parameterTypeElements = PsiUtil.getParameterTypeElements(parameter);
@@ -1805,7 +1825,9 @@
   }
 
   @Nullable
-  public static HighlightInfo checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression, PsiElement resolved) {
+  public static HighlightInfo checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression,
+                                                                           PsiElement resolved,
+                                                                           @NotNull PsiFile containingFile) {
     PsiClass referencedClass;
     @NonNls String resolvedName;
     PsiType type;
@@ -1903,13 +1925,14 @@
       return null;
     }
     if (referencedClass == null) return null;
-    return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName);
+    return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName, containingFile);
   }
 
   @Nullable
   private static HighlightInfo checkReferenceToOurInstanceInsideThisOrSuper(@NotNull final PsiElement expression,
                                                                             @NotNull PsiClass referencedClass,
-                                                                            final String resolvedName) {
+                                                                            final String resolvedName,
+                                                                            @NotNull PsiFile containingFile) {
     if (PsiTreeUtil.getParentOfType(expression, PsiReferenceParameterList.class) != null) return null;
     PsiElement element = expression.getParent();
     while (element != null) {
@@ -1919,7 +1942,7 @@
           .parent(PsiMatchers.hasClass(PsiExpressionStatement.class))
           .parent(PsiMatchers.hasClass(PsiCodeBlock.class))
           .parent(PsiMatchers.hasClass(PsiMethod.class))
-          .dot(PsiMatchers.isConstructor(true))
+          .dot(JavaMatchers.isConstructor(true))
           .parent(PsiMatchers.hasClass(PsiClass.class))
           .getElement();
         if (parentClass == null) {
@@ -1958,7 +1981,16 @@
       }
 
       if (element instanceof PsiReferenceExpression) {
-        final PsiElement resolve = ((PsiReferenceExpression)element).resolve();
+        final PsiElement resolve;
+        if (element instanceof PsiReferenceExpressionImpl) {
+          PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)element;
+          JavaResolveResult[] results = JavaResolveUtil
+            .resolveWithContainingFile(referenceExpression, PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, false, containingFile);
+          resolve = results.length == 1 ? results[0].getElement() : null;
+        }
+        else {
+          resolve = ((PsiReferenceExpression)element).resolve();
+        }
         if (resolve instanceof PsiField && ((PsiField)resolve).hasModifierProperty(PsiModifier.STATIC)) {
           return null;
         }
@@ -1976,8 +2008,8 @@
   }
 
   @Nullable
-  public static HighlightInfo checkImplicitThisReferenceBeforeSuper(@NotNull PsiClass aClass) {
-    if (JavaVersionService.getInstance().isAtLeast(aClass, JavaSdkVersion.JDK_1_7)) return null;
+  public static HighlightInfo checkImplicitThisReferenceBeforeSuper(@NotNull PsiClass aClass, @NotNull JavaSdkVersion javaSdkVersion) {
+    if (javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) return null;
     if (aClass instanceof PsiAnonymousClass || aClass instanceof PsiTypeParameter) return null;
     PsiClass superClass = aClass.getSuperClass();
     if (superClass == null || !PsiUtil.isInnerClass(superClass)) return null;
@@ -2205,13 +2237,13 @@
 
 
   @Nullable
-  public static HighlightInfo checkSynchronizedExpressionType(@NotNull PsiExpression expression, @Nullable PsiType type) {
+  public static HighlightInfo checkSynchronizedExpressionType(@NotNull PsiExpression expression, @Nullable PsiType type,@NotNull PsiFile containingFile) {
     if (type == null) return null;
     if (expression.getParent() instanceof PsiSynchronizedStatement) {
       PsiSynchronizedStatement synchronizedStatement = (PsiSynchronizedStatement)expression.getParent();
       if (expression == synchronizedStatement.getLockExpression() &&
           (type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type))) {
-        PsiClassType objectType = PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
+        PsiClassType objectType = PsiType.getJavaLangObject(containingFile.getManager(), expression.getResolveScope());
         return createIncompatibleTypeHighlightInfo(objectType, type, expression.getTextRange(), 0);
       }
     }
@@ -2308,14 +2340,14 @@
 
   @Nullable
   public static HighlightInfo checkSingleImportClassConflict(@NotNull PsiImportStatement statement,
-                                                             @NotNull Map<String, Pair<PsiImportStaticReferenceElement, PsiClass>> importedClasses) {
+                                                             @NotNull Map<String, Pair<PsiImportStaticReferenceElement, PsiClass>> importedClasses,@NotNull PsiFile containingFile) {
     if (statement.isOnDemand()) return null;
     PsiElement element = statement.resolve();
     if (element instanceof PsiClass) {
       String name = ((PsiClass)element).getName();
       Pair<PsiImportStaticReferenceElement, PsiClass> imported = importedClasses.get(name);
       PsiClass importedClass = imported == null ? null : imported.getSecond();
-      if (importedClass != null && !element.getManager().areElementsEquivalent(importedClass, element)) {
+      if (importedClass != null && !containingFile.getManager().areElementsEquivalent(importedClass, element)) {
         String description = JavaErrorMessages.message("single.import.class.conflict", formatClass(importedClass));
         return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create();
       }
@@ -2378,13 +2410,16 @@
 
 
   @Nullable
-  static HighlightInfo checkReference(@NotNull final PsiJavaCodeReferenceElement ref, @NotNull final JavaResolveResult result) {
+  static HighlightInfo checkReference(@NotNull final PsiJavaCodeReferenceElement ref,
+                                      @NotNull final JavaResolveResult result,
+                                      @NotNull PsiFile containingFile,
+                                      @NotNull LanguageLevel languageLevel) {
     final PsiElement refName = ref.getReferenceNameElement();
 
     if (!(refName instanceof PsiIdentifier) && !(refName instanceof PsiKeyword)) return null;
     final PsiElement resolved = result.getElement();
 
-    HighlightInfo highlightInfo = checkMemberReferencedBeforeConstructorCalled(ref, resolved);
+    HighlightInfo highlightInfo = checkMemberReferencedBeforeConstructorCalled(ref, resolved, containingFile);
     if (highlightInfo != null) return highlightInfo;
 
     PsiElement refParent = ref.getParent();
@@ -2454,7 +2489,8 @@
       }
     }
     if ((resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) && !(resolved instanceof ImplicitVariable)) {
-      highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref);
+      highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref,
+                                                                        languageLevel);
     }
     else if (resolved instanceof PsiClass) {
       if (Comparing.strEqual(((PsiClass)resolved).getQualifiedName(), ((PsiClass)resolved).getName())) {
@@ -2508,7 +2544,8 @@
   @Nullable
   static HighlightInfo checkElementInReferenceList(@NotNull PsiJavaCodeReferenceElement ref,
                                                    @NotNull PsiReferenceList referenceList,
-                                                   @NotNull JavaResolveResult resolveResult) {
+                                                   @NotNull JavaResolveResult resolveResult,
+                                                   @NotNull LanguageLevel languageLevel) {
     PsiElement resolved = resolveResult.getElement();
     HighlightInfo highlightInfo = null;
     PsiElement refGrandParent = referenceList.getParent();
@@ -2516,7 +2553,7 @@
       PsiClass aClass = (PsiClass)resolved;
       if (refGrandParent instanceof PsiClass) {
         if (refGrandParent instanceof PsiTypeParameter) {
-          highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref);
+          highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref, languageLevel);
         }
         else {
           highlightInfo = HighlightClassUtil.checkExtendsClassAndImplementsInterface(referenceList, resolveResult, ref);
@@ -2630,8 +2667,11 @@
   }
 
   @Nullable
-  private static HighlightInfo checkFeature(@Nullable final PsiElement element, @NotNull final Feature feature) {
-    if (element != null && element.getManager().isInProject(element) && !PsiUtil.getLanguageLevel(element).isAtLeast(feature.level)) {
+  private static HighlightInfo checkFeature(@NotNull final PsiElement element,
+                                            @NotNull Feature feature,
+                                            @NotNull LanguageLevel languageLevel,
+                                            @NotNull PsiFile containingFile) {
+    if (containingFile.getManager().isInProject(containingFile) && !languageLevel.isAtLeast(feature.level)) {
       String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key));
       HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create();
       QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(feature.level));
@@ -2643,62 +2683,69 @@
   }
 
   @Nullable
-  public static HighlightInfo checkGenericsFeature(PsiElement parameterList, int listSize) {
-    return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS) : null;
+  public static HighlightInfo checkGenericsFeature(@NotNull PsiElement parameterList,
+                                                   int listSize,
+                                                   @NotNull LanguageLevel languageLevel,
+                                                   @NotNull PsiFile containingFile) {
+    return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS, languageLevel, containingFile) : null;
   }
 
   @Nullable
-  public static HighlightInfo checkAnnotationFeature(PsiElement element) {
-    return checkFeature(element, Feature.ANNOTATIONS);
+  public static HighlightInfo checkAnnotationFeature(@NotNull PsiElement element,
+                                                     @NotNull LanguageLevel languageLevel,
+                                                     @NotNull PsiFile containingFile) {
+    return checkFeature(element, Feature.ANNOTATIONS, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkForEachFeature(PsiForeachStatement statement) {
-    return checkFeature(statement, Feature.FOR_EACH);
+  public static HighlightInfo checkForEachFeature(@NotNull PsiForeachStatement statement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(statement, Feature.FOR_EACH, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkStaticImportFeature(PsiImportStaticStatement statement) {
-    return checkFeature(statement, Feature.STATIC_IMPORTS);
+  public static HighlightInfo checkStaticImportFeature(@NotNull PsiImportStaticStatement statement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(statement, Feature.STATIC_IMPORTS, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkVarargFeature(PsiParameter parameter) {
-    return checkFeature(parameter, Feature.VARARGS);
+  public static HighlightInfo checkVarargFeature(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(parameter, Feature.VARARGS, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkDiamondFeature(PsiTypeElement typeElement) {
-    return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES) : null;
+  public static HighlightInfo checkDiamondFeature(@NotNull PsiTypeElement typeElement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES,
+                                                                          languageLevel, containingFile) : null;
   }
 
   @Nullable
-  public static HighlightInfo checkMultiCatchFeature(PsiParameter parameter) {
-    return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH) : null;
+  public static HighlightInfo checkMultiCatchFeature(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH,
+                                                                            languageLevel, containingFile) : null;
   }
 
   @Nullable
-  public static HighlightInfo checkTryWithResourcesFeature(PsiResourceVariable resourceVariable) {
-    return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES);
+  public static HighlightInfo checkTryWithResourcesFeature(@NotNull PsiResourceVariable resourceVariable, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkExtensionMethodsFeature(PsiMethod method) {
-    return checkFeature(method, Feature.EXTENSION_METHODS);
+  public static HighlightInfo checkExtensionMethodsFeature(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(method, Feature.EXTENSION_METHODS, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkMethodReferencesFeature(PsiMethodReferenceExpression expression) {
-    return checkFeature(expression, Feature.METHOD_REFERENCES);
+  public static HighlightInfo checkMethodReferencesFeature(@NotNull PsiMethodReferenceExpression expression, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(expression, Feature.METHOD_REFERENCES, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkLambdaFeature(PsiLambdaExpression expression) {
-    return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS);
+  public static HighlightInfo checkLambdaFeature(@NotNull PsiLambdaExpression expression, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS, languageLevel, containingFile);
   }
 
   @Nullable
-  public static HighlightInfo checkTypeAnnotationFeature(PsiAnnotation annotation) {
-    return checkFeature(annotation, Feature.TYPE_ANNOTATIONS);
+  public static HighlightInfo checkTypeAnnotationFeature(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+    return checkFeature(annotation, Feature.TYPE_ANNOTATIONS, languageLevel, containingFile);
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index c705951..4b8075d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -23,24 +23,28 @@
 import com.intellij.codeInsight.daemon.impl.quickfix.SetupJDKFix;
 import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.TextAttributesScheme;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaVersionService;
+import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.controlFlow.ControlFlowUtil;
 import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
+import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.javadoc.PsiDocTagValue;
 import com.intellij.psi.util.*;
 import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ObjectUtils;
 import com.intellij.util.containers.MostlySingularMultiMap;
 import gnu.trove.THashMap;
 import gnu.trove.TObjectIntHashMap;
@@ -81,6 +85,8 @@
     }
   };
   private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>>();
+  private LanguageLevel myLanguageLevel;
+  private JavaSdkVersion myJavaSdkVersion;
 
   public HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
     myResolveHelper = resolveHelper;
@@ -92,6 +98,7 @@
     if (signatures == null) {
       signatures = new MostlySingularMultiMap<MethodSignature, PsiMethod>();
       for (PsiMethod method : aClass.getMethods()) {
+        if (method instanceof ExternallyDefinedPsiElement) continue; // ignore aspectj-weaved methods; they are checked elsewhere
         MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
         signatures.add(signature, method);
       }
@@ -140,6 +147,8 @@
     myHolder = holder;
     boolean success = true;
     try {
+      myLanguageLevel = PsiUtil.getLanguageLevel(file);
+      myJavaSdkVersion = ObjectUtils.notNull(JavaSdkVersionUtil.getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
       if (updateWholeFile) {
         Project project = file.getProject();
         DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
@@ -192,14 +201,14 @@
   @Override
   public void visitAnnotation(PsiAnnotation annotation) {
     super.visitAnnotation(annotation);
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationFeature(annotation));
-    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationFeature(annotation, myLanguageLevel, myFile));
+    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
-    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation));
+    if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation, myLanguageLevel));
     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkRepeatableAnnotation(annotation));
   }
 
@@ -225,7 +234,8 @@
     }
   }
 
-  @Override public void visitAnnotationMethod(PsiAnnotationMethod method) {
+  @Override
+  public void visitAnnotationMethod(PsiAnnotationMethod method) {
     PsiType returnType = method.getReturnType();
     PsiAnnotationMemberValue value = method.getDefaultValue();
     if (returnType != null && value != null) {
@@ -237,7 +247,8 @@
     myHolder.add(AnnotationsHighlightUtil.checkClashesWithSuperMethods(method));
   }
 
-  @Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
+  @Override
+  public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
     super.visitArrayInitializerExpression(expression);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkArrayInitializerApplicable(expression));
     if (!(expression.getParent() instanceof PsiNewExpression)) {
@@ -245,9 +256,10 @@
     }
   }
 
-  @Override public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
+  @Override
+  public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment,myFile));
     if (!myHolder.hasErrorResults()) visitExpression(assignment);
   }
 
@@ -259,7 +271,7 @@
 
   @Override
   public void visitLambdaExpression(PsiLambdaExpression expression) {
-    myHolder.add(HighlightUtil.checkLambdaFeature(expression));
+    myHolder.add(HighlightUtil.checkLambdaFeature(expression, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) {
       if (LambdaUtil.isValidLambdaContext(expression.getParent())) {
         final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
@@ -354,11 +366,12 @@
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassAndPackageConflict(aClass));
   }
 
-  @Override public void visitClassInitializer(PsiClassInitializer initializer) {
+  @Override
+  public void visitClassInitializer(PsiClassInitializer initializer) {
     super.visitClassInitializer(initializer);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
@@ -367,25 +380,29 @@
     }
   }
 
-  @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
+  @Override
+  public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
     super.visitClassObjectAccessExpression(expression);
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkClassObjectAccessExpression(expression));
   }
 
-  @Override public void visitComment(PsiComment comment) {
+  @Override
+  public void visitComment(PsiComment comment) {
     super.visitComment(comment);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
     if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(comment);
   }
 
-  @Override public void visitContinueStatement(PsiContinueStatement statement) {
+  @Override
+  public void visitContinueStatement(PsiContinueStatement statement) {
     super.visitContinueStatement(statement);
     if (!myHolder.hasErrorResults()) {
       myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
     }
   }
 
-  @Override public void visitJavaToken(PsiJavaToken token) {
+  @Override
+  public void visitJavaToken(PsiJavaToken token) {
     super.visitJavaToken(token);
     if (!myHolder.hasErrorResults()
         && token.getTokenType() == JavaTokenType.RBRACE
@@ -398,28 +415,31 @@
         PsiMethod method = (PsiMethod)gParent;
         codeBlock = method.getBody();
         returnType = method.getReturnType();
-      } else if (gParent instanceof PsiLambdaExpression) {
+      }
+      else if (gParent instanceof PsiLambdaExpression) {
         final PsiElement body = ((PsiLambdaExpression)gParent).getBody();
         if (!(body instanceof PsiCodeBlock)) return;
         codeBlock = (PsiCodeBlock)body;
         returnType = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)gParent);
-      } else {
+      }
+      else {
         return;
       }
       myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(codeBlock, returnType));
     }
-
   }
 
-  @Override public void visitDocComment(PsiDocComment comment) {
+  @Override
+  public void visitDocComment(PsiDocComment comment) {
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
   }
 
-  @Override public void visitDocTagValue(PsiDocTagValue value) {
+  @Override
+  public void visitDocTagValue(PsiDocTagValue value) {
     PsiReference reference = value.getReference();
     if (reference != null) {
       PsiElement element = reference.resolve();
-      final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+      final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
       if (element instanceof PsiMethod) {
         myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)element, ((PsiDocMethodOrFieldRef)value).getNameElement(), false,
                                                             colorsScheme));
@@ -430,13 +450,15 @@
     }
   }
 
-  @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
+  @Override
+  public void visitEnumConstant(PsiEnumConstant enumConstant) {
     super.visitEnumConstant(enumConstant);
-    if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder);
+    if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder, myJavaSdkVersion);
     if (!myHolder.hasErrorResults()) registerConstructorCall(enumConstant);
   }
 
-  @Override public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
+  @Override
+  public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
     super.visitEnumConstantInitializer(enumConstantInitializer);
     if (!myHolder.hasErrorResults()) {
       TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(enumConstantInitializer);
@@ -444,29 +466,30 @@
     }
   }
 
-  @Override public void visitExpression(PsiExpression expression) {
+  @Override
+  public void visitExpression(PsiExpression expression) {
     ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
 
     super.visitExpression(expression);
     PsiType type = expression.getType();
     if (myHolder.add(HighlightUtil.checkMustBeBoolean(expression, type))) return;
 
-    if(expression instanceof PsiArrayAccessExpression) {
+    if (expression instanceof PsiArrayAccessExpression) {
       myHolder.add(HighlightUtil.checkValidArrayAccessExpression((PsiArrayAccessExpression)expression));
     }
 
     if (expression.getParent() instanceof PsiNewExpression
-             && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
-             && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
+        && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
+        && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
       // like in 'new String["s"]'
       myHolder.add(HighlightUtil.checkAssignability(PsiType.INT, expression.getType(), expression, expression));
     }
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
     if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkArrayInitializer(expression, type));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression, type));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression, type));
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression, type));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression, type,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression, type));
     if (!myHolder.hasErrorResults()
         && expression.getParent() instanceof PsiThrowStatement
@@ -492,18 +515,19 @@
 
   @Override
   public void visitForeachStatement(final PsiForeachStatement statement) {
-    myHolder.add(HighlightUtil.checkForEachFeature(statement));
+    myHolder.add(HighlightUtil.checkForEachFeature(statement, myLanguageLevel, myFile));
   }
 
   @Override
   public void visitImportStaticStatement(final PsiImportStaticStatement statement) {
-    myHolder.add(HighlightUtil.checkStaticImportFeature(statement));
+    myHolder.add(HighlightUtil.checkStaticImportFeature(statement, myLanguageLevel, myFile));
   }
 
   @Override
   public void visitIdentifier(final PsiIdentifier identifier) {
+    TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
+
     PsiElement parent = identifier.getParent();
-    final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
     if (parent instanceof PsiVariable) {
       PsiVariable variable = (PsiVariable)parent;
       myHolder.add(HighlightUtil.checkVariableAlreadyDefined(variable));
@@ -512,6 +536,7 @@
         final PsiElement child = variable.getLastChild();
         if (child instanceof PsiErrorElement && child.getPrevSibling() == identifier) return;
       }
+
       boolean isMethodParameter = variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiMethod;
       if (!isMethodParameter) { // method params are highlighted in visitMethod since we should make sure the method body was visited before
         if (HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems)) {
@@ -524,11 +549,13 @@
       else {
         myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file
       }
+
+      myHolder.add(HighlightUtil.checkUnderscore(identifier, variable));
     }
     else if (parent instanceof PsiClass) {
       PsiClass aClass = (PsiClass)parent;
       if (aClass.isAnnotationType()) {
-        myHolder.add(HighlightUtil.checkAnnotationFeature(identifier));
+        myHolder.add(HighlightUtil.checkAnnotationFeature(identifier, myLanguageLevel, myFile));
       }
 
       myHolder.add(HighlightClassUtil.checkClassAlreadyImported(aClass, identifier));
@@ -546,6 +573,7 @@
     else {
       visitParentReference(parent);
     }
+
     super.visitIdentifier(identifier);
   }
 
@@ -560,7 +588,7 @@
       catch (IndexNotReadyException e) {
         return;
       }
-      myHolder.add(HighlightUtil.checkReference(ref, result));
+      myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
       if (myRefCountHolder != null) {
         myRefCountHolder.registerReference(ref, result);
       }
@@ -570,7 +598,7 @@
   @Override
   public void visitImportStatement(final PsiImportStatement statement) {
     if (!myHolder.hasErrorResults()) {
-      myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses));
+      myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses,myFile));
     }
   }
 
@@ -624,13 +652,15 @@
     }
   }
 
-  @Override public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
+  @Override
+  public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
     super.visitInstanceOfExpression(expression);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInstanceOfApplicable(expression));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInstanceOfGenericType(expression));
   }
 
-  @Override public void visitKeyword(PsiKeyword keyword) {
+  @Override
+  public void visitKeyword(PsiKeyword keyword) {
     super.visitKeyword(keyword);
     PsiElement parent = keyword.getParent();
     String text = keyword.getText();
@@ -668,25 +698,28 @@
     }
   }
 
-  @Override public void visitLabeledStatement(PsiLabeledStatement statement) {
+  @Override
+  public void visitLabeledStatement(PsiLabeledStatement statement) {
     super.visitLabeledStatement(statement);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelWithoutStatement(statement));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelAlreadyInUse(statement));
   }
 
-  @Override public void visitLiteralExpression(PsiLiteralExpression expression) {
+  @Override
+  public void visitLiteralExpression(PsiLiteralExpression expression) {
     super.visitLiteralExpression(expression);
     if (myHolder.hasErrorResults()) return;
-    myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression));
+    myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression, myLanguageLevel,myFile));
     if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(expression);
   }
 
-  @Override public void visitMethod(PsiMethod method) {
+  @Override
+  public void visitMethod(PsiMethod method) {
     super.visitMethod(method);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
-    if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method));
+    if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method, myLanguageLevel));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSafeVarargsAnnotation(method));
     if (!myHolder.hasErrorResults() && method.isConstructor()) {
       myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, method.getContainingClass()));
@@ -694,7 +727,7 @@
 
     // method params are highlighted in visitMethod since we should make sure the method body was visited before
     PsiParameter[] parameters = method.getParameterList().getParameters();
-    final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+    final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
 
     for (PsiParameter parameter : parameters) {
       int info = myReassignedParameters.get(parameter);
@@ -713,7 +746,7 @@
     if (parent instanceof PsiReferenceExpression || parent instanceof PsiJavaCodeReferenceElement) {
       return;
     }
-    final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+    final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
     if (parent instanceof PsiMethodCallExpression) {
       PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
       PsiElement methodNameElement = element.getReferenceNameElement();
@@ -751,13 +784,14 @@
     }
   }
 
-  @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+  @Override
+  public void visitMethodCallExpression(PsiMethodCallExpression expression) {
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumSuperConstructorCall(expression));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkSuperQualifierType(myFile.getProject(), expression));
     // in case of JSP synthetic method call, do not check
-    if (expression.getMethodExpression().isPhysical() && !myHolder.hasErrorResults()) {
+    if (myFile.isPhysical() && !myHolder.hasErrorResults()) {
       try {
-        myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper));
+        myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper, myLanguageLevel,myJavaSdkVersion));
       }
       catch (IndexNotReadyException ignored) {
       }
@@ -772,7 +806,7 @@
     PsiElement parent = list.getParent();
     if (parent instanceof PsiMethod) {
       PsiMethod method = (PsiMethod)parent;
-      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method));
+      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method, myLanguageLevel,myFile));
       MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
       if (!method.isConstructor()) {
         try {
@@ -793,7 +827,7 @@
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
-      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
+      if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method,myFile));
     }
     else if (parent instanceof PsiClass) {
       PsiClass aClass = (PsiClass)parent;
@@ -818,7 +852,8 @@
     }
   }
 
-  @Override public void visitNameValuePair(PsiNameValuePair pair) {
+  @Override
+  public void visitNameValuePair(PsiNameValuePair pair) {
     myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair));
     if (!myHolder.hasErrorResults()) {
       PsiIdentifier nameId = pair.getNameIdentifier();
@@ -829,14 +864,15 @@
     }
   }
 
-  @Override public void visitNewExpression(PsiNewExpression expression) {
+  @Override
+  public void visitNewExpression(PsiNewExpression expression) {
     myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
     try {
-      if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder);
+      if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder, myJavaSdkVersion);
     }
     catch (IndexNotReadyException ignored) {
     }
@@ -859,13 +895,14 @@
 
     final PsiElement parent = parameter.getParent();
     if (parent instanceof PsiParameterList) {
-      if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter));
+      if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter,
+                                                                                                     myLanguageLevel,myFile));
     }
     else if (parent instanceof PsiForeachStatement) {
       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType((PsiForeachStatement)parent));
     }
     else if (parent instanceof PsiCatchSection) {
-      if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMultiCatchFeature(parameter));
+      if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMultiCatchFeature(parameter, myLanguageLevel,myFile));
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
       if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
       if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkCatchTypeIsDisjoint(parameter));
@@ -878,14 +915,16 @@
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationMethodParameters(list));
   }
 
-  @Override public void visitPostfixExpression(PsiPostfixExpression expression) {
+  @Override
+  public void visitPostfixExpression(PsiPostfixExpression expression) {
     super.visitPostfixExpression(expression);
     if (!myHolder.hasErrorResults()) {
       myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
     }
   }
 
-  @Override public void visitPrefixExpression(PsiPrefixExpression expression) {
+  @Override
+  public void visitPrefixExpression(PsiPrefixExpression expression) {
     super.visitPrefixExpression(expression);
     if (!myHolder.hasErrorResults()) {
       myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
@@ -910,7 +949,17 @@
   private JavaResolveResult doVisitReferenceElement(@NotNull PsiJavaCodeReferenceElement ref) {
     JavaResolveResult result;
     try {
-      result = ref.advancedResolve(true);
+      if (ref instanceof PsiReferenceExpressionImpl) {
+        PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)ref;
+        JavaResolveResult[] results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+                                                                                 PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE,
+                                                                                 true, true,
+                                                                                 myFile);
+        result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
+      }
+      else {
+        result = ref.advancedResolve(true);
+      }
     }
     catch (IndexNotReadyException e) {
       return null;
@@ -922,9 +971,9 @@
       if (myRefCountHolder != null) {
         myRefCountHolder.registerReference(ref, result);
       }
-      myHolder.add(HighlightUtil.checkReference(ref, result));
+      myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
       if (!myHolder.hasErrorResults() && resolved instanceof PsiTypeParameter) {
-        boolean cannotSelectFromTypeParameter = !JavaVersionService.getInstance().isAtLeast(ref, JavaSdkVersion.JDK_1_7);
+        boolean cannotSelectFromTypeParameter = !myJavaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7);
         if (!cannotSelectFromTypeParameter) {
           final PsiClass containingClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class);
           if (containingClass != null) {
@@ -940,17 +989,18 @@
       }
     }
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAbstractInstantiation(ref, resolved));
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsForeignInnerClass(ref, resolved));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSelectStaticClassFromParameterizedType(resolved, ref));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, ref,
-                                                                                                                 result.getSubstitutor()));
+                                                                                                                 result.getSubstitutor(),
+                                                                                                                 myJavaSdkVersion));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkCannotPassInner(ref));
 
     if (resolved != null && parent instanceof PsiReferenceList) {
       if (!myHolder.hasErrorResults()) {
         PsiReferenceList referenceList = (PsiReferenceList)parent;
-        myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result));
+        myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result, myLanguageLevel));
       }
     }
 
@@ -974,7 +1024,7 @@
         myReassignedParameters.put((PsiParameter)variable, 2);
       }
 
-      final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+      final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
       if (!variable.hasModifierProperty(PsiModifier.FINAL) && isReassigned(variable)) {
         myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, ref));
       }
@@ -1027,7 +1077,8 @@
     return result;
   }
 
-  @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
+  @Override
+  public void visitReferenceExpression(PsiReferenceExpression expression) {
     JavaResolveResult resultForIncompleteCode = doVisitReferenceElement(expression);
     if (!myHolder.hasErrorResults()) {
       visitExpression(expression);
@@ -1036,7 +1087,15 @@
     JavaResolveResult result;
     JavaResolveResult[] results;
     try {
-      results = expression.multiResolve(true);
+      if (expression instanceof PsiReferenceExpressionImpl) {
+        PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)expression;
+        results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+                                                             PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, true,
+                                                             myFile);
+      }
+      else {
+        results = expression.multiResolve(true);
+      }
       result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
     }
     catch (IndexNotReadyException e) {
@@ -1046,7 +1105,7 @@
     if (resolved instanceof PsiVariable && resolved.getContainingFile() == expression.getContainingFile()) {
       if (!myHolder.hasErrorResults()) {
         try {
-          myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems));
+          myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems,myFile));
         }
         catch (IndexNotReadyException ignored) {
         }
@@ -1089,7 +1148,7 @@
 
   @Override
   public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
-    myHolder.add(HighlightUtil.checkMethodReferencesFeature(expression));
+    myHolder.add(HighlightUtil.checkMethodReferencesFeature(expression, myLanguageLevel,myFile));
     JavaResolveResult result;
     try {
       result = expression.advancedResolve(true);
@@ -1164,51 +1223,59 @@
 
   @Override
   public void visitReferenceParameterList(PsiReferenceParameterList list) {
-    myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list));
+    myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(list));
   }
 
-  @Override public void visitReturnStatement(PsiReturnStatement statement) {
+  @Override
+  public void visitReturnStatement(PsiReturnStatement statement) {
     try {
       myHolder.add(HighlightUtil.checkReturnStatementType(statement));
     }
-    catch (IndexNotReadyException ignore) { }
+    catch (IndexNotReadyException ignore) {
+    }
   }
 
-  @Override public void visitStatement(PsiStatement statement) {
+  @Override
+  public void visitStatement(PsiStatement statement) {
     super.visitStatement(statement);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAStatement(statement));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkStatementPrependedWithCaseInsideSwitch(statement));
   }
 
-  @Override public void visitSuperExpression(PsiSuperExpression expr) {
+  @Override
+  public void visitSuperExpression(PsiSuperExpression expr) {
     myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkAbstractMethodDirectCall(expr));
     if (!myHolder.hasErrorResults()) visitExpression(expr);
   }
 
-  @Override public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
+  @Override
+  public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
     super.visitSwitchLabelStatement(statement);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCaseStatement(statement));
   }
 
-  @Override public void visitSwitchStatement(PsiSwitchStatement statement) {
+  @Override
+  public void visitSwitchStatement(PsiSwitchStatement statement) {
     super.visitSwitchStatement(statement);
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSwitchSelectorType(statement));
   }
 
-  @Override public void visitThisExpression(PsiThisExpression expr) {
+  @Override
+  public void visitThisExpression(PsiThisExpression expr) {
     myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
     if (!myHolder.hasErrorResults()) {
-      myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null));
+      myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
     }
     if (!myHolder.hasErrorResults()) {
       visitExpression(expr);
     }
   }
 
-  @Override public void visitThrowStatement(PsiThrowStatement statement) {
+  @Override
+  public void visitThrowStatement(PsiThrowStatement statement) {
     myHolder.add(HighlightUtil.checkUnhandledExceptions(statement, null));
     if (!myHolder.hasErrorResults()) visitStatement(statement);
   }
@@ -1224,7 +1291,7 @@
           added = myHolder.addAll(HighlightUtil.checkExceptionThrownInTry(parameter, thrownTypes));
         }
         if (!added) {
-          myHolder.addAll(HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes));
+          myHolder.addAll(HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes,myFile));
         }
       }
     }
@@ -1233,20 +1300,21 @@
   @Override
   public void visitResourceVariable(final PsiResourceVariable resourceVariable) {
     visitVariable(resourceVariable);
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceVariable));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceVariable, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resourceVariable));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resourceVariable));
   }
 
   @Override
   public void visitTypeElement(final PsiTypeElement type) {
-    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkDiamondFeature(type));
+    if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkDiamondFeature(type, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
   }
 
-  @Override public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
+  @Override
+  public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
     super.visitTypeCastExpression(typeCast);
     try {
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
@@ -1255,11 +1323,13 @@
     }
   }
 
-  @Override public void visitTypeParameterList(PsiTypeParameterList list) {
-    myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list));
+  @Override
+  public void visitTypeParameterList(PsiTypeParameterList list) {
+    myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list, myLanguageLevel,myFile));
   }
 
-  @Override public void visitVariable(PsiVariable variable) {
+  @Override
+  public void visitVariable(PsiVariable variable) {
     super.visitVariable(variable);
     try {
       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
index ff14d0c..8212b03 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
@@ -145,7 +145,7 @@
       myOutOfScopeVariable.delete();
     }
 
-    if (HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(myUnresolvedReference, addedVar, new THashMap<PsiElement, Collection<PsiReferenceExpression>>()) != null) {
+    if (HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(myUnresolvedReference, addedVar, new THashMap<PsiElement, Collection<PsiReferenceExpression>>(),file) != null) {
       initialize(addedVar);
     }
 
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 c12e9cb..ac60748 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
@@ -18,7 +18,7 @@
 import com.intellij.codeInsight.FileModificationService;
 import com.intellij.codeInsight.NullableNotNullManager;
 import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
 import com.intellij.codeInsight.generation.PsiElementClassMember;
 import com.intellij.codeInsight.generation.PsiFieldMember;
 import com.intellij.codeInsight.generation.PsiMethodMember;
@@ -316,7 +316,7 @@
     if (newParameters == parameters) return false; //user must have canceled dialog
     boolean created = false;
     // do not introduce assignment in chanined constructor
-    if (HighlightControlFlowUtil.getChainedConstructors(constructor) == null) {
+    if (JavaHighlightUtil.getChainedConstructors(constructor) == null) {
       for (PsiField field : fields.keySet()) {
         final String defaultParamName = fields.get(field);
         PsiParameter parameter = findParamByName(defaultParamName, field.getType(), newParameters, parameterInfos);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
index 667143b..491a5f6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
@@ -569,7 +569,7 @@
     return result.toArray(new PsiVariable[result.size()]);
   }
 
-  private static void getExpectedInformation(PsiExpression expression,
+  private static void getExpectedInformation(final PsiExpression expression,
                                              List<ExpectedTypeInfo[]> types,
                                              List<String> expectedMethodNames,
                                              List<String> expectedFieldNames) {
@@ -579,6 +579,12 @@
       if (!(parent instanceof PsiReferenceExpression)) {
         ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, false);
         if (someExpectedTypes.length > 0) {
+          Arrays.sort(someExpectedTypes, new Comparator<ExpectedTypeInfo>() {
+            @Override
+            public int compare(ExpectedTypeInfo o1, ExpectedTypeInfo o2) {
+              return compareExpectedTypes(o1, o2, expression);
+            }
+          });
           types.add(someExpectedTypes);
         }
         continue;
@@ -595,6 +601,12 @@
         if (refName.equals("equals")) {
           ExpectedTypeInfo[] someExpectedTypes = equalsExpectedTypes((PsiMethodCallExpression)pparent);
           if (someExpectedTypes.length > 0) {
+            Arrays.sort(someExpectedTypes, new Comparator<ExpectedTypeInfo>() {
+              @Override
+              public int compare(ExpectedTypeInfo o1, ExpectedTypeInfo o2) {
+                return compareExpectedTypes(o1, o2, expression);
+              }
+            });
             types.add(someExpectedTypes);
           }
         }
@@ -609,6 +621,14 @@
     }
   }
 
+  private static int compareExpectedTypes(ExpectedTypeInfo o1, ExpectedTypeInfo o2, PsiExpression expression) {
+    PsiClass c1 = PsiUtil.resolveClassInType(o1.getDefaultType());
+    PsiClass c2 = PsiUtil.resolveClassInType(o2.getDefaultType());
+    if (c1 == null && c2 == null) return 0;
+    if (c1 == null || c2 == null) return c1 == null ? -1 : 1;
+    return compareMembers(c1, c2, expression);
+  }
+
   private static ExpectedTypeInfo[] equalsExpectedTypes(PsiMethodCallExpression methodCall) {
     final PsiType[] argumentTypes = methodCall.getArgumentList().getExpressionTypes();
     if (argumentTypes.length != 1) {
@@ -781,25 +801,7 @@
     Arrays.sort(members, new Comparator<PsiMember>() {
       @Override
       public int compare(final PsiMember m1, final PsiMember m2) {
-        ProgressManager.checkCanceled();
-        int result = JavaStatisticsManager.createInfo(null, m2).getUseCount() - JavaStatisticsManager.createInfo(null, m1).getUseCount();
-        if (result != 0) return result;
-        final PsiClass aClass = m1.getContainingClass();
-        final PsiClass bClass = m2.getContainingClass();
-        if (aClass == null || bClass == null) return 0;
-        result = JavaStatisticsManager.createInfo(null, bClass).getUseCount() - JavaStatisticsManager.createInfo(null, aClass).getUseCount();
-        if (result != 0) return result;
-
-        WeighingComparable<PsiElement,ProximityLocation> proximity1 = PsiProximityComparator.getProximity(m1, expression);
-        WeighingComparable<PsiElement,ProximityLocation> proximity2 = PsiProximityComparator.getProximity(m2, expression);
-        if (proximity1 != null && proximity2 != null) {
-          result = proximity2.compareTo(proximity1);
-          if (result != 0) return result;
-        }
-
-        String name1 = StaticImportMethodFix.getMemberQualifiedName(m1);
-        String name2 = StaticImportMethodFix.getMemberQualifiedName(m2);
-        return name1 == null || name2 == null ? 0 : name1.compareTo(name2);
+        return compareMembers(m1, m2, expression);
       }
     });
 
@@ -836,6 +838,29 @@
     }
   }
 
+  private static int compareMembers(PsiMember m1, PsiMember m2, PsiExpression context) {
+    ProgressManager.checkCanceled();
+    int result = JavaStatisticsManager.createInfo(null, m2).getUseCount() - JavaStatisticsManager.createInfo(null, m1).getUseCount();
+    if (result != 0) return result;
+    final PsiClass aClass = m1.getContainingClass();
+    final PsiClass bClass = m2.getContainingClass();
+    if (aClass != null && bClass != null) {
+      result = JavaStatisticsManager.createInfo(null, bClass).getUseCount() - JavaStatisticsManager.createInfo(null, aClass).getUseCount();
+      if (result != 0) return result;
+    }
+
+    WeighingComparable<PsiElement,ProximityLocation> proximity1 = PsiProximityComparator.getProximity(m1, context);
+    WeighingComparable<PsiElement,ProximityLocation> proximity2 = PsiProximityComparator.getProximity(m2, context);
+    if (proximity1 != null && proximity2 != null) {
+      result = proximity2.compareTo(proximity1);
+      if (result != 0) return result;
+    }
+
+    String name1 = PsiUtil.getMemberQualifiedName(m1);
+    String name2 = PsiUtil.getMemberQualifiedName(m2);
+    return name1 == null || name2 == null ? 0 : name1.compareTo(name2);
+  }
+
   public static boolean isAccessedForWriting(final PsiExpression[] expressionOccurences) {
     for (PsiExpression expression : expressionOccurences) {
       if(PsiUtil.isAccessedForWriting(expression)) return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
index 3225968..11bab80 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
@@ -17,13 +17,13 @@
 
 import com.intellij.codeInsight.FileModificationService;
 import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInsight.intention.LowPriorityAction;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PropertyUtil;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -116,16 +116,12 @@
     PsiClass aClass = myField.getContainingClass();
     final List<PsiMethod> methods = new ArrayList<PsiMethod>();
     if (myCreateGetter) {
-      methods.add(PropertyUtil.generateGetterPrototype(myField));
+      methods.add(GenerateMembersUtil.generateGetterPrototype(myField));
     }
     if (myCreateSetter) {
-      methods.add(PropertyUtil.generateSetterPrototype(myField));
+      methods.add(GenerateMembersUtil.generateSetterPrototype(myField));
     }
     for (PsiMethod method : methods) {
-      String modifier = PsiUtil.getMaximumModifierForMember(aClass);
-      if (modifier != null) {
-        PsiUtil.setModifierProperty(method, modifier, true);
-      }
       aClass.add(method);
     }
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
index eeae2b0..c5bd028 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiField;
 import com.intellij.psi.PsiMethod;
@@ -55,13 +56,13 @@
 
   @Override
   protected void beforeTemplateFinished(PsiClass aClass, PsiField field) {
-    PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(field);
+    PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(field);
     if (aClass.findMethodsBySignature(getterPrototype, false).length == 0) {
       aClass.add(getterPrototype);
     }
 
 
-    PsiMethod setterPrototype = PropertyUtil.generateSetterPrototype(field);
+    PsiMethod setterPrototype = GenerateMembersUtil.generateSetterPrototype(field);
     if (aClass.findMethodsBySignature(setterPrototype, false).length == 0) {
       aClass.add(setterPrototype);
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
index c616859..6567a9a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
@@ -18,6 +18,7 @@
 import com.intellij.codeInsight.CodeInsightUtilCore;
 import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
 import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.codeInsight.intention.HighPriorityAction;
 import com.intellij.codeInsight.intention.impl.TypeExpression;
 import com.intellij.codeInsight.lookup.LookupElement;
@@ -226,7 +227,7 @@
     PsiElement typeReference;
     PsiCodeBlock body;
     if (callText.startsWith(GET_PREFIX) || callText.startsWith(IS_PREFIX)) {
-      accessor = (PsiMethod)targetClass.add(PropertyUtil.generateGetterPrototype(field));
+      accessor = (PsiMethod)targetClass.add(GenerateMembersUtil.generateGetterPrototype(field));
       body = accessor.getBody();
       LOG.assertTrue(body != null, accessor.getText());
       fieldReference = ((PsiReturnStatement)body.getStatements()[0]).getReturnValue();
@@ -242,10 +243,6 @@
     }
     accessor.setName(callText);
     PsiUtil.setModifierProperty(accessor, PsiModifier.STATIC, isStatic);
-    final String modifier = PsiUtil.getMaximumModifierForMember(targetClass);
-    if (modifier != null) {
-      PsiUtil.setModifierProperty(accessor, modifier, true);
-    }
 
     TemplateBuilderImpl builder = new TemplateBuilderImpl(accessor);
     builder.replaceElement(typeReference, TYPE_VARIABLE, new TypeExpression(project, expectedTypes), true);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
index 2e23f7e..17871d1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
@@ -119,6 +119,9 @@
           return filterAssignableFrom(initializer.getType(), candidates);
         }
       }
+      if (var instanceof PsiParameter) {
+        return filterBySuperMethods((PsiParameter)var, candidates);
+      }
     }
 
     return super.filterByContext(candidates, ref);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index bfb7c45..5de7252 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -43,7 +43,9 @@
 import com.intellij.psi.search.PsiShortNamesCache;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Processor;
 import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -125,6 +127,18 @@
       }
     }
 
+    classList = filterByRequiredMemberName(classList);
+
+    List<PsiClass> filtered = filterByContext(classList, myElement);
+    if (!filtered.isEmpty()) {
+      classList = filtered;
+    }
+
+    filterAlreadyImportedButUnresolved(classList);
+    return classList;
+  }
+
+  private List<PsiClass> filterByRequiredMemberName(List<PsiClass> classList) {
     final String memberName = getRequiredMemberName(myElement);
     if (memberName != null) {
       List<PsiClass> filtered = ContainerUtil.findAll(classList, new Condition<PsiClass>() {
@@ -146,13 +160,6 @@
         classList = filtered;
       }
     }
-
-    List<PsiClass> filtered = filterByContext(classList, myElement);
-    if (!filtered.isEmpty()) {
-      classList = filtered;
-    }
-
-    filterAlreadyImportedButUnresolved(classList);
     return classList;
   }
 
@@ -206,6 +213,41 @@
     return candidates;
   }
 
+  protected static List<PsiClass> filterBySuperMethods(PsiParameter parameter, List<PsiClass> candidates) {
+    PsiElement parent = parameter.getParent();
+    if (parent instanceof PsiParameterList) {
+      PsiElement granny = parent.getParent();
+      if (granny instanceof PsiMethod) {
+        final PsiMethod method = (PsiMethod)granny;
+        if (method.getModifierList().findAnnotation(CommonClassNames.JAVA_LANG_OVERRIDE) != null) {
+          PsiClass aClass = method.getContainingClass();
+          final Set<PsiClass> probableTypes = new HashSet<PsiClass>();
+          InheritanceUtil.processSupers(aClass, false, new Processor<PsiClass>() {
+            @Override
+            public boolean process(PsiClass psiClass) {
+              for (PsiMethod psiMethod : psiClass.findMethodsByName(method.getName(), false)) {
+                for (PsiParameter psiParameter : psiMethod.getParameterList().getParameters()) {
+                  ContainerUtil.addIfNotNull(probableTypes, PsiUtil.resolveClassInClassTypeOnly(psiParameter.getType()));
+                }
+              }
+              return true;
+            }
+          });
+          List<PsiClass> filtered = ContainerUtil.filter(candidates, new Condition<PsiClass>() {
+            @Override
+            public boolean value(PsiClass psiClass) {
+              return probableTypes.contains(psiClass);
+            }
+          });
+          if (!filtered.isEmpty()) {
+            return filtered;
+          }
+        }
+      }
+    }
+    return candidates;
+  }
+
   public enum Result {
     POPUP_SHOWN,
     CLASS_AUTO_IMPORTED,
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
index 8e06218..12176d3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
@@ -17,6 +17,7 @@
 
 import com.intellij.codeInsight.FileModificationService;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
@@ -98,7 +99,7 @@
           }
         }
         else if (PsiUtil.isAccessedForReading((PsiExpression)place)) {
-          final PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(psiField);
+          final PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(psiField);
           final PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true);
           if (getter != null && PsiUtil.isAccessible(getter, place, accessObjectClass)) {
             QuickFixAction.registerQuickFixAction(error, new ReplaceInaccessibleFieldWithGetterSetterFix(place, getter, false));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
index 9c9af0f..9461af0 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
@@ -44,7 +44,6 @@
 import com.intellij.util.ObjectUtils;
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
@@ -233,7 +232,7 @@
   }
 
   public static boolean isExcluded(PsiMember method) {
-    String name = getMemberQualifiedName(method);
+    String name = PsiUtil.getMemberQualifiedName(method);
     if (name == null) return false;
     CodeInsightSettings cis = CodeInsightSettings.getInstance();
     for (String excluded : cis.EXCLUDED_PACKAGES) {
@@ -301,7 +300,7 @@
             return FINAL_CHOICE;
           }
 
-          String qname = getMemberQualifiedName(selectedValue);
+          String qname = PsiUtil.getMemberQualifiedName(selectedValue);
           if (qname == null) return FINAL_CHOICE;
           List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
           return new BaseListPopupStep<String>(null, excludableStrings) {
@@ -371,19 +370,6 @@
     popup.showInBestPositionFor(editor);
   }
 
-  @Nullable
-  public static String getMemberQualifiedName(PsiMember member) {
-    if (member instanceof PsiClass) {
-      return ((PsiClass)member).getQualifiedName();
-    }
-
-    PsiClass containingClass = member.getContainingClass();
-    if (containingClass == null) return null;
-    String className = containingClass.getQualifiedName();
-    if (className == null) return null;
-    return className + "." + member.getName();
-  }
-
   @Override
   public boolean startInWriteAction() {
     return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
index 8483946..1070533 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
@@ -312,7 +312,8 @@
     Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>();
     for (PsiReferenceExpression expression : references) {
       if (ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) return false;
-      HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems);
+      HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems,
+                                                                                                 variable.getContainingFile());
       if (highlightInfo != null) return false;
       highlightInfo = HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, finalVarProblems);
       if (highlightInfo != null) return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
index a7a666c..a8b3b28 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
@@ -18,10 +18,12 @@
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
 import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
 import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
-import com.intellij.openapi.project.DumbService;
 
 import java.util.HashMap;
 
@@ -38,8 +40,9 @@
     PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject());
     PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(manager.getProject()));
     PsiElementFactory factory = facade.getElementFactory();
+    JavaSdkVersion version = JavaSdkVersionUtil.getJavaSdkVersion(parameterList);
     for (PsiClass aClass : classes) {
-      if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false) == null) {
+      if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) {
         PsiType[] actualTypeParameters = parameterList.getTypeArguments();
         PsiTypeParameter[] classTypeParameters = aClass.getTypeParameters();
         HashMap<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
index 03b8075..ae7dfb9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
@@ -142,7 +142,7 @@
   }
 
   @Override
-  public Result charTyped(final char c, final Project project, final Editor editor, @NotNull final PsiFile file) {
+  public Result charTyped(final char c, final Project project, @NotNull final Editor editor, @NotNull final PsiFile file) {
     if (myJavaLTTyped) {
       myJavaLTTyped = false;
       handleAfterJavaLT(editor, JavaTokenType.LT, JavaTokenType.GT, INVALID_INSIDE_REFERENCE);
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
index af0a06c..f957efb 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
@@ -41,7 +41,7 @@
   private static final char SLASH = '/';
   
   @Override
-  public Result charTyped(char c, Project project, Editor editor, PsiFile file) {
+  public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) {
     if (project == null || editor == null || file == null) {
       return Result.CONTINUE;
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
index cfb4084..eebf066 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
@@ -30,6 +30,7 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.util.PsiTreeUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -154,7 +155,7 @@
   }
 
   protected String getLineBreaker(PsiElement token) {
-    CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(token.getProject());
+    CommonCodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(token.getProject()).getCommonSettings(token.getLanguage());
     return codeStyleSettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE ? "\\n\"\n+ \"" : "\\n\" +\n\"";
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
index c64d304..d706a2d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
@@ -36,7 +36,11 @@
   @Override
   public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
     List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+    result.add(getDocTagRange((PsiDocTag)e, editorText, cursorOffset));
+    return result;
+  }
 
+  public static TextRange getDocTagRange(PsiDocTag e, CharSequence documentText, int minOffset) {
     TextRange range = e.getTextRange();
 
     int endOffset = range.getEndOffset();
@@ -49,7 +53,7 @@
 
       int childStartOffset = child.getTextRange().getStartOffset();
 
-      if (childStartOffset <= cursorOffset) {
+      if (childStartOffset <= minOffset) {
         break;
       }
 
@@ -71,10 +75,8 @@
       endOffset = Math.min(childStartOffset, endOffset);
     }
 
-    startOffset = CharArrayUtil.shiftBackward(editorText, startOffset - 1, "* \t") + 1;
+    startOffset = CharArrayUtil.shiftBackward(documentText, startOffset - 1, "* \t") + 1;
 
-    result.add(new TextRange(startOffset, endOffset));
-
-    return result;
+    return new TextRange(startOffset, endOffset);
   }
 }
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 538b713..1b08887 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
@@ -19,10 +19,7 @@
 import com.intellij.codeInsight.ExpectedTypesProvider;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiAnonymousClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiNewExpression;
-import com.intellij.psi.PsiReferenceExpression;
+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;
@@ -38,7 +35,8 @@
 
   @Override
   protected boolean shouldShowExplicitLambdaType(PsiAnonymousClass anonymousClass, PsiNewExpression expression) {
-    if (expression.getParent() instanceof PsiReferenceExpression) {
+    PsiElement parent = expression.getParent();
+    if (parent instanceof PsiReferenceExpression || parent instanceof PsiAssignmentExpression) {
       return true;
     }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
index a3c52e7..de7261d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
@@ -106,6 +106,12 @@
     return id;
   }
 
+  private static boolean shouldAddOverrideAnnotation(PsiElement context) {
+    CodeStyleSettings style = CodeStyleSettingsManager.getSettings(context.getProject());
+
+    return style.INSERT_OVERRIDE_ANNOTATION && PsiUtil.isLanguageLevel5OrHigher(context);
+  }
+
   @Override
   public void run() {
     try {
@@ -133,8 +139,7 @@
       else {
         if (!mySuperHasHashCode) {
           @NonNls String text = "";
-          CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
-          if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+          if (shouldAddOverrideAnnotation(myClass)) {
             text += "@Override\n";
           }
 
@@ -172,7 +177,7 @@
 
     @NonNls StringBuffer buffer = new StringBuffer();
     CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
-    if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+    if (shouldAddOverrideAnnotation(myClass)) {
       buffer.append("@Override\n");
     }
     buffer.append("public boolean equals(Object ").append(myParameterName).append(") {\n");
@@ -327,8 +332,7 @@
   private PsiMethod createHashCode() throws IncorrectOperationException {
     @NonNls StringBuilder buffer = new StringBuilder();
 
-    CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
-    if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+    if (shouldAddOverrideAnnotation(myClass)) {
       buffer.append("@Override\n");
     }
     buffer.append("public int hashCode() {\n");
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
index 8b3dd21..632dd6d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
@@ -21,8 +21,11 @@
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.codeStyle.VariableKind;
 import com.intellij.psi.util.PropertyMemberType;
+import com.intellij.psi.util.PropertyUtil;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -54,31 +57,38 @@
   @Override
   @NotNull
   public List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
-    final PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
+    PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
     try {
-      final String name = myMemberType == PropertyMemberType.FIELD? myAttributeName : JavaCodeStyleManager.getInstance(aClass.getProject()).propertyNameToVariableName(myAttributeName, VariableKind.FIELD);
-      final PsiField psiField = psiElementFactory.createField(name, myType);
-      final GenerationInfo[] objects = new GenerateGetterAndSetterHandler().generateMemberPrototypes(aClass, new PsiFieldMember(psiField));
-      final GenerationInfo getter = objects[0];
-      final GenerationInfo setter = objects[1];
+      String fieldName = getFieldName(aClass);
+      PsiField psiField = psiElementFactory.createField(fieldName, myType);
+      GenerationInfo[] infos = new GenerateGetterAndSetterHandler().generateMemberPrototypes(aClass, new PsiFieldMember(psiField));
       if (myAnnotations.length > 0) {
-        final PsiMember targetMember;
-        switch (myMemberType) {
-          case FIELD: targetMember = psiField;
-            break;
-          case GETTER: targetMember = getter.getPsiMember();
-            break;
-          case SETTER: targetMember = setter.getPsiMember();
-            break;
-          default: targetMember = null;
-            break;
+        PsiMember targetMember = null;
+        if (myMemberType == PropertyMemberType.FIELD) {
+          targetMember = psiField;
         }
-        assert targetMember != null;
-        for (PsiAnnotation annotation : myAnnotations) {
-          targetMember.getModifierList().addAfter(annotation, null);
+        else {
+          for (GenerationInfo info : infos) {
+            PsiMember member = info.getPsiMember();
+            if (!(member instanceof PsiMethod)) continue;
+            if (myMemberType == PropertyMemberType.GETTER && PropertyUtil.isSimplePropertyGetter((PsiMethod)member) ||
+                myMemberType == PropertyMemberType.SETTER && PropertyUtil.isSimplePropertySetter((PsiMethod)member)) {
+              targetMember = member;
+              break;
+            }
+          }
+          if (targetMember == null) targetMember = findExistingMember(aClass, myMemberType);
+        }
+        PsiModifierList modifierList = targetMember != null? targetMember.getModifierList() : null;
+        if (modifierList != null) {
+          for (PsiAnnotation annotation : myAnnotations) {
+            PsiAnnotation existing = modifierList.findAnnotation(annotation.getQualifiedName());
+            if (existing != null) existing.replace(annotation);
+            else modifierList.addAfter(annotation, null);
+          }
         }
       }
-      return Arrays.asList(new PsiGenerationInfo<PsiField>(psiField), getter, setter);
+      return ContainerUtil.concat(Collections.singletonList(new PsiGenerationInfo<PsiField>(psiField)), Arrays.asList(infos));
     }
     catch (IncorrectOperationException e) {
       assert false : e;
@@ -86,6 +96,33 @@
     }
   }
 
+  @Nullable
+  public PsiMember findExistingMember(@NotNull PsiClass aClass, @NotNull PropertyMemberType memberType) {
+    if (memberType == PropertyMemberType.FIELD) {
+      return aClass.findFieldByName(getFieldName(aClass), false);
+    }
+    else if (memberType == PropertyMemberType.GETTER) {
+      try {
+        PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
+        PsiField field = psiElementFactory.createField(myAttributeName, myType);
+        PsiMethod[] templates = GetterSetterPrototypeProvider.generateGetterSetters(field, myMemberType == PropertyMemberType.GETTER);
+        for (PsiMethod template : templates) {
+          PsiMethod existingMethod = aClass.findMethodBySignature(template, true);
+          if (existingMethod != null) return existingMethod;
+        }
+      }
+      catch (IncorrectOperationException e) {
+        assert false : e;
+      }
+    }
+    return null;
+  }
+
+  private String getFieldName(PsiClass aClass) {
+    return myMemberType == PropertyMemberType.FIELD? myAttributeName : JavaCodeStyleManager
+      .getInstance(aClass.getProject()).propertyNameToVariableName(myAttributeName, VariableKind.FIELD);
+  }
+
   @Override
   protected ClassMember[] getAllOriginalMembers(PsiClass aClass) {
     throw new UnsupportedOperationException();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
index a58dfe3..27c5325 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
@@ -33,6 +33,7 @@
 import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PropertyUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
@@ -260,7 +261,7 @@
 
     try {
       final PsiMethod resultMethod = createMethod(factory, sourceMethod, target);
-      copyDocComment(sourceMethod, resultMethod);
+      copyDocComment(sourceMethod, resultMethod, factory);
       copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList());
       final PsiSubstitutor collisionResolvedSubstitutor =
         substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod);
@@ -305,7 +306,8 @@
     for (PsiTypeParameter typeParam : sourceTypeParameterList.getTypeParameters()) {
       final PsiTypeParameter substitutedTypeParam = substituteTypeParameter(factory, typeParam, substitutor, sourceMethod);
 
-      final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target, substitutedTypeParam, substitutor);
+      final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target,
+                                                                                substitutedTypeParam, substitutor);
       targetTypeParameterList.add(resolvedTypeParam);
       if (substitutedTypeParam != resolvedTypeParam) {
         substitutionMap.put(typeParam, factory.createType(resolvedTypeParam));
@@ -328,7 +330,7 @@
         return newTypeParameter;
       }
     }
-    return typeParam;
+    return factory.createTypeParameter(typeParam.getName(), typeParam.getSuperTypes());
   }
 
   @NotNull
@@ -383,8 +385,8 @@
                                            @NotNull PsiSubstitutor substitutor, PsiElement target) {
     PsiParameter[] parameters = sourceParameterList.getParameters();
     UniqueNameGenerator generator = new UniqueNameGenerator();
-    for (int i = 0; i < parameters.length; i++) {
-      PsiParameter parameter = parameters[i];
+
+    for (PsiParameter parameter : parameters) {
       final PsiType parameterType = parameter.getType();
       final PsiType substituted = substituteType(substitutor, parameterType, (PsiMethod)parameter.getDeclarationScope());
       @NonNls String paramName = parameter.getName();
@@ -394,14 +396,20 @@
         isBaseNameGenerated = false;
       }
 
-      if (paramName == null || isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName)) {
+      if (paramName == null ||
+          isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName) ||
+          !factory.isValidParameterName(paramName)) {
         String[] names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, substituted).names;
         if (names.length > 0) {
           paramName = generator.generateUniqueName(names[0]);
         }
+        else {
+          paramName = generator.generateUniqueName("p");
+        }
       }
-
-      if (paramName == null) paramName = "p" + i;
+      else if (!generator.value(paramName)) {
+        paramName = generator.generateUniqueName(paramName);
+      }
       generator.addExistingName(paramName);
       final PsiParameter newParameter = factory.createParameter(paramName, substituted, target);
       copyOrReplaceModifierList(parameter, newParameter);
@@ -419,12 +427,12 @@
     }
   }
 
-  private static void copyDocComment(PsiMethod source, PsiMethod target) {
+  private static void copyDocComment(PsiMethod source, PsiMethod target, JVMElementFactory factory) {
     final PsiElement navigationElement = source.getNavigationElement();
     if (navigationElement instanceof PsiDocCommentOwner) {
       final PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment();
       if (docComment != null) {
-        target.addAfter(docComment, null);
+        target.addAfter(factory.createDocCommentFromText(docComment.getText()), null);
       }
     }
   }
@@ -488,14 +496,6 @@
     }
   }
 
-  public static boolean shouldAddOverrideAnnotation(PsiElement context, boolean interfaceMethod) {
-    CodeStyleSettings style = CodeStyleSettingsManager.getSettings(context.getProject());
-    if (!style.INSERT_OVERRIDE_ANNOTATION) return false;
-
-    if (interfaceMethod) return PsiUtil.isLanguageLevel6OrHigher(context);
-    return PsiUtil.isLanguageLevel5OrHigher(context);
-  }
-
   public static void setupGeneratedMethod(PsiMethod method) {
     PsiClass base = method.getContainingClass().getSuperClass();
     PsiMethod overridden = base == null ? null : base.findMethodBySignature(method, true);
@@ -551,4 +551,27 @@
       }
     }
   }
+
+  @Nullable
+  public static PsiMethod generateGetterPrototype(@NotNull PsiField field) {
+    return annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateGetterPrototype(field));
+  }
+
+  @Nullable
+  public static PsiMethod generateSetterPrototype(@NotNull PsiField field) {
+    return annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateSetterPrototype(field));
+  }
+
+  @Nullable
+  private static PsiMethod annotateOnOverrideImplement(@Nullable PsiClass targetClass, @Nullable PsiMethod generated) {
+    if (generated == null || targetClass == null) return generated;
+
+    if (CodeStyleSettingsManager.getSettings(targetClass.getProject()).INSERT_OVERRIDE_ANNOTATION) {
+      PsiMethod superMethod = targetClass.findMethodBySignature(generated, true);
+      if (superMethod != null && superMethod.getContainingClass() != targetClass) {
+        OverrideImplementUtil.annotateOnOverrideImplement(generated, targetClass, superMethod, true);
+      }
+    }
+    return generated;
+  }
 }
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 53630f6..01d7187 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 0-2 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.
@@ -119,34 +119,22 @@
     return !superClass.isInterface();
   }
 
-  @NotNull
-  private static List<PsiMethod> overrideOrImplementMethod(PsiClass aClass,
-                                                       PsiMethod method,
-                                                       PsiSubstitutor substitutor,
-                                                       boolean toCopyJavaDoc,
-                                                       boolean insertOverrideIfPossible) throws IncorrectOperationException {
-    return overrideOrImplementMethod(aClass, method, substitutor, createDefaultDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible));
-  }
-
   public static List<PsiMethod> overrideOrImplementMethod(PsiClass aClass,
-      PsiMethod method,
-      PsiSubstitutor substitutor,
-      Consumer<PsiMethod> decorator) throws IncorrectOperationException {
+                                                          PsiMethod method,
+                                                          PsiSubstitutor substitutor,
+                                                          boolean toCopyJavaDoc,
+                                                          boolean insertOverrideIfPossible) throws IncorrectOperationException {
     if (!method.isValid() || !substitutor.isValid()) return Collections.emptyList();
 
     List<PsiMethod> results = new ArrayList<PsiMethod>();
     for (final MethodImplementor implementor : getImplementors()) {
       final PsiMethod[] prototypes = implementor.createImplementationPrototypes(aClass, method);
-      if (implementor.isBodyGenerated()) {
-        ContainerUtil.addAll(results, prototypes);
-      }
-      else {
-        for (PsiMethod prototype : prototypes) {
-          decorator.consume(prototype);
-          results.add(prototype);
-        }
+      for (PsiMethod prototype : prototypes) {
+        implementor.createDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible).consume(prototype);
+        results.add(prototype);
       }
     }
+
     if (results.isEmpty()) {
       PsiMethod method1 = GenerateMembersUtil.substituteGenericMethod(method, substitutor, aClass);
 
@@ -163,6 +151,7 @@
           defaultValue.getParent().deleteChildRange(defaultKeyword, defaultValue);
         }
       }
+      Consumer<PsiMethod> decorator = createDefaultDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible);
       decorator.consume(result);
       results.add(result);
     }
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
index a14108b..0f64be3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
@@ -83,17 +83,6 @@
   @Nullable
   private static PsiMethod createMethodIfNotExists(PsiClass aClass, final PsiMethod template) {
     PsiMethod existing = aClass.findMethodBySignature(template, false);
-    if (existing == null) {
-      if (template != null) {
-        String modifier = aClass.isEnum() && aClass.hasModifierProperty(PsiModifier.PUBLIC) ? null : PsiUtil.getMaximumModifierForMember(aClass);
-        if (modifier != null) {
-          PsiUtil.setModifierProperty(template, modifier, true);
-        }
-      }
-      return template;
-    }
-    else {
-      return null;
-    }
+    return existing == null ? template : null;
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
index 9d6fe88..2707501 100644
--- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
@@ -131,11 +131,11 @@
       Runnable inspect = new Runnable() {
         @Override
         public void run() {
-          pass.doInspectInBatch(managerEx, Collections.<LocalInspectionToolWrapper>singletonList(toolWrapper));
+          pass.doInspectInBatch(context, managerEx, Collections.<LocalInspectionToolWrapper>singletonList(toolWrapper));
         }
       };
       if (indicator == null) {
-        ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(inspect, new ProgressIndicatorBase());
+        ProgressManager.getInstance().executeProcessUnderProgress(inspect, new ProgressIndicatorBase());
       }
       else {
         inspect.run();
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java
index 3b41277..c8a94ed 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.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.
@@ -53,8 +53,10 @@
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    final PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
+    PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
     if (assignment == null) return false;
+    PsiElement parent = assignment.getParent();
+    if (!(parent instanceof PsiExpressionStatement)) return false;
     PsiField field = getAssignedField(assignment);
     if (field == null || field.hasInitializer()) return false;
     PsiClass psiClass = field.getContainingClass();
@@ -74,11 +76,12 @@
     if (initializer == null) return false;
     final Ref<Boolean> result = new Ref<Boolean>(Boolean.TRUE);
     initializer.accept(new JavaRecursiveElementWalkingVisitor() {
-      @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
+      @Override
+      public void visitReferenceExpression(PsiReferenceExpression expression) {
         PsiElement resolved = expression.resolve();
         if (resolved == null) return;
         if (PsiTreeUtil.isAncestor(ctrOrInitializer, resolved, false) && !PsiTreeUtil.isAncestor(initializer, resolved, false)) {
-          // resolved somewhere inside construcor but outside initializer
+          // resolved somewhere inside constructor but outside initializer
           result.set(Boolean.FALSE);
         }
       }
@@ -97,16 +100,21 @@
     }
   }
 
-  private static boolean isInitializedWithSameExpression(final PsiField field, final PsiAssignmentExpression assignment, final Collection<PsiAssignmentExpression> initializingAssignments) {
+  private static boolean isInitializedWithSameExpression(final PsiField field,
+                                                         final PsiAssignmentExpression assignment,
+                                                         final Collection<PsiAssignmentExpression> initializingAssignments) {
     final PsiExpression expression = assignment.getRExpression();
+    if (expression == null) return false;
+    PsiClass containingClass = field.getContainingClass();
+    if (containingClass == null) return false;
+
     final Ref<Boolean> result = new Ref<Boolean>(Boolean.TRUE);
     final List<PsiAssignmentExpression> totalUsages = new ArrayList<PsiAssignmentExpression>();
-    PsiClass containingClass = field.getContainingClass();
-    assert containingClass != null;
-    containingClass.accept(new JavaRecursiveElementVisitor(){
+    containingClass.accept(new JavaRecursiveElementVisitor() {
       private PsiCodeBlock currentInitializingBlock; //ctr or class initializer
 
-      @Override public void visitCodeBlock(PsiCodeBlock block) {
+      @Override
+      public void visitCodeBlock(PsiCodeBlock block) {
         PsiElement parent = block.getParent();
         if (parent instanceof PsiClassInitializer || parent instanceof PsiMethod && ((PsiMethod)parent).isConstructor()) {
           currentInitializingBlock = block;
@@ -118,7 +126,8 @@
         }
       }
 
-      @Override public void visitReferenceExpression(PsiReferenceExpression reference) {
+      @Override
+      public void visitReferenceExpression(PsiReferenceExpression reference) {
         if (!result.get().booleanValue()) return;
         super.visitReferenceExpression(reference);
         if (!PsiUtil.isOnAssignmentLeftHand(reference)) return;
@@ -126,7 +135,7 @@
         if (resolved != field) return;
         PsiExpression rValue = ((PsiAssignmentExpression)reference.getParent()).getRExpression();
         if (currentInitializingBlock != null) {
-          // ignore usages other than intializing
+          // ignore usages other than initializing
           if (rValue == null || !PsiEquivalenceUtil.areElementsEquivalent(rValue, expression)) {
             result.set(Boolean.FALSE);
           }
@@ -160,13 +169,13 @@
 
   @Override
   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
-    final PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
+    PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
     if (assignment == null) return;
     PsiField field = getAssignedField(assignment);
     if (field == null) return;
     if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
 
-    ArrayList<PsiAssignmentExpression> assignments = new ArrayList<PsiAssignmentExpression>();
+    List<PsiAssignmentExpression> assignments = new ArrayList<PsiAssignmentExpression>();
     if (!isInitializedWithSameExpression(field, assignment, assignments)) return;
     PsiExpression initializer = assignment.getRExpression();
     field.setInitializer(initializer);
@@ -174,10 +183,10 @@
     for (PsiAssignmentExpression assignmentExpression : assignments) {
       PsiElement statement = assignmentExpression.getParent();
       PsiElement parent = statement.getParent();
-      if (parent instanceof PsiIfStatement
-          || parent instanceof PsiWhileStatement
-          || parent instanceof PsiForStatement
-          || parent instanceof PsiForeachStatement) {
+      if (parent instanceof PsiIfStatement ||
+          parent instanceof PsiWhileStatement ||
+          parent instanceof PsiForStatement ||
+          parent instanceof PsiForeachStatement) {
         PsiStatement emptyStatement =
           JavaPsiFacade.getInstance(file.getProject()).getElementFactory().createStatementFromText(";", statement);
         statement.replace(emptyStatement);
@@ -187,8 +196,7 @@
       }
     }
 
-    EditorColorsManager manager = EditorColorsManager.getInstance();
-    TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
-    HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[] {field.getInitializer()}, attributes, false,null);
+    TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
+    HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[]{field.getInitializer()}, attributes, false, null);
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
index 19f3322..550da72 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
@@ -16,7 +16,7 @@
 package com.intellij.codeInsight.intention.impl;
 
 import com.intellij.codeInsight.CodeInsightBundle;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInsight.intention.QuickFixFactory;
 import com.intellij.openapi.editor.Editor;
@@ -69,7 +69,7 @@
     final Iterator<PsiMethod> iterator = result.iterator();
     //noinspection ForLoopThatDoesntUseLoopVariable
     for (PsiMethod constructor = iterator.next(); iterator.hasNext(); constructor = iterator.next()) {
-      final List<PsiMethod> chained = HighlightControlFlowUtil.getChainedConstructors(constructor);
+      final List<PsiMethod> chained = JavaHighlightUtil.getChainedConstructors(constructor);
       if (chained != null) {
         iterator.remove();
       }
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
index 168d544..0ccd769 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
@@ -34,7 +34,7 @@
   public void handleInsert(InsertionContext context) {
     super.handleInsert(context);
     if (getTailType() == TailType.DOT || context.getCompletionChar() == '.') {
-      AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor(), null);
+      AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor());
     }
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
index 9e89d7a..49befb3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
@@ -17,7 +17,7 @@
 
 import com.intellij.codeInsight.completion.*;
 import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
+import com.intellij.diagnostic.AttachmentFactory;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.ScrollType;
@@ -300,7 +300,7 @@
                                          "file.length=" + file.getTextLength() + "\n" +
                                          "document=" + context.getDocument() + "\n" +
                                          DebugUtil.currentStackTrace(),
-                                         new Attachment(context.getDocument())));
+                                         AttachmentFactory.createAttachment(context.getDocument())));
       return;
 
     }
diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
deleted file mode 100644
index 354af57..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
-import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.containers.BidirectionalMap;
-import gnu.trove.THashMap;
-import gnu.trove.THashSet;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.*;
-
-/**
- * @author cdr
- */
-public class RedundantSuppressInspection extends GlobalInspectionTool{
-  private BidirectionalMap<String, QuickFix> myQuickFixes = null;
-  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.RedundantSuppressInspection");
-
-  public boolean IGNORE_ALL = false;
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return InspectionsBundle.message("inspection.redundant.suppression.name");
-  }
-
-  @Override
-  @NotNull
-  @NonNls
-  public String getShortName() {
-    return "RedundantSuppression";
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new SingleCheckboxOptionsPanel("Ignore @SuppressWarning(\"ALL\")", this, "IGNORE_ALL");
-  }
-
-  @Override
-  public void writeSettings(@NotNull Element node) throws WriteExternalException {
-    if (IGNORE_ALL) {
-      super.writeSettings(node);
-    }
-  }
-
-  @Override
-  public void runInspection(@NotNull final AnalysisScope scope,
-                            @NotNull final InspectionManager manager,
-                            @NotNull final GlobalInspectionContext globalContext,
-                            @NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
-    globalContext.getRefManager().iterate(new RefJavaVisitor() {
-      @Override public void visitClass(@NotNull RefClass refClass) {
-        if (!globalContext.shouldCheck(refClass, RedundantSuppressInspection.this)) return;
-        CommonProblemDescriptor[] descriptors = checkElement(refClass, manager, globalContext.getProject());
-        if (descriptors != null) {
-          for (CommonProblemDescriptor descriptor : descriptors) {
-            if (descriptor instanceof ProblemDescriptor) {
-              final PsiElement psiElement = ((ProblemDescriptor)descriptor).getPsiElement();
-              final PsiMember member = PsiTreeUtil.getParentOfType(psiElement, PsiMember.class);
-              final RefElement refElement = globalContext.getRefManager().getReference(member);
-              if (refElement != null) {
-                problemDescriptionsProcessor.addProblemElement(refElement, descriptor);
-                continue;
-              }
-            }
-            problemDescriptionsProcessor.addProblemElement(refClass, descriptor);
-          }
-        }
-      }
-    });
-  }
-
-  @Nullable
-  private CommonProblemDescriptor[] checkElement(@NotNull RefClass refEntity, @NotNull InspectionManager manager, @NotNull Project project) {
-    final PsiClass psiClass = refEntity.getElement();
-    if (psiClass == null) return null;
-    return checkElement(psiClass, manager, project);
-  }
-
-  public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull final InspectionManager manager, @NotNull Project project) {
-    final Map<PsiElement, Collection<String>> suppressedScopes = new THashMap<PsiElement, Collection<String>>();
-    psiElement.accept(new JavaRecursiveElementWalkingVisitor() {
-      @Override public void visitModifierList(PsiModifierList list) {
-        super.visitModifierList(list);
-        final PsiElement parent = list.getParent();
-        if (parent instanceof PsiModifierListOwner && !(parent instanceof PsiClass)) {
-          checkElement(parent);
-        }
-      }
-
-      @Override public void visitComment(PsiComment comment) {
-        checkElement(comment);
-      }
-
-      @Override public void visitClass(PsiClass aClass) {
-        if (aClass == psiElement) {
-          super.visitClass(aClass);
-          checkElement(aClass);
-        }
-      }
-
-
-      private void checkElement(final PsiElement owner) {
-        String idsString = SuppressManager.getInstance().getSuppressedInspectionIdsIn(owner);
-        if (idsString != null && !idsString.isEmpty()) {
-          List<String> ids = StringUtil.split(idsString, ",");
-          if (IGNORE_ALL && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
-          Collection<String> suppressed = suppressedScopes.get(owner);
-          if (suppressed == null) {
-            suppressed = ids;
-          }
-          else {
-            for (String id : ids) {
-              if (!suppressed.contains(id)) {
-                suppressed.add(id);
-              }
-            }
-          }
-          suppressedScopes.put(owner, suppressed);
-        }
-      }
-    });
-
-    if (suppressedScopes.values().isEmpty()) return null;
-    // have to visit all file from scratch since inspections can be written in any perversive way including checkFile() overriding
-    Collection<InspectionToolWrapper> suppressedTools = new THashSet<InspectionToolWrapper>();
-    InspectionToolWrapper[] toolWrappers = getInspectionTools(psiElement, manager);
-    for (Collection<String> ids : suppressedScopes.values()) {
-      for (Iterator<String> iterator = ids.iterator(); iterator.hasNext(); ) {
-        final String shortName = iterator.next().trim();
-        for (InspectionToolWrapper toolWrapper : toolWrappers) {
-          if (toolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)toolWrapper).getTool().getID().equals(shortName)) {
-            if (((LocalInspectionToolWrapper)toolWrapper).isUnfair()) {
-              iterator.remove();
-              break;
-            }
-            else {
-              suppressedTools.add(toolWrapper);
-            }
-          }
-          else if (toolWrapper.getShortName().equals(shortName)) {
-            //ignore global unused as it won't be checked anyway
-            if (toolWrapper instanceof LocalInspectionToolWrapper || toolWrapper instanceof GlobalInspectionToolWrapper) {
-              suppressedTools.add(toolWrapper);
-            }
-            else {
-              iterator.remove();
-              break;
-            }
-          }
-        }
-      }
-    }
-
-    final AnalysisScope scope = new AnalysisScope(psiElement.getContainingFile());
-    final InspectionManagerEx inspectionManagerEx = (InspectionManagerEx)InspectionManager.getInstance(project);
-    final GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false);
-    globalContext.setCurrentScope(scope);
-    final RefManagerImpl refManager = (RefManagerImpl)globalContext.getRefManager();
-    refManager.inspectionReadActionStarted();
-    final List<ProblemDescriptor> result;
-    try {
-      result = new ArrayList<ProblemDescriptor>();
-      for (InspectionToolWrapper toolWrapper : suppressedTools) {
-        String toolId = toolWrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)toolWrapper).getTool().getID() : toolWrapper.getShortName();
-        toolWrapper.initialize(globalContext);
-        Collection<CommonProblemDescriptor> descriptors;
-        final InspectionToolPresentation presentation = globalContext.getPresentation(toolWrapper);
-        if (toolWrapper instanceof LocalInspectionToolWrapper) {
-          LocalInspectionToolWrapper local = (LocalInspectionToolWrapper)toolWrapper;
-          if (local.isUnfair()) continue; //cant't work with passes other than LocalInspectionPass
-          List<ProblemDescriptor> results = local.getTool().processFile(psiElement.getContainingFile(), manager);
-          InspectionToolPresentation toolPresentation = globalContext.getPresentation(local);
-          LocalDescriptorsUtil.addProblemDescriptors(results, toolPresentation, false, globalContext, local.getTool());
-          descriptors = presentation.getProblemDescriptors();
-        }
-        else if (toolWrapper instanceof GlobalInspectionToolWrapper) {
-          final GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)toolWrapper;
-          GlobalInspectionTool globalTool = global.getTool();
-          if (globalTool.isGraphNeeded()) {
-            refManager.findAllDeclarations();
-          }
-          final InspectionToolPresentation toolPresentation = globalContext.getPresentation(global);
-          globalContext.getRefManager().iterate(new RefVisitor() {
-            @Override public void visitElement(@NotNull RefEntity refEntity) {
-              CommonProblemDescriptor[]
-                descriptors1 = global.getTool().checkElement(refEntity, scope, manager, globalContext, toolPresentation);
-              if (descriptors1 != null) {
-                toolPresentation.addProblemElement(refEntity, false, descriptors1);
-              }
-            }
-          });
-          descriptors = presentation.getProblemDescriptors();
-        }
-        else {
-          continue;
-        }
-        for (PsiElement suppressedScope : suppressedScopes.keySet()) {
-          Collection<String> suppressedIds = suppressedScopes.get(suppressedScope);
-          if (!suppressedIds.contains(toolId)) continue;
-          for (CommonProblemDescriptor descriptor : descriptors) {
-            if (!(descriptor instanceof ProblemDescriptor)) continue;
-            PsiElement element = ((ProblemDescriptor)descriptor).getPsiElement();
-            if (element == null) continue;
-            PsiElement annotation = SuppressManager.getInstance().getElementToolSuppressedIn(element, toolId);
-            if (annotation != null && PsiTreeUtil.isAncestor(suppressedScope, annotation, false) || annotation == null && !PsiTreeUtil.isAncestor(suppressedScope, element, false)) {
-              suppressedIds.remove(toolId);
-              break;
-            }
-          }
-        }
-      }
-      for (PsiElement suppressedScope : suppressedScopes.keySet()) {
-        Collection<String> suppressedIds = suppressedScopes.get(suppressedScope);
-        for (String toolId : suppressedIds) {
-          PsiMember psiMember;
-          String problemLine = null;
-          if (suppressedScope instanceof PsiMember) {
-            psiMember = (PsiMember)suppressedScope;
-          }
-          else {
-            psiMember = PsiTreeUtil.getParentOfType(suppressedScope, PsiDocCommentOwner.class);
-            final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(suppressedScope, PsiStatement.class);
-            problemLine = statement != null ? statement.getText() : null;
-          }
-          if (psiMember != null && psiMember.isValid()) {
-            String description = InspectionsBundle.message("inspection.redundant.suppression.description");
-            if (myQuickFixes == null) myQuickFixes = new BidirectionalMap<String, QuickFix>();
-            final String key = toolId + (problemLine != null ? ";" + problemLine : "");
-            QuickFix fix = myQuickFixes.get(key);
-            if (fix == null) {
-              fix = new RemoveSuppressWarningAction(toolId, problemLine);
-              myQuickFixes.put(key, fix);
-            }
-            PsiElement identifier = null;
-            if (psiMember instanceof PsiMethod) {
-              identifier = ((PsiMethod)psiMember).getNameIdentifier();
-            }
-            else if (psiMember instanceof PsiField) {
-              identifier = ((PsiField)psiMember).getNameIdentifier();
-            }
-            else if (psiMember instanceof PsiClass) {
-              identifier = ((PsiClass)psiMember).getNameIdentifier();
-            }
-            if (identifier == null) {
-              identifier = psiMember;
-            }
-            result.add(
-              manager.createProblemDescriptor(identifier, description, (LocalQuickFix)fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
-                                              false));
-          }
-        }
-      }
-    }
-    finally {
-      refManager.inspectionReadActionFinished();
-      globalContext.close(true);
-    }
-    return result.toArray(new ProblemDescriptor[result.size()]);
-  }
-
-  protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
-    ModifiableModel model = InspectionProjectProfileManager.getInstance(manager.getProject()).getInspectionProfile().getModifiableModel();
-    InspectionProfileWrapper profile = new InspectionProfileWrapper((InspectionProfile)model);
-    profile.init(manager.getProject());
-
-    return profile.getInspectionTools(psiElement);
-  }
-
-
-  @Override
-  @Nullable
-  public QuickFix getQuickFix(final String hint) {
-    return myQuickFixes != null ? myQuickFixes.get(hint) : new RemoveSuppressWarningAction(hint);
-  }
-
-
-  @Override
-  @Nullable
-  public String getHint(@NotNull final QuickFix fix) {
-    if (myQuickFixes != null) {
-      final List<String> list = myQuickFixes.getKeysByValue(fix);
-      if (list != null) {
-        LOG.assertTrue(list.size() == 1);
-        return list.get(0);
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public boolean isEnabledByDefault() {
-    return false;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
index de7f6dc..18ba50a 100644
--- a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
@@ -41,7 +41,7 @@
   }
 
   @NotNull
-  private static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) {
+  public static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) {
     return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<SuppressQuickFix, SuppressIntentionAction>() {
       @Override
       public SuppressIntentionAction fun(SuppressQuickFix fix) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java
deleted file mode 100644
index 3b322ff..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.canBeFinal;
-
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.psi.*;
-import com.intellij.psi.controlFlow.*;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * User: anna
- * Date: 27-Dec-2005
- */
-class CanBeFinalAnnotator extends RefGraphAnnotatorEx {
-  private final RefManager myManager;
-  public static int CAN_BE_FINAL_MASK;
-
-  public CanBeFinalAnnotator(@NotNull RefManager manager) {
-    myManager = manager;
-  }
-
-  @Override
-  public void initialize(RefManager refManager) {
-    CAN_BE_FINAL_MASK = refManager.getLastUsedMask();
-  }
-
-  @Override
-  public void onInitialize(RefElement refElement) {
-    ((RefElementImpl)refElement).setFlag(true, CAN_BE_FINAL_MASK);
-    if (refElement instanceof RefClass) {
-      final RefClass refClass = (RefClass)refElement;
-      final PsiClass psiClass = refClass.getElement();
-      if (refClass.isEntry()) {
-        ((RefClassImpl)refClass).setFlag(false, CAN_BE_FINAL_MASK);
-        return;
-      }
-      if (refClass.isAbstract() || refClass.isAnonymous() || refClass.isInterface()) {
-        ((RefClassImpl)refClass).setFlag(false, CAN_BE_FINAL_MASK);
-        return;
-      }
-      if (!refClass.isSelfInheritor(psiClass)) {
-        for (PsiClass psiSuperClass : psiClass.getSupers()) {
-          if (myManager.belongsToScope(psiSuperClass)) {
-            RefClass refSuperClass = (RefClass)myManager.getReference(psiSuperClass);
-            if (refSuperClass != null) {
-              ((RefClassImpl)refSuperClass).setFlag(false, CAN_BE_FINAL_MASK);
-            }
-          }
-        }
-      }
-    }
-    else if (refElement instanceof RefMethod) {
-      final RefMethod refMethod = (RefMethod)refElement;
-      final PsiElement element = refMethod.getElement();
-      if (element instanceof PsiMethod) {
-        PsiMethod psiMethod = (PsiMethod)element;
-        if (refMethod.isConstructor() || refMethod.isAbstract() || refMethod.isStatic() ||
-            PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) || refMethod.getOwnerClass().isAnonymous() ||
-            refMethod.getOwnerClass().isInterface()) {
-          ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
-        }
-        if (PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) && refMethod.getOwner() != null &&
-            !(refMethod.getOwnerClass().getOwner() instanceof RefElement)) {
-          ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
-        }
-        for (PsiMethod psiSuperMethod : psiMethod.findSuperMethods()) {
-          if (myManager.belongsToScope(psiSuperMethod)) {
-            RefMethod refSuperMethod = (RefMethod)myManager.getReference(psiSuperMethod);
-            if (refSuperMethod != null) {
-              ((RefMethodImpl)refSuperMethod).setFlag(false, CAN_BE_FINAL_MASK);
-            }
-          }
-        }
-      }
-    }
-  }
-
-
-  @Override
-  public void onMarkReferenced(RefElement refWhat,
-                               RefElement refFrom,
-                               boolean referencedFromClassInitializer,
-                               boolean forReading,
-                               boolean forWriting) {
-    if (!(refWhat instanceof RefField)) return;
-    if (!(refFrom instanceof RefMethod) ||
-        !((RefMethod)refFrom).isConstructor() ||
-        ((PsiField)refWhat.getElement()).hasInitializer() ||
-        ((RefMethod)refFrom).getOwnerClass() != ((RefField)refWhat).getOwnerClass() ||
-        ((RefField)refWhat).isStatic()) {
-      if (!referencedFromClassInitializer  && forWriting) {
-        ((RefFieldImpl)refWhat).setFlag(false, CAN_BE_FINAL_MASK);
-      }
-    }
-  }
-
-  @Override
-  public void onReferencesBuild(RefElement refElement) {
-    if (refElement instanceof RefClass) {
-      final PsiClass psiClass = (PsiClass)refElement.getElement();
-      if (psiClass != null) {
-
-        if (refElement.isEntry()) {
-          ((RefClassImpl)refElement).setFlag(false, CAN_BE_FINAL_MASK);
-        }
-
-        PsiMethod[] psiMethods = psiClass.getMethods();
-        PsiField[] psiFields = psiClass.getFields();
-
-        HashSet<PsiVariable> allFields = new HashSet<PsiVariable>();
-        ContainerUtil.addAll(allFields, psiFields);
-        ArrayList<PsiVariable> instanceInitializerInitializedFields = new ArrayList<PsiVariable>();
-        boolean hasInitializers = false;
-        for (PsiClassInitializer initializer : psiClass.getInitializers()) {
-          PsiCodeBlock body = initializer.getBody();
-          hasInitializers = true;
-          ControlFlow flow;
-          try {
-            flow = ControlFlowFactory.getInstance(body.getProject())
-              .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
-          }
-          catch (AnalysisCanceledException e) {
-            flow = ControlFlow.EMPTY;
-          }
-          Collection<PsiVariable> writtenVariables = new ArrayList<PsiVariable>();
-          ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false, writtenVariables);
-          for (PsiVariable psiVariable : writtenVariables) {
-            if (allFields.contains(psiVariable)) {
-              if (instanceInitializerInitializedFields.contains(psiVariable)) {
-                allFields.remove(psiVariable);
-                instanceInitializerInitializedFields.remove(psiVariable);
-              }
-              else {
-                instanceInitializerInitializedFields.add(psiVariable);
-              }
-            }
-          }
-          for (PsiVariable psiVariable : writtenVariables) {
-            if (!instanceInitializerInitializedFields.contains(psiVariable)) {
-              allFields.remove(psiVariable);
-            }
-          }
-        }
-
-        for (PsiMethod psiMethod : psiMethods) {
-          if (psiMethod.isConstructor()) {
-            PsiCodeBlock body = psiMethod.getBody();
-            if (body != null) {
-              hasInitializers = true;
-              ControlFlow flow;
-              try {
-                flow = ControlFlowFactory.getInstance(body.getProject())
-                  .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
-              }
-              catch (AnalysisCanceledException e) {
-                flow = ControlFlow.EMPTY;
-              }
-
-              Collection<PsiVariable> writtenVariables = ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false);
-              for (PsiVariable psiVariable : writtenVariables) {
-                if (instanceInitializerInitializedFields.contains(psiVariable)) {
-                  allFields.remove(psiVariable);
-                  instanceInitializerInitializedFields.remove(psiVariable);
-                }
-              }
-              List<PsiMethod> redirectedConstructors = HighlightControlFlowUtil.getChainedConstructors(psiMethod);
-              if (redirectedConstructors == null || redirectedConstructors.isEmpty()) {
-                List<PsiVariable> ssaVariables = ControlFlowUtil.getSSAVariables(flow);
-                ArrayList<PsiVariable> good = new ArrayList<PsiVariable>(ssaVariables);
-                good.addAll(instanceInitializerInitializedFields);
-                allFields.retainAll(good);
-              }
-              else {
-                allFields.removeAll(writtenVariables);
-              }
-            }
-          }
-        }
-
-        for (PsiField psiField : psiFields) {
-          if ((!hasInitializers || !allFields.contains(psiField)) && psiField.getInitializer() == null) {
-            final RefFieldImpl refField = (RefFieldImpl)myManager.getReference(psiField);
-            if (refField != null) {
-              refField.setFlag(false, CAN_BE_FINAL_MASK);
-            }
-          }
-        }
-
-      }
-    }
-    else if (refElement instanceof RefMethod) {
-      final RefMethod refMethod = (RefMethod)refElement;
-      if (refMethod.isEntry()) {
-        ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
-      }
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
deleted file mode 100644
index 105bee1..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 24, 2001
- * Time: 2:46:32 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.canBeFinal;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-
-public class CanBeFinalInspection extends GlobalJavaInspectionTool {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.canBeFinal.CanBeFinalInspection");
-
-  public boolean REPORT_CLASSES = false;
-  public boolean REPORT_METHODS = false;
-  public boolean REPORT_FIELDS = true;
-  public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.can.be.final.display.name");
-  @NonNls public static final String SHORT_NAME = "CanBeFinal";
-  @NonNls private static final String QUICK_FIX_NAME = InspectionsBundle.message("inspection.can.be.final.accept.quickfix");
-
-  private class OptionsPanel extends JPanel {
-    private final JCheckBox myReportClassesCheckbox;
-    private final JCheckBox myReportMethodsCheckbox;
-    private final JCheckBox myReportFieldsCheckbox;
-
-    private OptionsPanel() {
-      super(new GridBagLayout());
-
-      GridBagConstraints gc = new GridBagConstraints();
-      gc.weighty = 0;
-      gc.weightx = 1;
-      gc.fill = GridBagConstraints.HORIZONTAL;
-      gc.anchor = GridBagConstraints.NORTHWEST;
-
-
-      myReportClassesCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option"));
-      myReportClassesCheckbox.setSelected(REPORT_CLASSES);
-      myReportClassesCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          REPORT_CLASSES = myReportClassesCheckbox.isSelected();
-        }
-      });
-      gc.gridy = 0;
-      add(myReportClassesCheckbox, gc);
-
-      myReportMethodsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option1"));
-      myReportMethodsCheckbox.setSelected(REPORT_METHODS);
-      myReportMethodsCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          REPORT_METHODS = myReportMethodsCheckbox.isSelected();
-        }
-      });
-      gc.gridy++;
-      add(myReportMethodsCheckbox, gc);
-
-      myReportFieldsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option2"));
-      myReportFieldsCheckbox.setSelected(REPORT_FIELDS);
-      myReportFieldsCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          REPORT_FIELDS = myReportFieldsCheckbox.isSelected();
-        }
-      });
-
-      gc.weighty = 1;
-      gc.gridy++;
-      add(myReportFieldsCheckbox, gc);
-    }
-  }
-
-  public boolean isReportClasses() {
-    return REPORT_CLASSES;
-  }
-
-  public boolean isReportMethods() {
-    return REPORT_METHODS;
-  }
-
-  public boolean isReportFields() {
-    return REPORT_FIELDS;
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new OptionsPanel();
-  }
-
-  @Override
-  @Nullable
-  public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
-    return new CanBeFinalAnnotator(refManager);
-  }
-
-
-  @Override
-  @Nullable
-  public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
-                                                @NotNull final AnalysisScope scope,
-                                                @NotNull final InspectionManager manager,
-                                                @NotNull final GlobalInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor processor) {
-    if (refEntity instanceof RefJavaElement) {
-      final RefJavaElement refElement = (RefJavaElement)refEntity;
-      if (refElement instanceof RefParameter) return null;
-      if (!refElement.isReferenced()) return null;
-      if (refElement.isSyntheticJSP()) return null;
-      if (refElement.isFinal()) return null;
-      if (!((RefElementImpl)refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK)) return null;
-
-      final PsiMember psiMember = (PsiMember)refElement.getElement();
-      if (psiMember == null || !CanBeFinalHandler.allowToBeFinal(psiMember)) return null;
-
-      PsiIdentifier psiIdentifier = null;
-      if (refElement instanceof RefClass) {
-        RefClass refClass = (RefClass)refElement;
-        if (refClass.isInterface() || refClass.isAnonymous() || refClass.isAbstract()) return null;
-        if (!isReportClasses()) return null;
-        psiIdentifier = ((PsiClass)psiMember).getNameIdentifier();
-      }
-      else if (refElement instanceof RefMethod) {
-        RefMethod refMethod = (RefMethod)refElement;
-        if (refMethod.getOwnerClass().isFinal()) return null;
-        if (!isReportMethods()) return null;
-        psiIdentifier = ((PsiMethod)psiMember).getNameIdentifier();
-      }
-      else if (refElement instanceof RefField) {
-        if (!isReportFields()) return null;
-        psiIdentifier = ((PsiField)psiMember).getNameIdentifier();
-      }
-
-
-      if (psiIdentifier != null) {
-        return new ProblemDescriptor[]{manager.createProblemDescriptor(psiIdentifier, InspectionsBundle.message(
-          "inspection.export.results.can.be.final.description"), new AcceptSuggested(globalContext.getRefManager()),
-                                                                 ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
-      }
-    }
-    return null;
-  }
-
-  @Override
-  protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
-                                                @NotNull final GlobalJavaInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor problemsProcessor) {
-    for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) {
-      problemsProcessor.ignoreElement(entryPoint);
-    }
-
-    manager.iterate(new RefJavaVisitor() {
-      @Override public void visitElement(@NotNull RefEntity refEntity) {
-        if (problemsProcessor.getDescriptions(refEntity) == null) return;
-        refEntity.accept(new RefJavaVisitor() {
-          @Override public void visitMethod(@NotNull final RefMethod refMethod) {
-            if (!refMethod.isStatic() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) &&
-                !(refMethod instanceof RefImplicitConstructor)) {
-              globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
-                @Override
-                public boolean process(PsiMethod derivedMethod) {
-                  ((RefElementImpl)refMethod).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
-                  problemsProcessor.ignoreElement(refMethod);
-                  return false;
-                }
-              });
-            }
-          }
-
-          @Override public void visitClass(@NotNull final RefClass refClass) {
-            if (!refClass.isAnonymous()) {
-              globalContext.enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
-                @Override
-                public boolean process(PsiClass inheritor) {
-                  ((RefClassImpl)refClass).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
-                  problemsProcessor.ignoreElement(refClass);
-                  return false;
-                }
-              });
-            }
-          }
-
-          @Override public void visitField(@NotNull final RefField refField) {
-            globalContext.enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
-              @Override
-              public boolean process(PsiReference psiReference) {
-                PsiElement expression = psiReference.getElement();
-                if (expression instanceof PsiReferenceExpression && PsiUtil.isAccessedForWriting((PsiExpression)expression)) {
-                  ((RefFieldImpl)refField).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
-                  problemsProcessor.ignoreElement(refField);
-                  return false;
-                }
-                return true;
-              }
-            });
-          }
-        });
-
-      }
-    });
-
-    return false;
-  }
-
-
-  @Override
-  @Nullable
-  public QuickFix getQuickFix(final String hint) {
-    return new AcceptSuggested(null);
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return DISPLAY_NAME;
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getShortName() {
-    return SHORT_NAME;
-  }
-
-  private static class AcceptSuggested implements LocalQuickFix {
-    private final RefManager myManager;
-
-    public AcceptSuggested(final RefManager manager) {
-      myManager = manager;
-    }
-
-    @Override
-    @NotNull
-    public String getName() {
-      return QUICK_FIX_NAME;
-    }
-
-    @Override
-    @NotNull
-    public String getFamilyName() {
-      return getName();
-    }
-
-    @Override
-    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
-      if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
-      final PsiElement element = descriptor.getPsiElement();
-      final PsiModifierListOwner psiElement = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class);
-      if (psiElement != null) {
-        RefJavaElement refElement = (RefJavaElement)(myManager != null ? myManager.getReference(psiElement) : null);
-        try {
-          if (psiElement instanceof PsiVariable) {
-            ((PsiVariable)psiElement).normalizeDeclaration();
-          }
-          final PsiModifierList modifierList = psiElement.getModifierList();
-          LOG.assertTrue(modifierList != null);
-          modifierList.setModifierProperty(PsiModifier.FINAL, true);
-        }
-        catch (IncorrectOperationException e) {
-          LOG.error(e);
-        }
-
-        if (refElement != null) {
-          RefJavaUtil.getInstance().setIsFinal(refElement, true);
-        }
-      }
-    }
-  }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
index c22571a..8943e59 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
@@ -47,6 +47,7 @@
 
   private class OptionsPanel extends JPanel {
     private final JCheckBox myIgnoreAssertions;
+    private final JCheckBox myReportConstantReferences;
     private final JCheckBox mySuggestNullables;
     private final JCheckBox myDontReportTrueAsserts;
 
@@ -88,6 +89,15 @@
         }
       });
 
+      myReportConstantReferences = new JCheckBox("Warn when reading a value guaranteed to be constant");
+      myReportConstantReferences.setSelected(REPORT_CONSTANT_REFERENCE_VALUES);
+      myReportConstantReferences.getModel().addChangeListener(new ChangeListener() {
+        @Override
+        public void stateChanged(ChangeEvent e) {
+          REPORT_CONSTANT_REFERENCE_VALUES = myReportConstantReferences.isSelected();
+        }
+      });
+
       gc.insets = new Insets(0, 0, 0, 0);
       gc.gridy = 0;
       add(mySuggestNullables, gc);
@@ -134,6 +144,9 @@
 
       gc.gridy++;
       add(myIgnoreAssertions, gc);
+
+      gc.gridy++;
+      add(myReportConstantReferences, gc);
     }
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java
new file mode 100644
index 0000000..01f982f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.deadCode;
+
+import com.intellij.codeInspection.InspectionEP;
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.codeInspection.InspectionsBundle;
+import org.jetbrains.annotations.NotNull;
+
+public class DummyEntryPointsEP extends InspectionEP {
+  public DummyEntryPointsEP() {
+    presentation = DummyEntryPointsPresentation.class.getName();
+    displayName = InspectionsBundle.message("inspection.dead.code.entry.points.display.name");
+    implementationClass = "";
+    shortName = "";
+  }
+
+  @NotNull
+  @Override
+  public InspectionProfileEntry instantiateTool() {
+    return new DummyEntryPointsTool();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
index 531c88c..04fe0f2 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.codeInspection.deadCode;
 
+import com.intellij.codeInspection.GlobalJavaInspectionContext;
 import com.intellij.codeInspection.InspectionsBundle;
 import com.intellij.codeInspection.ex.*;
 import com.intellij.codeInspection.reference.RefElement;
@@ -28,8 +29,8 @@
   private static final RefEntryPointFilter myFilter = new RefEntryPointFilter();
   private QuickFixAction[] myQuickFixActions;
 
-  public DummyEntryPointsPresentation(UnusedDeclarationInspection inspection, @NotNull InspectionToolWrapper toolWrapper) {
-    super(toolWrapper);
+  public DummyEntryPointsPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
+    super(toolWrapper, context);
   }
 
   @Override
@@ -51,9 +52,9 @@
     }
 
     @Override
-    protected boolean applyFix(RefEntity[] refElements) {
+    protected boolean applyFix(@NotNull RefEntity[] refElements) {
       final EntryPointsManager entryPointsManager =
-        getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager());
+        getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager());
       for (RefEntity refElement : refElements) {
         if (refElement instanceof RefElement) {
           entryPointsManager.removeEntryPoint((RefElement)refElement);
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
index 524f333..2b216dc 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
@@ -20,17 +20,14 @@
 import com.intellij.codeInspection.InspectionManager;
 import com.intellij.codeInspection.InspectionsBundle;
 import com.intellij.codeInspection.ProblemDescriptionsProcessor;
-import com.intellij.codeInspection.ex.InspectionPresentationProvider;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
 import com.intellij.codeInspection.ex.JobDescriptor;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * @author max
  */
-public class DummyEntryPointsTool extends UnusedDeclarationInspection implements InspectionPresentationProvider {
+public class DummyEntryPointsTool extends UnusedDeclarationInspection {
   public DummyEntryPointsTool() {
   }
 
@@ -64,10 +61,4 @@
   public String getShortName() {
     return "";
   }
-
-  @NotNull
-  @Override
-  public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
-    return new DummyEntryPointsPresentation(this, toolWrapper);
-  }
 }
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
index 02731b7..03ab979 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
@@ -27,10 +27,11 @@
 import com.intellij.codeInspection.reference.RefJavaElement;
 import com.intellij.codeInspection.reference.RefParameter;
 import com.intellij.codeInspection.util.RefFilter;
+import org.jetbrains.annotations.NotNull;
 
 public class RefEntryPointFilter extends RefFilter {
   @Override
-  public int getElementProblemCount(RefJavaElement refElement) {
+  public int getElementProblemCount(@NotNull RefJavaElement refElement) {
     if (refElement instanceof RefParameter) return 0;
     return refElement.isEntry() && !refElement.isSyntheticJSP() ? 1 : 0;
   }
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
deleted file mode 100644
index b00d749..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 2, 2001
- * Time: 12:07:30 AM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.util.RefFilter;
-import org.jetbrains.annotations.NotNull;
-
-public class RefUnreachableFilter extends RefFilter {
-  @NotNull
-  protected UnusedDeclarationInspection myTool;
-  @NotNull protected final GlobalInspectionContextImpl myContext;
-
-  public RefUnreachableFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
-    myTool = tool;
-    myContext = context;
-  }
-
-  @Override
-  public int getElementProblemCount(RefJavaElement refElement) {
-    if (refElement instanceof RefParameter) return 0;
-    if (refElement.isSyntheticJSP()) return 0;
-    if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
-    if (!myContext.isToCheckMember(refElement, myTool)) return 0;
-    return ((RefElementImpl)refElement).isSuspicious() ? 1 : 0;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
deleted file mode 100644
index 923e577..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 2, 2001
- * Time: 12:14:37 AM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.reference.*;
-import org.jetbrains.annotations.NotNull;
-
-public class UnreferencedFilter extends RefUnreachableFilter {
-  public UnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
-    super(tool, context);
-  }
-
-  @Override
-  public int getElementProblemCount(RefJavaElement refElement) {
-    if (refElement instanceof RefParameter) return 0;
-    if (refElement.isEntry() || !((RefElementImpl)refElement).isSuspicious() || refElement.isSyntheticJSP()) return 0;
-
-    if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
-    if (!myContext.isToCheckMember(refElement, myTool)) return 0;
-
-    if (refElement instanceof RefField) {
-      RefField refField = (RefField) refElement;
-      if (refField.isUsedForReading() && !refField.isUsedForWriting()) return 1;
-      if (refField.isUsedForWriting() && !refField.isUsedForReading()) return 1;
-    }
-
-    if (refElement instanceof RefClass && ((RefClass)refElement).isAnonymous()) return 0;
-    return -1;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
deleted file mode 100644
index 7799cc2..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 12, 2001
- * Time: 9:40:45 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.ExtensionPoints;
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
-import com.intellij.codeInspection.util.RefFilter;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiClassImplUtil;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
-import com.intellij.psi.search.PsiSearchHelper;
-import com.intellij.psi.util.PsiMethodUtil;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.SeparatorFactory;
-import com.intellij.util.containers.HashMap;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.*;
-import java.util.List;
-
-public class UnusedDeclarationInspection extends GlobalInspectionTool implements InspectionPresentationProvider {
-  public boolean ADD_MAINS_TO_ENTRIES = true;
-
-  public boolean ADD_APPLET_TO_ENTRIES = true;
-  public boolean ADD_SERVLET_TO_ENTRIES = true;
-  public boolean ADD_NONJAVA_TO_ENTRIES = true;
-
-  private Set<RefElement> myProcessedSuspicious = null;
-  private int myPhase;
-  public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
-  @NonNls public static final String SHORT_NAME = "UnusedDeclaration";
-  @NonNls private static final String ALTERNATIVE_ID = "unused";
-
-  public final EntryPoint[] myExtensions;
-  private static final Logger LOG = Logger.getInstance("#" + UnusedDeclarationInspection.class.getName());
-  private GlobalInspectionContextImpl myContext;
-
-  public UnusedDeclarationInspection() {
-    ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
-    final EntryPoint[] deadCodeAddins = new EntryPoint[point.getExtensions().length];
-    EntryPoint[] extensions = point.getExtensions();
-    for (int i = 0, extensionsLength = extensions.length; i < extensionsLength; i++) {
-      EntryPoint entryPoint = extensions[i];
-      try {
-        deadCodeAddins[i] = entryPoint.clone();
-      }
-      catch (CloneNotSupportedException e) {
-        LOG.error(e);
-      }
-    }
-    Arrays.sort(deadCodeAddins, new Comparator<EntryPoint>() {
-      @Override
-      public int compare(final EntryPoint o1, final EntryPoint o2) {
-        return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
-      }
-    });
-    myExtensions = deadCodeAddins;
-  }
-
-  private GlobalInspectionContextImpl getContext() {
-    return myContext;
-  }
-
-  private class OptionsPanel extends JPanel {
-    private final JCheckBox myMainsCheckbox;
-    private final JCheckBox myAppletToEntries;
-    private final JCheckBox myServletToEntries;
-    private final JCheckBox myNonJavaCheckbox;
-
-    private OptionsPanel() {
-      super(new GridBagLayout());
-      GridBagConstraints gc = new GridBagConstraints();
-      gc.weightx = 1;
-      gc.weighty = 0;
-      gc.insets = new Insets(0, IdeBorderFactory.TITLED_BORDER_INDENT, 2, 0);
-      gc.fill = GridBagConstraints.HORIZONTAL;
-      gc.anchor = GridBagConstraints.NORTHWEST;
-
-      myMainsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option"));
-      myMainsCheckbox.setSelected(ADD_MAINS_TO_ENTRIES);
-      myMainsCheckbox.addActionListener(new ActionListener() {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          ADD_MAINS_TO_ENTRIES = myMainsCheckbox.isSelected();
-        }
-      });
-
-      gc.gridy = 0;
-      add(myMainsCheckbox, gc);
-
-      myAppletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option3"));
-      myAppletToEntries.setSelected(ADD_APPLET_TO_ENTRIES);
-      myAppletToEntries.addActionListener(new ActionListener() {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          ADD_APPLET_TO_ENTRIES = myAppletToEntries.isSelected();
-        }
-      });
-      gc.gridy++;
-      add(myAppletToEntries, gc);
-
-      myServletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option4"));
-      myServletToEntries.setSelected(ADD_SERVLET_TO_ENTRIES);
-      myServletToEntries.addActionListener(new ActionListener(){
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          ADD_SERVLET_TO_ENTRIES = myServletToEntries.isSelected();
-        }
-      });
-      gc.gridy++;
-      add(myServletToEntries, gc);
-
-      for (final EntryPoint extension : myExtensions) {
-        if (extension.showUI()) {
-          final JCheckBox extCheckbox = new JCheckBox(extension.getDisplayName());
-          extCheckbox.setSelected(extension.isSelected());
-          extCheckbox.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-              extension.setSelected(extCheckbox.isSelected());
-            }
-          });
-          gc.gridy++;
-          add(extCheckbox, gc);
-        }
-      }
-
-      myNonJavaCheckbox =
-      new JCheckBox(InspectionsBundle.message("inspection.dead.code.option5"));
-      myNonJavaCheckbox.setSelected(ADD_NONJAVA_TO_ENTRIES);
-      myNonJavaCheckbox.addActionListener(new ActionListener() {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-          ADD_NONJAVA_TO_ENTRIES = myNonJavaCheckbox.isSelected();
-        }
-      });
-
-      gc.gridy++;
-      add(myNonJavaCheckbox, gc);
-
-      final JButton configureAnnotations = EntryPointsManagerImpl.createConfigureAnnotationsBtn(this);
-      gc.fill = GridBagConstraints.NONE;
-      gc.gridy++;
-      gc.insets.top = 10;
-      gc.weighty = 1;
-
-      add(configureAnnotations, gc);
-    }
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    final JPanel scrollPane = new JPanel(new BorderLayout());
-    scrollPane.add(SeparatorFactory.createSeparator("Entry points", null), BorderLayout.NORTH);
-    scrollPane.add(new OptionsPanel(), BorderLayout.CENTER);
-    return scrollPane;
-  }
-
-  private boolean isAddMainsEnabled() {
-    return ADD_MAINS_TO_ENTRIES;
-  }
-
-  private boolean isAddAppletEnabled() {
-    return ADD_APPLET_TO_ENTRIES;
-  }
-
-  private boolean isAddServletEnabled() {
-    return ADD_SERVLET_TO_ENTRIES;
-  }
-
-  private boolean isAddNonJavaUsedEnabled() {
-    return ADD_NONJAVA_TO_ENTRIES;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return DISPLAY_NAME;
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getShortName() {
-    return SHORT_NAME;
-  }
-
-  @Override
-  public void readSettings(@NotNull Element node) throws InvalidDataException {
-    super.readSettings(node);
-    for (EntryPoint extension : myExtensions) {
-      extension.readExternal(node);
-    }
-  }
-
-  @Override
-  public void writeSettings(@NotNull Element node) throws WriteExternalException {
-    super.writeSettings(node);
-    for (EntryPoint extension : myExtensions) {
-      extension.writeExternal(node);
-    }
-  }
-
-  private static boolean isExternalizableNoParameterConstructor(PsiMethod method, RefClass refClass) {
-    if (!method.isConstructor()) return false;
-    if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return false;
-    final PsiParameterList parameterList = method.getParameterList();
-    if (parameterList.getParametersCount() != 0) return false;
-    final PsiClass aClass = method.getContainingClass();
-    return aClass == null || isExternalizable(aClass, refClass);
-  }
-
-  private static boolean isSerializationImplicitlyUsedField(PsiField field) {
-    @NonNls final String name = field.getName();
-    if (!HighlightUtilBase.SERIAL_VERSION_UID_FIELD_NAME.equals(name) && !"serialPersistentFields".equals(name)) return false;
-    if (!field.hasModifierProperty(PsiModifier.STATIC)) return false;
-    PsiClass aClass = field.getContainingClass();
-    return aClass == null || isSerializable(aClass, null);
-  }
-
-  private static boolean isWriteObjectMethod(PsiMethod method, RefClass refClass) {
-    @NonNls final String name = method.getName();
-    if (!"writeObject".equals(name)) return false;
-    PsiParameter[] parameters = method.getParameterList().getParameters();
-    if (parameters.length != 1) return false;
-    if (!parameters[0].getType().equalsToText("java.io.ObjectOutputStream")) return false;
-    if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
-    PsiClass aClass = method.getContainingClass();
-    return !(aClass != null && !isSerializable(aClass, refClass));
-  }
-
-  private static boolean isReadObjectMethod(PsiMethod method, RefClass refClass) {
-    @NonNls final String name = method.getName();
-    if (!"readObject".equals(name)) return false;
-    PsiParameter[] parameters = method.getParameterList().getParameters();
-    if (parameters.length != 1) return false;
-    if (!parameters[0].getType().equalsToText("java.io.ObjectInputStream")) return false;
-    if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
-    PsiClass aClass = method.getContainingClass();
-    return !(aClass != null && !isSerializable(aClass, refClass));
-  }
-
-  private static boolean isWriteReplaceMethod(PsiMethod method, RefClass refClass) {
-    @NonNls final String name = method.getName();
-    if (!"writeReplace".equals(name)) return false;
-    PsiParameter[] parameters = method.getParameterList().getParameters();
-    if (parameters.length != 0) return false;
-    if (!method.getReturnType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return false;
-    if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
-    PsiClass aClass = method.getContainingClass();
-    return !(aClass != null && !isSerializable(aClass, refClass));
-  }
-
-  private static boolean isReadResolveMethod(PsiMethod method, RefClass refClass) {
-    @NonNls final String name = method.getName();
-    if (!"readResolve".equals(name)) return false;
-    PsiParameter[] parameters = method.getParameterList().getParameters();
-    if (parameters.length != 0) return false;
-    if (!method.getReturnType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return false;
-    if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
-    final PsiClass aClass = method.getContainingClass();
-    return !(aClass != null && !isSerializable(aClass, refClass));
-  }
-
-  private static boolean isSerializable(PsiClass aClass, @Nullable RefClass refClass) {
-    final PsiClass serializableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.io.Serializable", aClass.getResolveScope());
-    return serializableClass != null && isSerializable(aClass, refClass, serializableClass);
-  }
-
-  private static boolean isExternalizable(PsiClass aClass, RefClass refClass) {
-    final GlobalSearchScope scope = aClass.getResolveScope();
-    final PsiClass externalizableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.io.Externalizable", scope);
-    return externalizableClass != null && isSerializable(aClass, refClass, externalizableClass);
-  }
-
-  private static boolean isSerializable(PsiClass aClass, RefClass refClass, PsiClass serializableClass) {
-    if (aClass == null) return false;
-    if (aClass.isInheritor(serializableClass, true)) return true;
-    if (refClass != null) {
-      final Set<RefClass> subClasses = refClass.getSubClasses();
-      for (RefClass subClass : subClasses) {
-        if (isSerializable(subClass.getElement(), subClass, serializableClass)) return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
-  public void runInspection(@NotNull final AnalysisScope scope,
-                            @NotNull InspectionManager manager,
-                            @NotNull final GlobalInspectionContext globalContext,
-                            @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
-    globalContext.getRefManager().iterate(new RefJavaVisitor() {
-      @Override
-      public void visitElement(@NotNull final RefEntity refEntity) {
-        if (refEntity instanceof RefJavaElement) {
-          final RefElementImpl refElement = (RefElementImpl)refEntity;
-          if (!refElement.isSuspicious()) return;
-
-          PsiFile file = refElement.getContainingFile();
-
-          if (file == null) return;
-          final boolean isSuppressed = refElement.isSuppressed(getShortName(), ALTERNATIVE_ID);
-          if (!((GlobalInspectionContextImpl)globalContext).isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
-            if (isSuppressed || !scope.contains(file)) {
-              getEntryPointsManager().addEntryPoint(refElement, false);
-            }
-            return;
-          }
-
-          refElement.accept(new RefJavaVisitor() {
-            @Override
-            public void visitMethod(@NotNull RefMethod method) {
-              if (isAddMainsEnabled() && method.isAppMain()) {
-                getEntryPointsManager().addEntryPoint(method, false);
-              }
-            }
-
-            @Override
-            public void visitClass(@NotNull RefClass aClass) {
-              if (isAddAppletEnabled() && aClass.isApplet() ||
-                  isAddServletEnabled() && aClass.isServlet()) {
-                getEntryPointsManager().addEntryPoint(aClass, false);
-              }
-            }
-          });
-        }
-      }
-    });
-
-    if (isAddNonJavaUsedEnabled()) {
-      checkForReachables();
-      final StrictUnreferencedFilter strictUnreferencedFilter = new StrictUnreferencedFilter(this,
-                                                                                             (GlobalInspectionContextImpl)globalContext);
-      ProgressManager.getInstance().runProcess(new Runnable() {
-        @Override
-        public void run() {
-          final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(globalContext.getRefManager().getProject());
-          globalContext.getRefManager().iterate(new RefJavaVisitor() {
-            @Override
-            public void visitElement(@NotNull final RefEntity refEntity) {
-              if (refEntity instanceof RefClass && strictUnreferencedFilter.accepts((RefClass)refEntity)) {
-                findExternalClassReferences((RefClass)refEntity);
-              }
-              else if (refEntity instanceof RefMethod) {
-                RefMethod refMethod = (RefMethod)refEntity;
-                if (refMethod.isConstructor() && strictUnreferencedFilter.accepts(refMethod)) {
-                  findExternalClassReferences(refMethod.getOwnerClass());
-                }
-              }
-            }
-
-            private void findExternalClassReferences(final RefClass refElement) {
-              PsiClass psiClass = refElement.getElement();
-              String qualifiedName = psiClass.getQualifiedName();
-              if (qualifiedName != null) {
-                helper.processUsagesInNonJavaFiles(qualifiedName,
-                                                   new PsiNonJavaFileReferenceProcessor() {
-                                                     @Override
-                                                     public boolean process(PsiFile file, int startOffset, int endOffset) {
-                                                       getEntryPointsManager().addEntryPoint(refElement, false);
-                                                       return false;
-                                                     }
-                                                   },
-                                                   GlobalSearchScope.projectScope(globalContext.getProject()));
-              }
-            }
-          });
-        }
-      }, null);
-    }
-
-    myProcessedSuspicious = new HashSet<RefElement>();
-    myPhase = 1;
-  }
-
-  public boolean isEntryPoint(final RefElement owner) {
-    final PsiElement element = owner.getElement();
-    if (RefUtil.isImplicitUsage(element)) return true;
-    if (element instanceof PsiModifierListOwner) {
-      final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(element.getProject());
-      if (entryPointsManager.isEntryPoint((PsiModifierListOwner)element)) {
-        return true;
-      }
-    }
-    for (EntryPoint extension : myExtensions) {
-      if (extension.isEntryPoint(owner, element)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public boolean isEntryPoint(@NotNull PsiElement element) {
-    final Project project = element.getProject();
-    final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
-    if (element instanceof PsiMethod && isAddMainsEnabled() && PsiClassImplUtil.isMainOrPremainMethod((PsiMethod)element)) {
-      return true;
-    }
-    if (element instanceof PsiClass) {
-      PsiClass aClass = (PsiClass)element;
-      /*
-      if (aClass.isAnnotationType()) {
-        return true;
-      }
-
-      if (aClass.isEnum()) {
-        return true;
-      }
-      */
-      final PsiClass applet = psiFacade.findClass("java.applet.Applet", GlobalSearchScope.allScope(project));
-      if (isAddAppletEnabled() && applet != null && aClass.isInheritor(applet, true)) {
-        return true;
-      }
-
-      final PsiClass servlet = psiFacade.findClass("javax.servlet.Servlet", GlobalSearchScope.allScope(project));
-      if (isAddServletEnabled() && servlet != null && aClass.isInheritor(servlet, true)) {
-        return true;
-      }
-      if (isAddMainsEnabled() && PsiMethodUtil.hasMainMethod(aClass)) return true;
-    }
-    if (element instanceof PsiModifierListOwner) {
-      final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(project);
-      if (AnnotationUtil
-        .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.ADDITIONAL_ANNOTATIONS) ||
-        AnnotationUtil
-        .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.getAdditionalAnnotations())) {
-        return true;
-      }
-    }
-    for (EntryPoint extension : myExtensions) {
-      if (extension.isEntryPoint(element)) {
-        return true;
-      }
-    }
-    final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
-    for (ImplicitUsageProvider provider : implicitUsageProviders) {
-      if (provider.isImplicitUsage(element)) return true;
-    }
-    return false;
-  }
-
-
-  private static class StrictUnreferencedFilter extends UnreferencedFilter {
-    private StrictUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
-      super(tool, context);
-    }
-
-    @Override
-    public int getElementProblemCount(RefJavaElement refElement) {
-      final int problemCount = super.getElementProblemCount(refElement);
-      if (problemCount > -1) return problemCount;
-      return refElement.isReferenced() ? 0 : 1;
-    }
-  }
-
-  @Override
-  public boolean queryExternalUsagesRequests(@NotNull InspectionManager manager,
-                                             @NotNull GlobalInspectionContext globalContext,
-                                             @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
-    checkForReachables();
-    final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this, (GlobalInspectionContextImpl)globalContext) :
-                             new RefUnreachableFilter(this, (GlobalInspectionContextImpl)globalContext);
-    final boolean[] requestAdded = {false};
-
-    globalContext.getRefManager().iterate(new RefJavaVisitor() {
-      @Override
-      public void visitElement(@NotNull RefEntity refEntity) {
-        if (!(refEntity instanceof RefJavaElement)) return;
-        if (refEntity instanceof RefClass && ((RefClass)refEntity).isAnonymous()) return;
-        RefJavaElement refElement = (RefJavaElement)refEntity;
-        if (filter.accepts(refElement) && !myProcessedSuspicious.contains(refElement)) {
-          refEntity.accept(new RefJavaVisitor() {
-            @Override
-            public void visitField(@NotNull final RefField refField) {
-              myProcessedSuspicious.add(refField);
-              PsiField psiField = refField.getElement();
-              if (isSerializationImplicitlyUsedField(psiField)) {
-                getEntryPointsManager().addEntryPoint(refField, false);
-              }
-              else {
-                getJavaContext().enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
-                  @Override
-                  public boolean process(PsiReference psiReference) {
-                    getEntryPointsManager().addEntryPoint(refField, false);
-                    return false;
-                  }
-                });
-                requestAdded[0] = true;
-              }
-            }
-
-            @Override
-            public void visitMethod(@NotNull final RefMethod refMethod) {
-              myProcessedSuspicious.add(refMethod);
-              if (refMethod instanceof RefImplicitConstructor) {
-                visitClass(refMethod.getOwnerClass());
-              }
-              else {
-                PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
-                if (isSerializablePatternMethod(psiMethod, refMethod.getOwnerClass())) {
-                  getEntryPointsManager().addEntryPoint(refMethod, false);
-                }
-                else if (!refMethod.isExternalOverride() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())) {
-                  for (final RefMethod derivedMethod : refMethod.getDerivedMethods()) {
-                    myProcessedSuspicious.add(derivedMethod);
-                  }
-
-                  enqueueMethodUsages(refMethod);
-                  requestAdded[0] = true;
-                }
-              }
-            }
-
-            @Override
-            public void visitClass(@NotNull final RefClass refClass) {
-              myProcessedSuspicious.add(refClass);
-              if (!refClass.isAnonymous()) {
-                getJavaContext().enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
-                  @Override
-                  public boolean process(PsiClass inheritor) {
-                    getEntryPointsManager().addEntryPoint(refClass, false);
-                    return false;
-                  }
-                });
-
-                getJavaContext().enqueueClassUsagesProcessor(refClass, new GlobalJavaInspectionContext.UsagesProcessor() {
-                  @Override
-                  public boolean process(PsiReference psiReference) {
-                    getEntryPointsManager().addEntryPoint(refClass, false);
-                    return false;
-                  }
-                });
-                requestAdded[0] = true;
-              }
-            }
-          });
-        }
-      }
-    });
-
-    if (!requestAdded[0]) {
-      if (myPhase == 2) {
-        myProcessedSuspicious = null;
-        return false;
-      }
-      else {
-        myPhase = 2;
-      }
-    }
-
-    return true;
-  }
-
-  private static boolean isSerializablePatternMethod(PsiMethod psiMethod, RefClass refClass) {
-    return isReadObjectMethod(psiMethod, refClass) || isWriteObjectMethod(psiMethod, refClass) || isReadResolveMethod(psiMethod, refClass) ||
-           isWriteReplaceMethod(psiMethod, refClass) || isExternalizableNoParameterConstructor(psiMethod, refClass);
-  }
-
-  private void enqueueMethodUsages(final RefMethod refMethod) {
-    if (refMethod.getSuperMethods().isEmpty()) {
-      getJavaContext().enqueueMethodUsagesProcessor(refMethod, new GlobalJavaInspectionContext.UsagesProcessor() {
-        @Override
-        public boolean process(PsiReference psiReference) {
-          getEntryPointsManager().addEntryPoint(refMethod, false);
-          return false;
-        }
-      });
-    }
-    else {
-      for (RefMethod refSuper : refMethod.getSuperMethods()) {
-        enqueueMethodUsages(refSuper);
-      }
-    }
-  }
-
-  private GlobalJavaInspectionContext getJavaContext() {
-    return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT);
-  }
-
-  @Nullable
-  @Override
-  public JobDescriptor[] getAdditionalJobs() {
-    return new JobDescriptor[]{getContext().getStdJobDescriptors().BUILD_GRAPH, getContext().getStdJobDescriptors().FIND_EXTERNAL_USAGES};
-  }
-
-
-  void checkForReachables() {
-    CodeScanner codeScanner = new CodeScanner();
-
-    // Cleanup previous reachability information.
-    getContext().getRefManager().iterate(new RefJavaVisitor() {
-      @Override
-      public void visitElement(@NotNull RefEntity refEntity) {
-        if (refEntity instanceof RefJavaElement) {
-          final RefJavaElementImpl refElement = (RefJavaElementImpl)refEntity;
-          if (!getContext().isToCheckMember(refElement, UnusedDeclarationInspection.this)) return;
-          refElement.setReachable(false);
-        }
-      }
-    });
-
-
-    for (RefElement entry : getEntryPointsManager().getEntryPoints()) {
-      entry.accept(codeScanner);
-    }
-
-    while (codeScanner.newlyInstantiatedClassesCount() != 0) {
-      codeScanner.cleanInstantiatedClassesCount();
-      codeScanner.processDelayedMethods();
-    }
-  }
-
-  private EntryPointsManager getEntryPointsManager() {
-    return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager());
-  }
-
-  private static class CodeScanner extends RefJavaVisitor {
-    private final HashMap<RefClass, HashSet<RefMethod>> myClassIDtoMethods;
-    private final HashSet<RefClass> myInstantiatedClasses;
-    private int myInstantiatedClassesCount;
-    private final HashSet<RefMethod> myProcessedMethods;
-
-    private CodeScanner() {
-      myClassIDtoMethods = new HashMap<RefClass, HashSet<RefMethod>>();
-      myInstantiatedClasses = new HashSet<RefClass>();
-      myProcessedMethods = new HashSet<RefMethod>();
-      myInstantiatedClassesCount = 0;
-    }
-
-    @Override public void visitMethod(@NotNull RefMethod method) {
-      if (!myProcessedMethods.contains(method)) {
-        // Process class's static intitializers
-        if (method.isStatic() || method.isConstructor()) {
-          if (method.isConstructor()) {
-            addInstantiatedClass(method.getOwnerClass());
-          }
-          else {
-            ((RefClassImpl)method.getOwnerClass()).setReachable(true);
-          }
-          myProcessedMethods.add(method);
-          makeContentReachable((RefJavaElementImpl)method);
-          makeClassInitializersReachable(method.getOwnerClass());
-        }
-        else {
-          if (isClassInstantiated(method.getOwnerClass())) {
-            myProcessedMethods.add(method);
-            makeContentReachable((RefJavaElementImpl)method);
-          }
-          else {
-            addDelayedMethod(method);
-          }
-
-          for (RefMethod refSub : method.getDerivedMethods()) {
-            visitMethod(refSub);
-          }
-        }
-      }
-    }
-
-    @Override public void visitClass(@NotNull RefClass refClass) {
-      boolean alreadyActive = refClass.isReachable();
-      ((RefClassImpl)refClass).setReachable(true);
-
-      if (!alreadyActive) {
-        // Process class's static intitializers.
-        makeClassInitializersReachable(refClass);
-      }
-
-      addInstantiatedClass(refClass);
-    }
-
-    @Override public void visitField(@NotNull RefField field) {
-      // Process class's static intitializers.
-      if (!field.isReachable()) {
-        makeContentReachable((RefJavaElementImpl)field);
-        makeClassInitializersReachable(field.getOwnerClass());
-      }
-    }
-
-    private void addInstantiatedClass(RefClass refClass) {
-      if (myInstantiatedClasses.add(refClass)) {
-        ((RefClassImpl)refClass).setReachable(true);
-        myInstantiatedClassesCount++;
-
-        final List<RefMethod> refMethods = refClass.getLibraryMethods();
-        for (RefMethod refMethod : refMethods) {
-          refMethod.accept(this);
-        }
-        for (RefClass baseClass : refClass.getBaseClasses()) {
-          addInstantiatedClass(baseClass);
-        }
-      }
-    }
-
-    private void makeContentReachable(RefJavaElementImpl refElement) {
-      refElement.setReachable(true);
-      for (RefElement refCallee : refElement.getOutReferences()) {
-        refCallee.accept(this);
-      }
-    }
-
-    private void makeClassInitializersReachable(RefClass refClass) {
-      for (RefElement refCallee : refClass.getOutReferences()) {
-        refCallee.accept(this);
-      }
-    }
-
-    private void addDelayedMethod(RefMethod refMethod) {
-      HashSet<RefMethod> methods = myClassIDtoMethods.get(refMethod.getOwnerClass());
-      if (methods == null) {
-        methods = new HashSet<RefMethod>();
-        myClassIDtoMethods.put(refMethod.getOwnerClass(), methods);
-      }
-      methods.add(refMethod);
-    }
-
-    private boolean isClassInstantiated(RefClass refClass) {
-      return myInstantiatedClasses.contains(refClass);
-    }
-
-    private int newlyInstantiatedClassesCount() {
-      return myInstantiatedClassesCount;
-    }
-
-    private void cleanInstantiatedClassesCount() {
-      myInstantiatedClassesCount = 0;
-    }
-
-    private void processDelayedMethods() {
-      RefClass[] instClasses = myInstantiatedClasses.toArray(new RefClass[myInstantiatedClasses.size()]);
-      for (RefClass refClass : instClasses) {
-        if (isClassInstantiated(refClass)) {
-          HashSet<RefMethod> methods = myClassIDtoMethods.get(refClass);
-          if (methods != null) {
-            RefMethod[] arMethods = methods.toArray(new RefMethod[methods.size()]);
-            for (RefMethod arMethod : arMethods) {
-              arMethod.accept(this);
-            }
-          }
-        }
-      }
-    }
-  }
-
-
-  @NotNull
-  @Override
-  public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
-    return new UnusedDeclarationPresentation(toolWrapper);
-  }
-
-  @Override
-  public void initialize(@NotNull GlobalInspectionContext context) {
-    super.initialize(context);
-    myContext = (GlobalInspectionContextImpl)context;
-  }
-
-  @Override
-  public void cleanup() {
-    super.cleanup();
-    myContext = null;
-  }
-
-  @Override
-  public boolean isGraphNeeded() {
-    return true;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
index 29f0578..0db0532 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
@@ -65,9 +65,10 @@
   @NonNls private static final String COMMENT = "comment";
   @NonNls private static final String [] HINTS = {COMMENT, DELETE};
 
-  public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper) {
-    super(toolWrapper);
+  public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
+    super(toolWrapper, context);
     myQuickFixActions = createQuickFixes(toolWrapper);
+    ((EntryPointsManagerBase)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES);
   }
 
   public RefFilter getFilter() {
@@ -82,7 +83,7 @@
     }
 
     @Override
-    public int getElementProblemCount(final RefJavaElement refElement) {
+    public int getElementProblemCount(@NotNull final RefJavaElement refElement) {
       final int problemCount = super.getElementProblemCount(refElement);
       if (problemCount > - 1) return problemCount;
       if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1;
@@ -91,7 +92,7 @@
   }
 
   @NotNull
-  UnusedDeclarationInspection getTool() {
+  private UnusedDeclarationInspection getTool() {
     return (UnusedDeclarationInspection)getToolWrapper().getTool();
   }
 
@@ -162,7 +163,7 @@
     }
 
     @Override
-    protected boolean applyFix(final RefEntity[] refElements) {
+    protected boolean applyFix(@NotNull final RefEntity[] refElements) {
       if (!super.applyFix(refElements)) return false;
       final ArrayList<PsiElement> psiElements = new ArrayList<PsiElement>();
       for (RefEntity refElement : refElements) {
@@ -176,6 +177,7 @@
         @Override
         public void run() {
           final Project project = getContext().getProject();
+          if (isDisposed() || project.isDisposed()) return;
           SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() {
             @Override
             public void run() {
@@ -199,7 +201,7 @@
     }
 
     @Override
-    protected boolean applyFix(RefEntity[] refElements) {
+    protected boolean applyFix(@NotNull RefEntity[] refElements) {
       final EntryPointsManager entryPointsManager = getEntryPointsManager();
       for (RefEntity refElement : refElements) {
         if (refElement instanceof RefElement) {
@@ -218,9 +220,9 @@
     }
 
     @Override
-    protected boolean applyFix(RefEntity[] refElements) {
+    protected boolean applyFix(@NotNull RefEntity[] refElements) {
       if (!super.applyFix(refElements)) return false;
-      ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>(1);
+      List<RefElement> deletedRefs = new ArrayList<RefElement>(1);
       for (RefEntity refElement : refElements) {
         PsiElement psiElement = refElement instanceof RefElement ? ((RefElement)refElement).getElement() : null;
         if (psiElement == null) continue;
@@ -331,12 +333,6 @@
   }
 
   @Override
-  public void initialize(@NotNull GlobalInspectionContextImpl context) {
-    super.initialize(context);
-    ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES);
-  }
-
-  @Override
   public void updateContent() {
     getTool().checkForReachables();
     myPackageContents = new HashMap<String, Set<RefEntity>>();
@@ -360,7 +356,7 @@
   @Override
   public boolean hasReportedProblems() {
     final GlobalInspectionContextImpl context = getContext();
-    if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){
+    if (!isDisposed() && context.getUIOptions().SHOW_ONLY_DIFF){
       return containsOnlyDiff(myPackageContents) ||
              myOldPackageContents != null && containsOnlyDiff(myOldPackageContents);
     }
@@ -438,7 +434,7 @@
   @Override
   public FileStatus getElementStatus(final RefEntity element) {
     final GlobalInspectionContextImpl context = getContext();
-    if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
+    if (!isDisposed() && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
       if (myOldPackageContents != null){
         final boolean old = RefUtil.contains(element, collectRefElements(myOldPackageContents));
         final boolean current = RefUtil.contains(element, collectRefElements(myPackageContents));
diff --git a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
index a2a95d7..a35c30d 100644
--- a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
@@ -15,7 +15,7 @@
  */
 package com.intellij.codeInspection.emptyMethod;
 
-import com.intellij.ExtensionPoints;
+import com.intellij.ToolExtensionPoints;
 import com.intellij.analysis.AnalysisScope;
 import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.daemon.GroupNames;
@@ -51,7 +51,7 @@
 /**
  * @author max
  */
-public class EmptyMethodInspection extends GlobalJavaInspectionTool {
+public class EmptyMethodInspection extends GlobalJavaBatchInspectionTool {
   private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.empty.method.display.name");
   @NonNls private static final String SHORT_NAME = "EmptyMethod";
 
@@ -166,7 +166,7 @@
     if (AnnotationUtil.isAnnotated(owner, EXCLUDE_ANNOS)) {
       return false;
     }
-    for (final Object extension : Extensions.getExtensions(ExtensionPoints.EMPTY_METHOD_TOOL)) {
+    for (final Object extension : Extensions.getExtensions(ToolExtensionPoints.EMPTY_METHOD_TOOL)) {
       if (((Condition<RefMethod>) extension).value(refMethod)) {
         return false;
       }
@@ -358,7 +358,7 @@
     }
 
     @Override
-    public void applyFix(final @NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+    public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
        applyFix(project, new ProblemDescriptor[]{descriptor}, new ArrayList<PsiElement>(), null);
     }
 
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
index caacfbf..d8851e0 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
@@ -24,339 +24,31 @@
  */
 package com.intellij.codeInspection.ex;
 
-import com.intellij.ExtensionPoints;
-import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
-import com.intellij.codeInspection.reference.*;
 import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
-import com.intellij.ide.DataManager;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.*;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.ExtensionPointListener;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.extensions.PluginDescriptor;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.*;
-import com.intellij.profile.codeInspection.InspectionProfileManager;
-import com.intellij.psi.*;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
 import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
 @State(
     name = "EntryPointsManager",
     storages = {@Storage( file = StoragePathMacros.PROJECT_FILE)}
 )
-public class EntryPointsManagerImpl implements PersistentStateComponent<Element>, EntryPointsManager {
-  @NonNls private static final String[] STANDARD_ANNOS = {
-    "javax.ws.rs.*",
-  };
-
-  // null means uninitialized
-  private volatile List<String> ADDITIONAL_ANNOS;
-
-  public Collection<String> getAdditionalAnnotations() {
-    List<String> annos = ADDITIONAL_ANNOS;
-    if (annos == null) {
-      annos = new ArrayList<String>();
-      Collections.addAll(annos, STANDARD_ANNOS);
-      final EntryPoint[] extensions = Extensions.getExtensions(ExtensionPoints.DEAD_CODE_TOOL, null);
-      for (EntryPoint extension : extensions) {
-        final String[] ignoredAnnotations = extension.getIgnoreAnnotations();
-        if (ignoredAnnotations != null) {
-          ContainerUtil.addAll(annos, ignoredAnnotations);
-        }
-      }
-      ADDITIONAL_ANNOS = annos = Collections.unmodifiableList(annos);
-    }
-    return annos;
-  }
-  public JDOMExternalizableStringList ADDITIONAL_ANNOTATIONS = new JDOMExternalizableStringList();
-  private final Map<String, SmartRefElementPointer> myPersistentEntryPoints;
-  private final Set<RefElement> myTemporaryEntryPoints;
-  private static final String VERSION = "2.0";
-  @NonNls private static final String VERSION_ATTR = "version";
-  @NonNls private static final String ENTRY_POINT_ATTR = "entry_point";
-  private boolean myAddNonJavaEntries = true;
-  private boolean myResolved = false;
-  private final Project myProject;
-  private long myLastModificationCount = -1;
-
+public class EntryPointsManagerImpl extends EntryPointsManagerBase implements PersistentStateComponent<Element> {
   public EntryPointsManagerImpl(Project project) {
-    myProject = project;
-    myTemporaryEntryPoints = new HashSet<RefElement>();
-    myPersistentEntryPoints =
-        new LinkedHashMap<String, SmartRefElementPointer>(); // To keep the order between readExternal to writeExternal
-    Disposer.register(project, this);
-    final ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
-    point.addExtensionPointListener(new ExtensionPointListener<EntryPoint>() {
-      @Override
-      public void extensionAdded(@NotNull EntryPoint extension, @Nullable PluginDescriptor pluginDescriptor) {
-        extensionRemoved(extension, pluginDescriptor);
-      }
-
-      @Override
-      public void extensionRemoved(@NotNull EntryPoint extension, @Nullable PluginDescriptor pluginDescriptor) {
-        if (ADDITIONAL_ANNOS != null) {
-          ADDITIONAL_ANNOS = null;
-          UIUtil.invokeLaterIfNeeded(new Runnable() {
-            @Override
-            public void run() {
-              if (ApplicationManager.getApplication().isDisposed()) return;
-              InspectionProfileManager.getInstance().fireProfileChanged(null);
-            }
-          });
-        }
-      }
-    }, this);
-  }
-
-  public static EntryPointsManagerImpl getInstance(Project project) {
-    return ServiceManager.getService(project, EntryPointsManagerImpl.class);
-  }
-
-  @Override
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  public void loadState(Element element) {
-    Element entryPointsElement = element.getChild("entry_points");
-    if (entryPointsElement != null) {
-      final String version = entryPointsElement.getAttributeValue(VERSION_ATTR);
-      if (!Comparing.strEqual(version, VERSION)) {
-        convert(entryPointsElement, myPersistentEntryPoints);
-      }
-      else {
-        List content = entryPointsElement.getChildren();
-        for (final Object aContent : content) {
-          Element entryElement = (Element)aContent;
-          if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
-            SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(entryElement);
-            myPersistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
-          }
-        }
-      }
-    }
-    try {
-      ADDITIONAL_ANNOTATIONS.readExternal(element);
-    }
-    catch (InvalidDataException ignored) {
-    }
-  }
-
-  @Override
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  public Element getState()  {
-    Element element = new Element("state");
-    writeExternal(element, myPersistentEntryPoints, ADDITIONAL_ANNOTATIONS);
-    return element;
-  }
-
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  public static void writeExternal(final Element element,
-                            final Map<String, SmartRefElementPointer> persistentEntryPoints,
-                            final JDOMExternalizableStringList additional_annotations) {
-    Element entryPointsElement = new Element("entry_points");
-    entryPointsElement.setAttribute(VERSION_ATTR, VERSION);
-    for (SmartRefElementPointer entryPoint : persistentEntryPoints.values()) {
-      assert entryPoint.isPersistent();
-      entryPoint.writeExternal(entryPointsElement);
-    }
-
-    element.addContent(entryPointsElement);
-    if (!additional_annotations.isEmpty()) {
-      try {
-        additional_annotations.writeExternal(element);
-      }
-      catch (WriteExternalException ignored) {
-      }
-    }
-  }
-
-  @Override
-  public void resolveEntryPoints(final RefManager manager) {
-    if (!myResolved) {
-      myResolved = true;
-      cleanup();
-      validateEntryPoints();
-
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          for (SmartRefElementPointer entryPoint : myPersistentEntryPoints.values()) {
-            if (entryPoint.resolve(manager)) {
-              RefEntity refElement = entryPoint.getRefElement();
-              ((RefElementImpl)refElement).setEntry(true);
-              ((RefElementImpl)refElement).setPermanentEntry(entryPoint.isPersistent());
-            }
-          }
-        }
-      });
-    }
-  }
-
-  private void purgeTemporaryEntryPoints() {
-    for (RefElement entryPoint : myTemporaryEntryPoints) {
-      ((RefElementImpl)entryPoint).setEntry(false);
-    }
-
-    myTemporaryEntryPoints.clear();
-  }
-
-  @Override
-  public void addEntryPoint(RefElement newEntryPoint, boolean isPersistent) {
-    if (!newEntryPoint.isValid()) return;
-    if (newEntryPoint instanceof RefClass) {
-      RefClass refClass = (RefClass)newEntryPoint;
-
-      if (refClass.isAnonymous()) {
-        // Anonymous class cannot be an entry point.
-        return;
-      }
-
-      List<RefMethod> refConstructors = refClass.getConstructors();
-      if (refConstructors.size() == 1) {
-        addEntryPoint(refConstructors.get(0), isPersistent);
-        return;
-      }
-      else if (refConstructors.size() > 1) {
-        // Many constructors here. Need to ask user which ones are used
-        for (int i = 0; i < refConstructors.size(); i++) {
-          addEntryPoint(refConstructors.get(i), isPersistent);
-        }
-
-        return;
-      }
-    }
-
-    if (!isPersistent) {
-      myTemporaryEntryPoints.add(newEntryPoint);
-      ((RefElementImpl)newEntryPoint).setEntry(true);
-    }
-    else {
-      if (myPersistentEntryPoints.get(newEntryPoint.getExternalName()) == null) {
-        final SmartRefElementPointerImpl entry = new SmartRefElementPointerImpl(newEntryPoint, true);
-        myPersistentEntryPoints.put(entry.getFQName(), entry);
-        ((RefElementImpl)newEntryPoint).setEntry(true);
-        ((RefElementImpl)newEntryPoint).setPermanentEntry(true);
-        if (entry.isPersistent()) { //do save entry points
-          final EntryPointsManagerImpl entryPointsManager = getInstance(newEntryPoint.getElement().getProject());
-          if (this != entryPointsManager) {
-            entryPointsManager.addEntryPoint(newEntryPoint, true);
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  public void removeEntryPoint(RefElement anEntryPoint) {
-    if (anEntryPoint instanceof RefClass) {
-      RefClass refClass = (RefClass)anEntryPoint;
-      if (!refClass.isInterface()) {
-        anEntryPoint = refClass.getDefaultConstructor();
-      }
-    }
-
-    if (anEntryPoint == null) return;
-
-    myTemporaryEntryPoints.remove(anEntryPoint);
-
-    Set<Map.Entry<String, SmartRefElementPointer>> set = myPersistentEntryPoints.entrySet();
-    String key = null;
-    for (Map.Entry<String, SmartRefElementPointer> entry : set) {
-      SmartRefElementPointer value = entry.getValue();
-      if (value.getRefElement() == anEntryPoint) {
-        key = entry.getKey();
-        break;
-      }
-    }
-
-    if (key != null) {
-      myPersistentEntryPoints.remove(key);
-      ((RefElementImpl)anEntryPoint).setEntry(false);
-    }
-
-    if (anEntryPoint.isPermanentEntry() && anEntryPoint.isValid()) {
-      final Project project = anEntryPoint.getElement().getProject();
-      final EntryPointsManagerImpl entryPointsManager = getInstance(project);
-      if (this != entryPointsManager) {
-        entryPointsManager.removeEntryPoint(anEntryPoint);
-      }
-    }
-  }
-
-  @Override
-  public RefElement[] getEntryPoints() {
-    validateEntryPoints();
-    List<RefElement> entries = new ArrayList<RefElement>();
-    Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
-    for (SmartRefElementPointer refElementPointer : collection) {
-      final RefEntity elt = refElementPointer.getRefElement();
-      if (elt instanceof RefElement) {
-        entries.add((RefElement)elt);
-      }
-    }
-    entries.addAll(myTemporaryEntryPoints);
-
-    return entries.toArray(new RefElement[entries.size()]);
-  }
-
-  @Override
-  public void dispose() {
-    cleanup();
-  }
-
-  private void validateEntryPoints() {
-    long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
-    if (count != myLastModificationCount) {
-      myLastModificationCount = count;
-      Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
-      SmartRefElementPointer[] entries = collection.toArray(new SmartRefElementPointer[collection.size()]);
-      for (SmartRefElementPointer entry : entries) {
-        RefElement refElement = (RefElement)entry.getRefElement();
-        if (refElement != null && !refElement.isValid()) {
-          myPersistentEntryPoints.remove(entry.getFQName());
-        }
-      }
-
-      final Iterator<RefElement> it = myTemporaryEntryPoints.iterator();
-      while (it.hasNext()) {
-        RefElement refElement = it.next();
-        if (!refElement.isValid()) {
-          it.remove();
-        }
-      }
-    }
-  }
-
-  @Override
-  public void cleanup() {
-    purgeTemporaryEntryPoints();
-    Collection<SmartRefElementPointer> entries = myPersistentEntryPoints.values();
-    for (SmartRefElementPointer entry : entries) {
-      entry.freeReference();
-    }
-  }
-
-  @Override
-  public boolean isAddNonJavaEntries() {
-    return myAddNonJavaEntries;
+    super(project);
   }
 
   @Override
   public void configureAnnotations() {
-    final ArrayList<String> list = new ArrayList<String>(ADDITIONAL_ANNOTATIONS);
+    final List<String> list = new ArrayList<String>(ADDITIONAL_ANNOTATIONS);
     final JPanel listPanel = SpecialAnnotationsUtil.createSpecialAnnotationsListControl(list, "Do not check if annotated by", true);
     new DialogWrapper(myProject) {
       {
@@ -379,77 +71,15 @@
     }.show();
   }
 
-  public static JButton createConfigureAnnotationsBtn(final JComponent parent) {
+  @Override
+  public JButton createConfigureAnnotationsBtn() {
     final JButton configureAnnotations = new JButton("Configure annotations...");
     configureAnnotations.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
-        Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parent));
-        if (project == null) project = ProjectManager.getInstance().getDefaultProject();
-        EntryPointsManagerImpl.getInstance(project).configureAnnotations();
+        configureAnnotations();
       }
     });
     return configureAnnotations;
   }
-
-  public void addAllPersistentEntries(EntryPointsManagerImpl manager) {
-    myPersistentEntryPoints.putAll(manager.myPersistentEntryPoints);
-  }
-
-  public static void convert(Element element, final Map<String, SmartRefElementPointer> persistentEntryPoints) {
-    List content = element.getChildren();
-    for (final Object aContent : content) {
-      Element entryElement = (Element)aContent;
-      if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
-        String fqName = entryElement.getAttributeValue(SmartRefElementPointerImpl.FQNAME_ATTR);
-        final String type = entryElement.getAttributeValue(SmartRefElementPointerImpl.TYPE_ATTR);
-        if (Comparing.strEqual(type, RefJavaManager.METHOD)) {
-
-          int spaceIdx = fqName.indexOf(' ');
-          int lastDotIdx = fqName.lastIndexOf('.');
-
-          int parenIndex = fqName.indexOf('(');
-
-          while (lastDotIdx > parenIndex) lastDotIdx = fqName.lastIndexOf('.', lastDotIdx - 1);
-
-          boolean notype = false;
-          if (spaceIdx < 0 || spaceIdx + 1 > lastDotIdx || spaceIdx > parenIndex) {
-            notype = true;
-          }
-
-          final String className = fqName.substring(notype ? 0 : spaceIdx + 1, lastDotIdx);
-          final String methodSignature =
-              notype ? fqName.substring(lastDotIdx + 1) : fqName.substring(0, spaceIdx) + ' ' + fqName.substring(lastDotIdx + 1);
-
-          fqName = className + " " + methodSignature;
-        }
-        else if (Comparing.strEqual(type, RefJavaManager.FIELD)) {
-          final int lastDotIdx = fqName.lastIndexOf('.');
-          if (lastDotIdx > 0 && lastDotIdx < fqName.length() - 2) {
-            String className = fqName.substring(0, lastDotIdx);
-            String fieldName = fqName.substring(lastDotIdx + 1);
-            fqName = className + " " + fieldName;
-          }
-          else {
-            continue;
-          }
-        }
-        SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(type, fqName);
-        persistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
-      }
-    }
-  }
-
-  public void setAddNonJavaEntries(final boolean addNonJavaEntries) {
-    myAddNonJavaEntries = addNonJavaEntries;
-  }
-
-  public boolean isEntryPoint(@NotNull PsiModifierListOwner element) {
-    if (!ADDITIONAL_ANNOTATIONS.isEmpty() && ADDITIONAL_ANNOTATIONS.contains(Deprecated.class.getName()) &&
-        element instanceof PsiDocCommentOwner && ((PsiDocCommentOwner)element).isDeprecated()) {
-      return true;
-    }
-    return AnnotationUtil.isAnnotated(element, ADDITIONAL_ANNOTATIONS) ||
-           AnnotationUtil.isAnnotated(element, getAdditionalAnnotations());
-  }
 }
diff --git a/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java b/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
index 4c0e222..ecd1dca 100644
--- a/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
@@ -27,7 +27,7 @@
 import com.intellij.codeInspection.reference.RefModule;
 import com.intellij.codeInspection.unnecessaryModuleDependency.UnnecessaryModuleDependencyInspection;
 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.project.ProjectBundle;
 import com.intellij.openapi.roots.*;
@@ -44,6 +44,11 @@
 
 public class InconsistentLanguageLevelInspection extends GlobalInspectionTool {
   @Override
+  public boolean isGraphNeeded() {
+    return false;
+  }
+
+  @Override
   public void runInspection(@NotNull AnalysisScope scope,
                             @NotNull InspectionManager manager,
                             @NotNull GlobalInspectionContext globalContext,
@@ -52,7 +57,7 @@
     scope.accept(new PsiElementVisitor(){
       @Override
       public void visitElement(PsiElement element) {
-        final Module module = ModuleUtil.findModuleForPsiElement(element);
+        final Module module = ModuleUtilCore.findModuleForPsiElement(element);
         if (module != null) {
           modules.add(module);
         }
diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
index 2a82958..4f9fa88 100644
--- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
@@ -51,6 +51,10 @@
     PsiElement pos = parameters.getPosition();
     MagicConstantInspection.AllowedValues allowedValues = null;
 
+    if (JavaCompletionData.AFTER_DOT.accepts(pos)) {
+      return;
+    }
+
     if (IN_METHOD_CALL_ARGUMENT.accepts(pos)) {
       PsiCall call = PsiTreeUtil.getParentOfType(pos, PsiCall.class);
       if (!(call instanceof PsiExpression)) return;
diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
index f185806..7193cc9 100644
--- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
@@ -55,6 +55,8 @@
 import java.util.*;
 
 public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
+  public static final Key<Boolean> NO_ANNOTATIONS_FOUND = Key.create("REPORTED_NO_ANNOTATIONS_FOUND");
+
   @Nls
   @NotNull
   @Override
@@ -152,8 +154,19 @@
     };
   }
 
+  @Override
+  public void cleanup(Project project) {
+    super.cleanup(project);
+    project.putUserData(NO_ANNOTATIONS_FOUND, null);
+  }
+
   private static void checkAnnotationsJarAttached(@NotNull PsiFile file, @NotNull ProblemsHolder holder) {
     final Project project = file.getProject();
+    if (!holder.isOnTheFly()) {
+      final Boolean found = project.getUserData(NO_ANNOTATIONS_FOUND);
+      if (found != null) return;
+    }
+
     PsiClass event = JavaPsiFacade.getInstance(project).findClass("java.awt.event.InputEvent", GlobalSearchScope.allScope(project));
     if (event == null) return; // no jdk to attach
     PsiMethod[] methods = event.findMethodsByName("getModifiers", false);
@@ -172,6 +185,11 @@
       }
     }
     if (jdk == null) return; // no jdk to attach
+
+    if (!holder.isOnTheFly()) {
+      project.putUserData(NO_ANNOTATIONS_FOUND, Boolean.TRUE);
+    }
+
     final Sdk finalJdk = jdk;
 
     String path = finalJdk.getHomePath();
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
deleted file mode 100644
index 8c9cda6..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 21, 2001
- * Time: 4:29:19 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInsight.TestFrameworks;
-import com.intellij.lang.injection.InjectedLanguageManager;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.util.ClassUtil;
-import com.intellij.psi.util.PsiFormatUtil;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-public class RefClassImpl extends RefJavaElementImpl implements RefClass {
-  private static final Set<RefElement> EMPTY_SET = Collections.emptySet();
-  private static final Set<RefClass> EMPTY_CLASS_SET = Collections.emptySet();
-  private static final List<RefMethod> EMPTY_METHOD_LIST = new ArrayList<RefMethod>(0);
-  private static final int IS_ANONYMOUS_MASK = 0x10000;
-  private static final int IS_INTERFACE_MASK = 0x20000;
-  private static final int IS_UTILITY_MASK   = 0x40000;
-  private static final int IS_ABSTRACT_MASK  = 0x80000;
-
-  private static final int IS_APPLET_MASK    = 0x200000;
-  private static final int IS_SERVLET_MASK   = 0x400000;
-  private static final int IS_TESTCASE_MASK  = 0x800000;
-  private static final int IS_LOCAL_MASK     = 0x1000000;
-
-  private Set<RefClass> myBases; // singleton (to conserve the memory) or THashSet
-  private Set<RefClass> mySubClasses; // singleton (to conserve the memory) or THashSet
-  private List<RefMethod> myConstructors;
-  private RefMethodImpl myDefaultConstructor;
-  private List<RefMethod> myOverridingMethods;
-  private Set<RefElement> myInTypeReferences;
-  private Set<RefElement> myInstanceReferences;
-  private List<RefJavaElement> myClassExporters;
-
-  RefClassImpl(PsiClass psiClass, RefManager manager) {
-    super(psiClass, manager);
-  }
-
-  @Override
-  protected void initialize() {
-    myDefaultConstructor = null;
-
-    final PsiClass psiClass = getElement();
-
-    LOG.assertTrue(psiClass != null);
-
-    PsiElement psiParent = psiClass.getParent();
-    if (psiParent instanceof PsiFile) {
-      if (isSyntheticJSP()) {
-        final RefFileImpl refFile = (RefFileImpl)getRefManager().getReference(JspPsiUtil.getJspFile(psiClass));
-        LOG.assertTrue(refFile != null);
-        refFile.add(this);
-      } else if (psiParent instanceof PsiJavaFile) {
-        PsiJavaFile psiFile = (PsiJavaFile) psiParent;
-        String packageName = psiFile.getPackageName();
-        if (!"".equals(packageName)) {
-          ((RefPackageImpl)getRefJavaManager().getPackage(packageName)).add(this);
-        } else {
-          ((RefPackageImpl)getRefJavaManager().getDefaultPackage()).add(this);
-        }
-      }
-      final Module module = ModuleUtil.findModuleForPsiElement(psiClass);
-      LOG.assertTrue(module != null);
-      final RefModuleImpl refModule = ((RefModuleImpl)getRefManager().getRefModule(module));
-      LOG.assertTrue(refModule != null);
-      refModule.add(this);
-    } else {
-      while (!(psiParent instanceof PsiClass || psiParent instanceof PsiMethod || psiParent instanceof PsiField)) {
-        psiParent = psiParent.getParent();
-      }
-      RefElement refParent = getRefManager().getReference(psiParent);
-      LOG.assertTrue (refParent != null);
-      ((RefElementImpl)refParent).add(this);
-
-    }
-
-    setAbstract(psiClass.hasModifierProperty(PsiModifier.ABSTRACT));
-
-    setAnonymous(psiClass instanceof PsiAnonymousClass);
-    setIsLocal(!(isAnonymous() || psiParent instanceof PsiClass || psiParent instanceof PsiFile));
-    setInterface(psiClass.isInterface());
-
-    initializeSuperReferences(psiClass);
-
-    PsiMethod[] psiMethods = psiClass.getMethods();
-    PsiField[] psiFields = psiClass.getFields();
-
-    setUtilityClass(psiMethods.length > 0 || psiFields.length > 0);
-
-    for (PsiField psiField : psiFields) {
-      getRefManager().getReference(psiField);
-    }
-
-    if (!isApplet()) {
-      final PsiClass servlet = getRefJavaManager().getServlet();
-      setServlet(servlet != null && psiClass.isInheritor(servlet, true));
-    }
-    if (!isApplet() && !isServlet()) {
-      final boolean isTestClass = TestFrameworks.getInstance().isTestClass(psiClass);
-      setTestCase(isTestClass);
-      if (isTestClass) {
-        for (RefClass refBase : getBaseClasses()) {
-          ((RefClassImpl)refBase).setTestCase(true);
-        }
-      }
-    }
-
-    for (PsiMethod psiMethod : psiMethods) {
-      RefMethod refMethod = (RefMethod)getRefManager().getReference(psiMethod);
-
-      if (refMethod != null) {
-        if (psiMethod.isConstructor()) {
-          if (psiMethod.getParameterList().getParametersCount() > 0 || !psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) {
-            setUtilityClass(false);
-          }
-
-          addConstructor(refMethod);
-          if (psiMethod.getParameterList().getParametersCount() == 0) {
-            setDefaultConstructor((RefMethodImpl)refMethod);
-          }
-        }
-        else {
-          if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
-            setUtilityClass(false);
-          }
-        }
-      }
-    }
-
-    if (getConstructors().isEmpty() && !isInterface() && !isAnonymous()) {
-      RefImplicitConstructorImpl refImplicitConstructor = new RefImplicitConstructorImpl(this);
-      setDefaultConstructor(refImplicitConstructor);
-      addConstructor(refImplicitConstructor);
-    }
-
-    if (isInterface()) {
-      for (int i = 0; i < psiFields.length && isUtilityClass(); i++) {
-        PsiField psiField = psiFields[i];
-        if (!psiField.hasModifierProperty(PsiModifier.STATIC)) {
-          setUtilityClass(false);
-        }
-      }
-    }
-
-
-    final PsiClass applet = getRefJavaManager().getApplet();
-    setApplet(applet != null && psiClass.isInheritor(applet, true));
-    PsiManager psiManager = getRefManager().getPsiManager();
-    psiManager.dropResolveCaches();
-    PsiFile file = psiClass.getContainingFile();
-    if (file != null) {
-      InjectedLanguageManager.getInstance(file.getProject()).dropFileCaches(file);
-    }
-  }
-
-  private void initializeSuperReferences(PsiClass psiClass) {
-    if (!isSelfInheritor(psiClass)) {
-      for (PsiClass psiSuperClass : psiClass.getSupers()) {
-        if (getRefManager().belongsToScope(psiSuperClass)) {
-          RefClassImpl refClass = (RefClassImpl)getRefManager().getReference(psiSuperClass);
-          if (refClass != null) {
-            addBaseClass(refClass);
-            refClass.addSubClass(this);
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  public boolean isSelfInheritor(PsiClass psiClass) {
-    return isSelfInheritor(psiClass, new ArrayList<PsiClass>());
-  }
-
-  @Override
-  public PsiClass getElement() {
-    return (PsiClass)super.getElement();
-  }
-
-  private static boolean isSelfInheritor(PsiClass psiClass, ArrayList<PsiClass> visited) {
-    if (visited.contains(psiClass)) return true;
-
-    visited.add(psiClass);
-    for (PsiClass aSuper : psiClass.getSupers()) {
-      if (isSelfInheritor(aSuper, visited)) return true;
-    }
-    visited.remove(psiClass);
-
-    return false;
-  }
-
-  private void setDefaultConstructor(RefMethodImpl defaultConstructor) {
-    if (defaultConstructor != null) {
-      for (RefClass superClass : getBaseClasses()) {
-        RefMethodImpl superDefaultConstructor = (RefMethodImpl)superClass.getDefaultConstructor();
-
-        if (superDefaultConstructor != null) {
-          superDefaultConstructor.addInReference(defaultConstructor);
-          defaultConstructor.addOutReference(superDefaultConstructor);
-        }
-      }
-    }
-
-    myDefaultConstructor = defaultConstructor;
-  }
-
-  @Override
-  public void buildReferences() {
-    PsiClass psiClass = getElement();
-
-    if (psiClass != null) {
-      for (PsiClassInitializer classInitializer : psiClass.getInitializers()) {
-        RefJavaUtil.getInstance().addReferences(psiClass, this, classInitializer.getBody());
-      }
-
-      RefJavaUtil.getInstance().addReferences(psiClass, this, psiClass.getModifierList());
-
-      PsiField[] psiFields = psiClass.getFields();
-      for (PsiField psiField : psiFields) {
-        getRefManager().getReference(psiField);
-        final PsiExpression initializer = psiField.getInitializer();
-        if (initializer != null) {
-          RefJavaUtil.getInstance().addReferences(psiClass, this, initializer);
-        }
-      }
-
-      PsiMethod[] psiMethods = psiClass.getMethods();
-      for (PsiMethod psiMethod : psiMethods) {
-        getRefManager().getReference(psiMethod);
-      }
-      getRefManager().fireBuildReferences(this);
-    }
-  }
-
-  @Override
-  public void accept(@NotNull final RefVisitor visitor) {
-    if (visitor instanceof RefJavaVisitor) {
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          ((RefJavaVisitor)visitor).visitClass(RefClassImpl.this);
-        }
-      });
-    } else {
-      super.accept(visitor);
-    }
-  }
-
-  @Override
-  @NotNull
-  public Set<RefClass> getBaseClasses() {
-    if (myBases == null) return EMPTY_CLASS_SET;
-    return myBases;
-  }
-
-  private void addBaseClass(RefClass refClass){
-    if (myBases == null) {
-      myBases = Collections.singleton(refClass);
-      return;
-    }
-    if (myBases.size() == 1) {
-      // convert from singleton
-      myBases = new THashSet<RefClass>(myBases);
-    }
-    myBases.add(refClass);
-  }
-
-  @Override
-  @NotNull
-  public Set<RefClass> getSubClasses() {
-    if (mySubClasses == null) return EMPTY_CLASS_SET;
-    return mySubClasses;
-  }
-
-  private void addSubClass(@NotNull RefClass refClass){
-    if (mySubClasses == null) {
-      mySubClasses = Collections.singleton(refClass);
-      return;
-    }
-    if (mySubClasses.size() == 1) {
-      // convert from singleton
-      mySubClasses = new THashSet<RefClass>(mySubClasses);
-    }
-    mySubClasses.add(refClass);
-  }
-  private void removeSubClass(RefClass refClass){
-    if (mySubClasses == null) return;
-    if (mySubClasses.size() == 1) {
-      mySubClasses = null;
-    }
-    else {
-      mySubClasses.remove(refClass);
-    }
-  }
-
-  @Override
-  @NotNull
-  public List<RefMethod> getConstructors() {
-    if (myConstructors == null) return EMPTY_METHOD_LIST;
-    return myConstructors;
-  }
-
-  @Override
-  @NotNull
-  public Set<RefElement> getInTypeReferences() {
-    if (myInTypeReferences == null) return EMPTY_SET;
-    return myInTypeReferences;
-  }
-
-  public void addTypeReference(RefJavaElement from) {
-    if (from != null) {
-      if (myInTypeReferences == null){
-        myInTypeReferences = new THashSet<RefElement>(1);
-      }
-      myInTypeReferences.add(from);
-      ((RefJavaElementImpl)from).addOutTypeRefernce(this);
-      getRefManager().fireNodeMarkedReferenced(this, from, false, false, false);
-    }
-  }
-
-  @Override
-  @NotNull
-  public Set<RefElement> getInstanceReferences() {
-    if (myInstanceReferences == null) return EMPTY_SET;
-    return myInstanceReferences;
-  }
-
-  public void addInstanceReference(RefElement from) {
-    if (myInstanceReferences == null){
-      myInstanceReferences = new THashSet<RefElement>(1);
-    }
-    myInstanceReferences.add(from);
-  }
-
-  @Override
-  public RefMethod getDefaultConstructor() {
-    return myDefaultConstructor;
-  }
-
-  private void addConstructor(RefMethod refConstructor) {
-    if (myConstructors == null){
-      myConstructors = new ArrayList<RefMethod>(1);
-    }
-    myConstructors.add(refConstructor);
-  }
-
-  public void addLibraryOverrideMethod(RefMethod refMethod) {
-    if (myOverridingMethods == null){
-      myOverridingMethods = new ArrayList<RefMethod>(2);
-    }
-    myOverridingMethods.add(refMethod);
-  }
-
-  @Override
-  @NotNull
-  public List<RefMethod> getLibraryMethods() {
-    if (myOverridingMethods == null) return EMPTY_METHOD_LIST;
-    return myOverridingMethods;
-  }
-
-  @Override
-  public boolean isAnonymous() {
-    return checkFlag(IS_ANONYMOUS_MASK);
-  }
-
-  @Override
-  public boolean isInterface() {
-    return checkFlag(IS_INTERFACE_MASK);
-  }
-
-  @Override
-  public boolean isSuspicious() {
-    return !(isUtilityClass() && getOutReferences().isEmpty()) && super.isSuspicious();
-  }
-
-  @Override
-  public boolean isUtilityClass() {
-    return checkFlag(IS_UTILITY_MASK);
-  }
-
-  @Override
-  public String getExternalName() {
-    final String[] result = new String[1];
-    ApplicationManager.getApplication().runReadAction(new Runnable() {
-      @Override
-      public void run() {//todo synthetic JSP
-        final PsiClass psiClass = getElement();
-        LOG.assertTrue(psiClass != null);
-        result[0] = PsiFormatUtil.getExternalName(psiClass);
-      }
-    });
-    return result[0];
-  }
-
-
-  @Nullable
-  public static RefClass classFromExternalName(RefManager manager, String externalName) {
-    return (RefClass) manager.getReference(ClassUtil.findPsiClass(PsiManager.getInstance(manager.getProject()), externalName));
-  }
-
-  @Override
-  public void referenceRemoved() {
-    super.referenceRemoved();
-
-    for (RefClass subClass : getSubClasses()) {
-      ((RefClassImpl)subClass).removeBase(this);
-    }
-
-    for (RefClass superClass : getBaseClasses()) {
-      ((RefClassImpl)superClass).removeSubClass(this);
-    }
-  }
-
-  private void removeBase(RefClass superClass) {
-    final Set<RefClass> baseClasses = getBaseClasses();
-    if (baseClasses.contains(superClass)) {
-      if (baseClasses.size() == 1) {
-        myBases = null;
-        return;
-      }
-      baseClasses.remove(superClass);
-    }
-  }
-
-  protected void methodRemoved(RefMethod method) {
-    getConstructors().remove(method);
-    getLibraryMethods().remove(method);
-
-    if (getDefaultConstructor() == method) {
-      setDefaultConstructor(null);
-    }
-  }
-
-  @Override
-  public boolean isAbstract() {
-    return checkFlag(IS_ABSTRACT_MASK);
-  }
-
-  @Override
-  public boolean isApplet() {
-    return checkFlag(IS_APPLET_MASK);
-  }
-
-  @Override
-  public boolean isServlet() {
-    return checkFlag(IS_SERVLET_MASK);
-  }
-
-  @Override
-  public boolean isTestCase() {
-    return checkFlag(IS_TESTCASE_MASK);
-  }
-
-  @Override
-  public boolean isLocalClass() {
-    return checkFlag(IS_LOCAL_MASK);
-  }
-
-
-  @Override
-  public boolean isReferenced() {
-    if (super.isReferenced()) return true;
-
-    if (isInterface() || isAbstract()) {
-      if (!getSubClasses().isEmpty()) return true;
-    }
-
-    return false;
-  }
-
-  @Override
-  public boolean hasSuspiciousCallers() {
-    if (super.hasSuspiciousCallers()) return true;
-
-    if (isInterface() || isAbstract()) {
-      if (!getSubClasses().isEmpty()) return true;
-    }
-
-    return false;
-  }
-
-  public void addClassExporter(RefJavaElement exporter) {
-    if (myClassExporters == null) myClassExporters = new ArrayList<RefJavaElement>(1);
-    if (myClassExporters.contains(exporter)) return;
-    myClassExporters.add(exporter);
-  }
-
-  public List<RefJavaElement> getClassExporters() {
-    return myClassExporters;
-  }
-
-  private void setAnonymous(boolean anonymous) {
-    setFlag(anonymous, IS_ANONYMOUS_MASK);
-  }
-
-  private void setInterface(boolean anInterface) {
-    setFlag(anInterface, IS_INTERFACE_MASK);
-  }
-
-  private void setUtilityClass(boolean utilityClass) {
-    setFlag(utilityClass, IS_UTILITY_MASK);
-  }
-
-  private void setAbstract(boolean anAbstract) {
-    setFlag(anAbstract, IS_ABSTRACT_MASK);
-  }
-
-  private void setApplet(boolean applet) {
-    setFlag(applet, IS_APPLET_MASK);
-  }
-
-  private void setServlet(boolean servlet) {
-    setFlag(servlet, IS_SERVLET_MASK);
-  }
-
-  private void setTestCase(boolean testCase) {
-    setFlag(testCase, IS_TESTCASE_MASK);
-  }
-
-  private void setIsLocal(boolean isLocal) {
-    setFlag(isLocal, IS_LOCAL_MASK);
-  }
-
-  @Override
-  @NotNull
-  public RefElement getContainingEntry() {
-    RefElement defaultConstructor = getDefaultConstructor();
-    if (defaultConstructor != null) return defaultConstructor;
-    return super.getContainingEntry();
-  }
-}
-
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java
deleted file mode 100644
index 35262e3..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Computable;
-import com.intellij.psi.*;
-import com.intellij.psi.util.ClassUtil;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author max
- * Date: Oct 21, 2001
- */
-public class RefFieldImpl extends RefJavaElementImpl implements RefField {
-  private static final int USED_FOR_READING_MASK = 0x10000;
-  private static final int USED_FOR_WRITING_MASK = 0x20000;
-  private static final int ASSIGNED_ONLY_IN_INITIALIZER = 0x40000;
-
-  RefFieldImpl(@NotNull RefClass ownerClass, PsiField field, RefManager manager) {
-    super(field, manager);
-
-    ((RefClassImpl)ownerClass).add(this);
-
-    if (ownerClass.isInterface()) {
-      setIsStatic(true);
-      setIsFinal(true);
-    }
-  }
-
-  @Override
-  public PsiField getElement() {
-    return (PsiField)super.getElement();
-  }
-
-  @Override
-  protected void markReferenced(RefElementImpl refFrom, PsiElement psiFrom, PsiElement psiWhat, boolean forWriting, boolean forReading, PsiReferenceExpression expressionFrom) {
-    addInReference(refFrom);
-
-    boolean referencedFromClassInitializer = false;
-
-    if (forWriting && expressionFrom != null) {
-      PsiClassInitializer initializer = PsiTreeUtil.getParentOfType(expressionFrom, PsiClassInitializer.class);
-      if (initializer != null) {
-        if (initializer.getParent() instanceof PsiClass && psiFrom == initializer.getParent() && !expressionFrom.isQualified()) {
-          referencedFromClassInitializer = true;
-        }
-      }
-    }
-
-    if (forWriting) {
-      setUsedForWriting(true);
-    }
-
-    if (forReading) {
-      setUsedForReading(true);
-    }
-    getRefManager().fireNodeMarkedReferenced(this, refFrom, referencedFromClassInitializer, forReading, forWriting);
-  }
-
-  @Override
-  public boolean isUsedForReading() {
-    return checkFlag(USED_FOR_READING_MASK);
-  }
-
-  private void setUsedForReading(boolean usedForReading) {
-    setFlag(usedForReading, USED_FOR_READING_MASK);
-  }
-
-  @Override
-  public boolean isUsedForWriting() {
-    return checkFlag(USED_FOR_WRITING_MASK);
-  }
-
-  private void setUsedForWriting(boolean usedForWriting) {
-    setFlag(false, ASSIGNED_ONLY_IN_INITIALIZER);
-    setFlag(usedForWriting, USED_FOR_WRITING_MASK);
-  }
-
-  @Override
-  public boolean isOnlyAssignedInInitializer() {
-    return checkFlag(ASSIGNED_ONLY_IN_INITIALIZER);
-  }
-
-  @Override
-  public void accept(@NotNull final RefVisitor visitor) {
-    if (visitor instanceof RefJavaVisitor) {
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          ((RefJavaVisitor)visitor).visitField(RefFieldImpl.this);
-        }
-      });
-    }  else {
-      super.accept(visitor);
-    }
-  }
-
-  @Override
-  public void buildReferences() {
-    PsiField psiField = getElement();
-    if (psiField != null) {
-      final RefJavaUtil refUtil = RefJavaUtil.getInstance();
-      refUtil.addReferences(psiField, this, psiField.getInitializer());
-      refUtil.addReferences(psiField, this, psiField.getModifierList());
-      if (psiField instanceof PsiEnumConstant) {
-        refUtil.addReferences(psiField, this, psiField);
-      }
-
-      if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant) {
-        if (!checkFlag(USED_FOR_WRITING_MASK)) {
-          setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER);
-          setFlag(true, USED_FOR_WRITING_MASK);
-        }
-      }
-      PsiType psiType = psiField.getType();
-      RefClass ownerClass = refUtil.getOwnerClass(getRefManager(), psiField);
-
-      if (ownerClass != null) {
-        psiType = psiType.getDeepComponentType();
-        if (psiType instanceof PsiClassType) {
-          PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
-          if (psiClass != null && getRefManager().belongsToScope(psiClass)) {
-              RefClassImpl refClass = (RefClassImpl)getRefManager().getReference(psiClass);
-            if (refClass != null) {
-              refClass.addTypeReference(ownerClass);
-              refClass.addClassExporter(this);
-            }
-          }
-        }
-
-      }
-      getRefManager().fireBuildReferences(this);
-    }
-  }
-
-  @Override
-  public RefClass getOwnerClass() {
-    return (RefClass) getOwner();
-  }
-
-  @Override
-  public String getExternalName() {
-    return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
-      @Override
-      public String compute() {
-        PsiField psiField = getElement();
-        return psiField != null ? PsiFormatUtil.getExternalName(psiField) : null;
-      }
-    });
-  }
-
-  @Nullable
-  public static RefField fieldFromExternalName(RefManager manager, String externalName) {
-    return (RefField)manager.getReference(findPsiField(PsiManager.getInstance(manager.getProject()), externalName));
-  }
-
-  @Nullable
-  public static PsiField findPsiField(PsiManager manager, String externalName) {
-    int classNameDelimeter = externalName.lastIndexOf(' ');
-    if (classNameDelimeter > 0 && classNameDelimeter < externalName.length() - 1) {
-      final String className = externalName.substring(0, classNameDelimeter);
-      final String fieldName = externalName.substring(classNameDelimeter + 1);
-      final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
-      if (psiClass != null) {
-        return psiClass.findFieldByName(fieldName, false);
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public boolean isSuspicious() {
-    if (isEntry()) return false;
-    if (super.isSuspicious()) return true;
-    return isUsedForReading() != isUsedForWriting();
-  }
-
-  @Override
-  protected void initialize() {
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
deleted file mode 100644
index 7dd9282..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Nov 28, 2001
- * Time: 4:17:17 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Computable;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiModifierListOwner;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class RefImplicitConstructorImpl extends RefMethodImpl implements RefImplicitConstructor {
-
-  RefImplicitConstructorImpl(RefClass ownerClass) {
-    super(InspectionsBundle.message("inspection.reference.implicit.constructor.name", ownerClass.getName()), ownerClass);
-  }
-
-  @Override
-  public void buildReferences() {
-    getRefManager().fireBuildReferences(this);
-  }
-
-  @Override
-  public boolean isSuspicious() {
-    return ((RefClassImpl)getOwnerClass()).isSuspicious();
-  }
-
-  @NotNull
-  @Override
-  public String getName() {
-    return InspectionsBundle.message("inspection.reference.implicit.constructor.name", getOwnerClass().getName());
-  }
-
-  @Override
-  public String getExternalName() {
-    return getOwnerClass().getExternalName();
-  }
-
-  @Override
-  public boolean isValid() {
-    return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
-      @Override
-      public Boolean compute() {
-        return getOwnerClass().isValid();
-      }
-    }).booleanValue();
-  }
-
-  @Override
-  public String getAccessModifier() {
-    return getOwnerClass().getAccessModifier();
-  }
-
-  @Override
-  public void setAccessModifier(String am) {
-    RefJavaUtil.getInstance().setAccessModifier(getOwnerClass(), am);
-  }
-
-  @Override
-  public PsiModifierListOwner getElement() {
-    return getOwnerClass().getElement();
-  }
-
-  @Override
-  @Nullable
-  public PsiFile getContainingFile() {
-    return ((RefClassImpl)getOwnerClass()).getContainingFile();
-  }
-
-  @Override
-  public RefClass getOwnerClass() {
-    return myOwnerClass;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java
deleted file mode 100644
index c0cd71e..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 20-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.openapi.util.Iconable;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
-import com.intellij.util.IconUtil;
-import com.intellij.util.containers.Stack;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-public abstract class RefJavaElementImpl extends RefElementImpl implements RefJavaElement {
-  private Set<RefClass> myOutTypeReferences;
-  private static final int ACCESS_MODIFIER_MASK = 0x03;
-  private static final int ACCESS_PRIVATE = 0x00;
-  private static final int ACCESS_PROTECTED = 0x01;
-  private static final int ACCESS_PACKAGE = 0x02;
-  private static final int ACCESS_PUBLIC = 0x03;
-  private static final int IS_STATIC_MASK = 0x04;
-  private static final int IS_FINAL_MASK = 0x08;
-  private static final int IS_USES_DEPRECATION_MASK = 0x200;
-  private static final int IS_SYNTHETIC_JSP_ELEMENT = 0x400;
-
-  protected RefJavaElementImpl(String name, @NotNull RefJavaElement owner) {
-    super(name, owner);
-    String am = owner.getAccessModifier();
-    doSetAccessModifier(am);
-
-    final boolean synthOwner = owner.isSyntheticJSP();
-    if (synthOwner) {
-      setSyntheticJSP(true);
-    }
-  }
-
-  protected RefJavaElementImpl(PsiFile file, RefManager manager) {
-    super(file, manager);
-  }
-
-  protected RefJavaElementImpl(PsiModifierListOwner elem, RefManager manager) {
-    super(getName(elem), elem, manager);
-
-    setAccessModifier(RefJavaUtil.getInstance().getAccessModifier(elem));
-    final boolean isSynth = elem instanceof JspHolderMethod || elem instanceof JspClass;
-    if (isSynth) {
-      setSyntheticJSP(true);
-    }
-
-    setIsStatic(elem.hasModifierProperty(PsiModifier.STATIC));
-    setIsFinal(elem.hasModifierProperty(PsiModifier.FINAL));
-  }
-
-  @Override
-  @NotNull
-  public Collection<RefClass> getOutTypeReferences() {
-    if (myOutTypeReferences == null){
-      return Collections.emptySet();
-    }
-    return myOutTypeReferences;
-  }
-
-  public void addOutTypeRefernce(RefClass refClass){
-    if (myOutTypeReferences == null){
-      myOutTypeReferences = new THashSet<RefClass>();
-    }
-    myOutTypeReferences.add(refClass);
-  }
-
-  public static String getName(PsiElement element) {
-   if (element instanceof PsiAnonymousClass) {
-     PsiAnonymousClass psiAnonymousClass = (PsiAnonymousClass)element;
-     PsiClass psiBaseClass = psiAnonymousClass.getBaseClassType().resolve();
-     return InspectionsBundle.message("inspection.reference.anonymous.name", psiBaseClass == null ? "" : psiBaseClass.getQualifiedName());
-   }
-
-   if (element instanceof JspClass) {
-     final JspClass jspClass = (JspClass)element;
-     final PsiFile jspxFile = jspClass.getContainingFile();
-     return "<" + jspxFile.getName() + ">";
-   }
-
-   if (element instanceof JspHolderMethod) {
-     return InspectionsBundle.message("inspection.reference.jsp.holder.method.anonymous.name");
-   }
-
-   String name = null;
-   if (element instanceof PsiNamedElement) {
-     name = ((PsiNamedElement)element).getName();
-   }
-
-   return name == null ? InspectionsBundle.message("inspection.reference.anonymous") : name;
- }
-
-  @Override
-  public boolean isFinal() {
-    return checkFlag(IS_FINAL_MASK);
-  }
-
-  @Override
-  public boolean isStatic() {
-    return checkFlag(IS_STATIC_MASK);
-  }
-
-  public void setIsStatic(boolean isStatic) {
-    setFlag(isStatic, IS_STATIC_MASK);
-  }
-
-  @Override
-  public boolean isUsesDeprecatedApi() {
-    return checkFlag(IS_USES_DEPRECATION_MASK);
-  }
-
-  public void setUsesDeprecatedApi(boolean usesDeprecatedApi) {
-    setFlag(usesDeprecatedApi, IS_USES_DEPRECATION_MASK);
-  }
-
-  public void setIsFinal(boolean isFinal) {
-    setFlag(isFinal, IS_FINAL_MASK);
-  }
-
-  public void setReachable(boolean reachable) {
-    setFlag(reachable, IS_REACHABLE_MASK);
-  }
-
-  @Override
-  public boolean isSyntheticJSP() {
-    return checkFlag(IS_SYNTHETIC_JSP_ELEMENT);
-  }
-
-  public void setSyntheticJSP(boolean b) {
-    setFlag(b, IS_SYNTHETIC_JSP_ELEMENT);
-  }
-
-  @Override
-  @Nullable
-  public String getAccessModifier() {
-    long access_id = myFlags & ACCESS_MODIFIER_MASK;
-    if (access_id == ACCESS_PRIVATE) return PsiModifier.PRIVATE;
-    if (access_id == ACCESS_PUBLIC) return PsiModifier.PUBLIC;
-    if (access_id == ACCESS_PACKAGE) return PsiModifier.PACKAGE_LOCAL;
-    return PsiModifier.PROTECTED;
-  }
-
-  public void setAccessModifier(String am) {
-    doSetAccessModifier(am);
-  }
-
-  private void doSetAccessModifier(String am) {
-    final int access_id;
-
-    if (PsiModifier.PRIVATE.equals(am)) {
-      access_id = ACCESS_PRIVATE;
-    }
-    else if (PsiModifier.PUBLIC.equals(am)) {
-      access_id = ACCESS_PUBLIC;
-    }
-    else if (PsiModifier.PACKAGE_LOCAL.equals(am)) {
-      access_id = ACCESS_PACKAGE;
-    }
-    else {
-      access_id = ACCESS_PROTECTED;
-    }
-
-    myFlags = myFlags & ~0x3 | access_id;
-  }
-
-  public boolean isSuspiciousRecursive() {
-    return isCalledOnlyFrom(this, new Stack<RefJavaElement>());
-  }
-
-  private boolean isCalledOnlyFrom(RefJavaElement refElement, Stack<RefJavaElement> callStack) {
-    if (callStack.contains(this)) return refElement == this;
-    if (getInReferences().isEmpty()) return false;
-
-    if (refElement instanceof RefMethod) {
-      RefMethod refMethod = (RefMethod) refElement;
-      for (RefMethod refSuper : refMethod.getSuperMethods()) {
-        if (!refSuper.getInReferences().isEmpty()) return false;
-      }
-      if (refMethod.isConstructor()){
-        boolean unreachable = true;
-        for (RefElement refOut : refMethod.getOutReferences()){
-          unreachable &= !refOut.isReachable();
-        }
-        if (unreachable) return true;
-      }
-    }
-
-    callStack.push(this);
-    for (RefElement refCaller : getInReferences()) {
-      if (!((RefElementImpl)refCaller).isSuspicious() || !((RefJavaElementImpl)refCaller).isCalledOnlyFrom(refElement, callStack)) {
-        callStack.pop();
-        return false;
-      }
-    }
-
-    callStack.pop();
-    return true;
-  }
-
-  public void addReference(RefElement refWhat, PsiElement psiWhat, PsiElement psiFrom, boolean forWriting, boolean forReading, PsiReferenceExpression expression) {
-    if (refWhat != null) {
-      if (refWhat instanceof RefParameter) {
-        if (forWriting) {
-          ((RefParameter)refWhat).parameterReferenced(true);
-        }
-        if (forReading) {
-          ((RefParameter)refWhat).parameterReferenced(false);
-        }
-      }
-      addOutReference(refWhat);
-      ((RefJavaElementImpl)refWhat).markReferenced(this, psiFrom, psiWhat, forWriting, forReading, expression);
-    } else {
-      if (psiWhat instanceof PsiMethod) {
-        final PsiClass containingClass = ((PsiMethod)psiWhat).getContainingClass();
-        if (containingClass != null && containingClass.isEnum() && "values".equals(((PsiMethod)psiWhat).getName())) {
-          for (PsiField enumConstant : containingClass.getFields()) {
-            if (enumConstant instanceof PsiEnumConstant) {
-              final RefJavaElementImpl enumConstantReference = (RefJavaElementImpl)getRefManager().getReference(enumConstant);
-              if (enumConstantReference != null) {
-                addOutReference(enumConstantReference);
-                enumConstantReference.markReferenced(this, psiFrom, enumConstant, false, true, expression);
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  protected void markReferenced(final RefElementImpl refFrom, PsiElement psiFrom, PsiElement psiWhat, final boolean forWriting, boolean forReading, PsiReferenceExpression expressionFrom) {
-    addInReference(refFrom);
-    getRefManager().fireNodeMarkedReferenced(this, refFrom, false, forReading, forWriting);
-  }
-
-  protected RefJavaManager getRefJavaManager() {
-    return getRefManager().getExtension(RefJavaManager.MANAGER);
-  }
-
-  @Override
-  public void referenceRemoved() {
-    super.referenceRemoved();
-    if (isEntry()) {
-      getRefJavaManager().getEntryPointsManager().removeEntryPoint(this);
-    }
-  }
-
-  @Override
-  public Icon getIcon(final boolean expanded) {
-    if (isSyntheticJSP()) {
-      final PsiElement element = getElement();
-      if (element != null && element.isValid()) {
-        return IconUtil.getIcon(element.getContainingFile().getVirtualFile(),
-                                Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS, element.getProject());
-      }
-    }
-    return super.getIcon(expanded);
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java
deleted file mode 100644
index 9bfd6f0..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 20-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.psi.PsiJavaFile;
-
-public class RefJavaFileImpl extends RefFileImpl {
-  RefJavaFileImpl(PsiJavaFile elem, RefManager manager) {
-    super(elem, manager);
-    ((RefPackageImpl)getRefManager().getExtension(RefJavaManager.MANAGER).getPackage(elem.getPackageName())).add(this);
-  }
-}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index 8ebd6ab..f53e1fb 100644
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -122,11 +122,6 @@
     return file != null ? DEAD_CODE_TOOL.get(file, myRefManager).get() : null;
   }
 
-  public boolean isEntryPoint(PsiElement element) {
-    UnusedDeclarationInspection tool = getDeadCodeTool(element);
-    return tool != null && tool.isEntryPoint(element);
-  }
-
   @Override
   public RefPackage getDefaultPackage() {
     if (myDefaultPackage == null) {
@@ -349,7 +344,7 @@
 
   private static void appendPackageElement(final Element element, final String packageName) {
     final Element packageElement = new Element("package");
-    packageElement.addContent(packageName.length() > 0 ? packageName : InspectionsBundle.message("inspection.export.results.default"));
+    packageElement.addContent(packageName.isEmpty() ? InspectionsBundle.message("inspection.export.results.default") : packageName);
     element.addContent(packageElement);
   }
 
@@ -358,7 +353,7 @@
     if (myEntryPointsManager == null) {
       final Project project = myRefManager.getProject();
       myEntryPointsManager = new EntryPointsManagerImpl(project);
-      ((EntryPointsManagerImpl)myEntryPointsManager).addAllPersistentEntries(EntryPointsManagerImpl.getInstance(project));
+      ((EntryPointsManagerBase)myEntryPointsManager).addAllPersistentEntries(EntryPointsManagerBase.getInstance(project));
     }
     return myEntryPointsManager;
   }
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
deleted file mode 100644
index 71fa80a..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 21-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.MethodSignatureUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.VisibilityUtil;
-import org.jetbrains.annotations.Nullable;
-
-public class RefJavaUtilImpl extends RefJavaUtil{
-
-  @Override
-  public void addReferences(final PsiModifierListOwner psiFrom, final RefJavaElement ref, @Nullable PsiElement findIn) {
-    final RefJavaElementImpl refFrom = (RefJavaElementImpl)ref;
-    if (findIn != null) {
-      findIn.accept(
-        new JavaRecursiveElementWalkingVisitor() {
-          @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
-          }
-
-          @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
-            visitElement(expression);
-
-            PsiElement psiResolved = expression.resolve();
-
-            if (psiResolved instanceof PsiModifierListOwner) {
-              if (isDeprecated(psiResolved)) refFrom.setUsesDeprecatedApi(true);
-            }
-
-            RefElement refResolved = refFrom.getRefManager().getReference(psiResolved);
-            refFrom.addReference(
-              refResolved, psiResolved, psiFrom, PsiUtil.isAccessedForWriting(expression),
-              PsiUtil.isAccessedForReading(expression), expression
-            );
-
-            if (refResolved instanceof RefMethod) {
-              updateRefMethod(psiResolved, refResolved, expression, psiFrom, refFrom);
-            }
-          }
-
-
-          @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
-            super.visitEnumConstant(enumConstant);
-            processNewLikeConstruct(enumConstant.resolveConstructor(), enumConstant.getArgumentList());
-          }
-
-          @Override public void visitNewExpression(PsiNewExpression newExpr) {
-            super.visitNewExpression(newExpr);
-            PsiMethod psiConstructor = newExpr.resolveConstructor();
-            final PsiExpressionList argumentList = newExpr.getArgumentList();
-
-            RefMethod refConstructor = processNewLikeConstruct(psiConstructor, argumentList);
-
-            if (refConstructor == null) {  // No explicit constructor referenced. Should use default one.
-              PsiType newType = newExpr.getType();
-              if (newType instanceof PsiClassType) {
-                processClassReference(PsiUtil.resolveClassInType(newType), refFrom, psiFrom, true);
-              }
-            }
-          }
-
-          @Nullable
-          private RefMethod processNewLikeConstruct(final PsiMethod psiConstructor, final PsiExpressionList argumentList) {
-            if (psiConstructor != null) {
-              if (isDeprecated(psiConstructor)) refFrom.setUsesDeprecatedApi(true);
-            }
-
-            RefMethodImpl refConstructor = (RefMethodImpl)refFrom.getRefManager().getReference(
-              psiConstructor
-            );
-            refFrom.addReference(refConstructor, psiConstructor, psiFrom, false, true, null);
-
-            if (argumentList != null) {
-              PsiExpression[] psiParams = argumentList.getExpressions();
-              for (PsiExpression param : psiParams) {
-                param.accept(this);
-              }
-
-              if (refConstructor != null) {
-                refConstructor.updateParameterValues(psiParams);
-              }
-            }
-            return refConstructor;
-          }
-
-          @Override public void visitAnonymousClass(PsiAnonymousClass psiClass) {
-            super.visitAnonymousClass(psiClass);
-            RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
-            refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
-          }
-
-          @Override public void visitReturnStatement(PsiReturnStatement statement) {
-            super.visitReturnStatement(statement);
-
-            if (refFrom instanceof RefMethodImpl) {
-              RefMethodImpl refMethod = (RefMethodImpl)refFrom;
-              refMethod.updateReturnValueTemplate(statement.getReturnValue());
-            }
-          }
-
-          @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
-            super.visitClassObjectAccessExpression(expression);
-            final PsiTypeElement operand = expression.getOperand();
-            final PsiType type = operand.getType();
-            if (type instanceof PsiClassType) {
-              processClassReference(((PsiClassType)type).resolve(), refFrom, psiFrom, false);
-            }
-          }
-
-          private void processClassReference(final PsiClass psiClass,
-                                             final RefJavaElementImpl refFrom,
-                                             final PsiModifierListOwner psiFrom,
-                                             boolean defaultConstructorOnly) {
-            if (psiClass != null) {
-              RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
-
-              if (refClass != null) {
-                boolean hasConstructorsMarked = false;
-
-                if (defaultConstructorOnly) {
-                  RefMethodImpl refDefaultConstructor = (RefMethodImpl)refClass.getDefaultConstructor();
-                  if (refDefaultConstructor != null && !(refDefaultConstructor instanceof RefImplicitConstructor)) {
-                    refDefaultConstructor.addInReference(refFrom);
-                    refFrom.addOutReference(refDefaultConstructor);
-                    hasConstructorsMarked = true;
-                  }
-                }
-                else {
-                  for (RefMethod cons : refClass.getConstructors()) {
-                    if (cons instanceof RefImplicitConstructor) continue;
-                    ((RefMethodImpl)cons).addInReference(refFrom);
-                    refFrom.addOutReference(cons);
-                    hasConstructorsMarked = true;
-                  }
-                }
-
-                if (!hasConstructorsMarked) {
-                  refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
-                }
-              }
-            }
-          }
-        }
-      );
-    }
-  }
-
-  private void updateRefMethod(PsiElement psiResolved,
-                               RefElement refResolved,
-                               PsiElement refExpression,
-                               final PsiElement psiFrom,
-                               final RefElement refFrom) {
-    PsiMethod psiMethod = (PsiMethod)psiResolved;
-    RefMethodImpl refMethod = (RefMethodImpl)refResolved;
-
-    PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(
-      refExpression,
-      PsiMethodCallExpression.class
-    );
-    if (call != null) {
-      PsiType returnType = psiMethod.getReturnType();
-      if (!psiMethod.isConstructor() && returnType != PsiType.VOID) {
-        if (!(call.getParent() instanceof PsiExpressionStatement)) {
-          refMethod.setReturnValueUsed(true);
-        }
-
-        addTypeReference(psiFrom, returnType, refFrom.getRefManager());
-      }
-
-      PsiExpressionList argumentList = call.getArgumentList();
-      if (argumentList.getExpressions().length > 0) {
-        refMethod.updateParameterValues(argumentList.getExpressions());
-      }
-
-      final PsiExpression psiExpression = call.getMethodExpression().getQualifierExpression();
-      if (psiExpression != null) {
-        final PsiType usedType = psiExpression.getType();
-        if (usedType != null) {
-          final String fqName = psiMethod.getContainingClass().getQualifiedName();
-          if (fqName != null) {
-            final PsiClassType methodOwnerType = JavaPsiFacade.getInstance(call.getProject()).getElementFactory()
-              .createTypeByFQClassName(fqName, GlobalSearchScope.allScope(psiMethod.getProject()));
-            if (!usedType.equals(methodOwnerType)) {
-              refMethod.setCalledOnSubClass(true);
-            }
-          }
-        }
-      }
-    }
-  }
-
-
-
-
-  @Override
-  public RefClass getTopLevelClass(RefElement refElement) {
-    RefEntity refParent = refElement.getOwner();
-
-    while (refParent != null && refParent instanceof RefElement && !(refParent instanceof RefFile)) {
-      refElement = (RefElementImpl)refParent;
-      refParent = refParent.getOwner();
-    }
-
-    return (RefClass)refElement;
-  }
-
-  @Override
-  public boolean isInheritor(RefClass subClass, RefClass superClass) {
-    if (subClass == superClass) return true;
-
-    for (RefClass baseClass : subClass.getBaseClasses()) {
-      if (isInheritor(baseClass, superClass)) return true;
-    }
-
-    return false;
-  }
-
-  @Override
-  @Nullable
-  public String getPackageName(RefEntity refEntity) {
-    if (refEntity instanceof RefProject) {
-      return null;
-    }
-    RefPackage refPackage = getPackage(refEntity);
-
-    return refPackage == null ? InspectionsBundle.message("inspection.reference.default.package") : refPackage.getQualifiedName();
-  }
-
-  @Override
-  public String getAccessModifier(PsiModifierListOwner psiElement) {
-     if (psiElement instanceof PsiParameter) return PsiModifier.PACKAGE_LOCAL;
-
-     PsiModifierList list = psiElement.getModifierList();
-     String result = PsiModifier.PACKAGE_LOCAL;
-
-     if (list != null) {
-       if (list.hasModifierProperty(PsiModifier.PRIVATE)) {
-         result = PsiModifier.PRIVATE;
-       }
-       else if (list.hasModifierProperty(PsiModifier.PROTECTED)) {
-         result = PsiModifier.PROTECTED;
-       }
-       else if (list.hasModifierProperty(PsiModifier.PUBLIC)) {
-         result = PsiModifier.PUBLIC;
-       }
-       else if (psiElement.getParent() instanceof PsiClass) {
-         PsiClass ownerClass = (PsiClass)psiElement.getParent();
-         if (ownerClass.isInterface()) {
-           result = PsiModifier.PUBLIC;
-         }
-       }
-     }
-
-     return result;
-   }
-
-   @Override
-   @Nullable public RefClass getOwnerClass(RefManager refManager, PsiElement psiElement) {
-     while (psiElement != null && !(psiElement instanceof PsiClass)) {
-       psiElement = psiElement.getParent();
-     }
-
-     return psiElement != null ? (RefClass)refManager.getReference(psiElement) : null;
-   }
-
-   @Override
-   @Nullable public RefClass getOwnerClass(RefElement refElement) {
-     RefEntity parent = refElement.getOwner();
-
-     while (!(parent instanceof RefClass) && parent instanceof RefElement) {
-       parent = parent.getOwner();
-     }
-
-     if (parent instanceof RefClass) return (RefClass)parent;
-
-     return null;
-   }
-
-
-
-   @Override
-   public boolean isMethodOnlyCallsSuper(PsiMethod method) {
-     boolean hasStatements = false;
-     PsiCodeBlock body = method.getBody();
-     if (body != null) {
-       PsiStatement[] statements = body.getStatements();
-       for (PsiStatement statement : statements) {
-         boolean isCallToSameSuper = false;
-         if (statement instanceof PsiExpressionStatement) {
-           isCallToSameSuper = isCallToSuperMethod(((PsiExpressionStatement)statement).getExpression(), method);
-         }
-         else if (statement instanceof PsiReturnStatement) {
-           PsiExpression expression = ((PsiReturnStatement)statement).getReturnValue();
-           isCallToSameSuper = expression == null || isCallToSuperMethod(expression, method);
-         }
-
-         hasStatements = true;
-         if (isCallToSameSuper) continue;
-
-         return false;
-       }
-     }
-
-     if (hasStatements) {
-       final PsiMethod[] superMethods = method.findSuperMethods();
-       for (PsiMethod superMethod : superMethods) {
-         if (VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(superMethod.getModifierList()),
-                                    VisibilityUtil.getVisibilityModifier(method.getModifierList())) > 0) return false;
-       }
-     }
-     return hasStatements;
-   }
-
-   @Override
-   public boolean isCallToSuperMethod(PsiExpression expression, PsiMethod method) {
-     if (expression instanceof PsiMethodCallExpression) {
-       PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression;
-       if (methodCall.getMethodExpression().getQualifierExpression() instanceof PsiSuperExpression) {
-         PsiMethod superMethod = (PsiMethod)methodCall.getMethodExpression().resolve();
-         if (superMethod == null || !MethodSignatureUtil.areSignaturesEqual(method, superMethod)) return false;
-         PsiExpression[] args = methodCall.getArgumentList().getExpressions();
-         PsiParameter[] parms = method.getParameterList().getParameters();
-
-         for (int i = 0; i < args.length; i++) {
-           PsiExpression arg = args[i];
-           if (!(arg instanceof PsiReferenceExpression)) return false;
-           if (!parms[i].equals(((PsiReferenceExpression)arg).resolve())) return false;
-         }
-
-         return true;
-       }
-     }
-
-     return false;
-   }
-
-   @Override
-   public int compareAccess(String a1, String a2) {
-     int i1 = getAccessNumber(a1);
-     int i2 = getAccessNumber(a2);
-
-     if (i1 == i2) return 0;
-     if (i1 < i2) return -1;
-     return 1;
-   }
-
-   @SuppressWarnings("StringEquality")
-     private static int getAccessNumber(String a) {
-     if (a == PsiModifier.PRIVATE) {
-       return 0;
-     }
-     else if (a == PsiModifier.PACKAGE_LOCAL) {
-       return 1;
-     }
-     else if (a == PsiModifier.PROTECTED) {
-       return 2;
-     }
-     else if (a == PsiModifier.PUBLIC) return 3;
-
-     return -1;
-   }
-
-  @Override
-  public void setAccessModifier(RefJavaElement refElement, String newAccess) {
-    ((RefJavaElementImpl)refElement).setAccessModifier(newAccess);
-  }
-
-  @Override
-  public void setIsStatic(RefJavaElement refElement, boolean isStatic) {
-    ((RefJavaElementImpl)refElement).setIsStatic(isStatic);
-  }
-
-  @Override
-  public void setIsFinal(RefJavaElement refElement, boolean isFinal) {
-    ((RefJavaElementImpl)refElement).setIsFinal(isFinal);
-  }
-
-  @Override
-  public void addTypeReference(PsiElement psiElement, PsiType psiType, RefManager refManager) {
-    RefClass ownerClass = getOwnerClass(refManager, psiElement);
-
-    if (ownerClass != null) {
-      psiType = psiType.getDeepComponentType();
-
-      if (psiType instanceof PsiClassType) {
-        PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
-        if (psiClass != null && refManager.belongsToScope(psiClass)) {
-          RefClassImpl refClass = (RefClassImpl)refManager.getReference(psiClass);
-          if (refClass != null) {
-            refClass.addTypeReference(ownerClass);
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java
deleted file mode 100644
index bca7bd1..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInsight.ExceptionUtil;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.*;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author max
- * Date: Oct 21, 2001
- */
-public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
-  private static final List<RefMethod> EMPTY_METHOD_LIST = Collections.emptyList();
-  private static final RefParameter[] EMPTY_PARAMS_ARRAY = new RefParameter[0];
-
-  private static final int IS_APPMAIN_MASK = 0x10000;
-  private static final int IS_LIBRARY_OVERRIDE_MASK = 0x20000;
-  private static final int IS_CONSTRUCTOR_MASK = 0x40000;
-  private static final int IS_ABSTRACT_MASK = 0x80000;
-  private static final int IS_BODY_EMPTY_MASK = 0x100000;
-  private static final int IS_ONLY_CALLS_SUPER_MASK = 0x200000;
-  private static final int IS_RETURN_VALUE_USED_MASK = 0x400000;
-
-  private static final int IS_TEST_METHOD_MASK = 0x4000000;
-  private static final int IS_CALLED_ON_SUBCLASS = 0x8000000;
-
-  private static final String RETURN_VALUE_UNDEFINED = "#";
-
-  private List<RefMethod> mySuperMethods;
-  private List<RefMethod> myDerivedMethods;
-  private List<String> myUnThrownExceptions;
-
-  private RefParameter[] myParameters;
-  private String myReturnValueTemplate;
-  protected final RefClass myOwnerClass;
-
-  RefMethodImpl(@NotNull RefClass ownerClass, PsiMethod method, RefManager manager) {
-    super(method, manager);
-
-    ((RefClassImpl)ownerClass).add(this);
-
-    myOwnerClass = ownerClass;
-  }
-
-  // To be used only from RefImplicitConstructor.
-  protected RefMethodImpl(String name, @NotNull RefClass ownerClass) {
-    super(name, ownerClass);
-    myOwnerClass = ownerClass;
-    ((RefClassImpl)ownerClass).add(this);
-
-    addOutReference(getOwnerClass());
-    ((RefClassImpl)getOwnerClass()).addInReference(this);
-
-    setConstructor(true);
-  }
-
-  @Override
-  protected void initialize() {
-    final PsiMethod method = (PsiMethod)getElement();
-    LOG.assertTrue(method != null);
-    setConstructor(method.isConstructor());
-    setFlag(method.getReturnType() == null || PsiType.VOID.equals(method.getReturnType()), IS_RETURN_VALUE_USED_MASK);
-
-    if (!isReturnValueUsed()) {
-      myReturnValueTemplate = RETURN_VALUE_UNDEFINED;
-    }
-
-    if (isConstructor()) {
-      addReference(getOwnerClass(), getOwnerClass().getElement(), method, false, true, null);
-    }
-
-    if (getOwnerClass().isInterface()) {
-      setAbstract(false);
-    } else {
-      setAbstract(method.hasModifierProperty(PsiModifier.ABSTRACT));
-    }
-
-
-    setAppMain(isAppMain(method, this));
-    setLibraryOverride(method.hasModifierProperty(PsiModifier.NATIVE));
-
-    initializeSuperMethods(method);
-    if (isExternalOverride()) {
-      ((RefClassImpl)getOwnerClass()).addLibraryOverrideMethod(this);
-    }
-
-    @NonNls final String name = method.getName();
-    if (getOwnerClass().isTestCase() && name.startsWith("test")) {
-      setTestMethod(true);
-    }
-
-    PsiParameter[] paramList = method.getParameterList().getParameters();
-    if (paramList.length > 0){
-      myParameters = new RefParameterImpl[paramList.length];
-      for (int i = 0; i < paramList.length; i++) {
-        PsiParameter parameter = paramList[i];
-        myParameters[i] = getRefJavaManager().getParameterReference(parameter, i);
-      }
-    }
-
-    if (method.hasModifierProperty(PsiModifier.NATIVE)) {
-      updateReturnValueTemplate(null);
-      updateThrowsList(null);
-    }
-    collectUncaughtExceptions(method);
-  }
-
-  private static boolean isAppMain(PsiMethod psiMethod, RefMethod refMethod) {
-    if (!refMethod.isStatic()) return false;
-    if (!PsiType.VOID.equals(psiMethod.getReturnType())) return false;
-
-    PsiMethod appMainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppMainPattern();
-    if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appMainPattern)) return true;
-
-    PsiMethod appPremainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppPremainPattern();
-    return MethodSignatureUtil.areSignaturesEqual(psiMethod, appPremainPattern);
-  }
-
-  private void checkForSuperCall(PsiMethod method) {
-    if (isConstructor()) {
-      PsiCodeBlock body = method.getBody();
-      if (body == null) return;
-      PsiStatement[] statements = body.getStatements();
-      boolean isBaseExplicitlyCalled = false;
-      if (statements.length > 0) {
-        PsiStatement first = statements[0];
-        if (first instanceof PsiExpressionStatement) {
-          PsiExpression firstExpression = ((PsiExpressionStatement) first).getExpression();
-          if (firstExpression instanceof PsiMethodCallExpression) {
-            PsiExpression qualifierExpression = ((PsiMethodCallExpression)firstExpression).getMethodExpression().getQualifierExpression();
-            if (qualifierExpression instanceof PsiReferenceExpression) {
-              @NonNls String text = qualifierExpression.getText();
-              if ("super".equals(text) || text.equals("this")) {
-                isBaseExplicitlyCalled = true;
-              }
-            }
-          }
-        }
-      }
-
-      if (!isBaseExplicitlyCalled) {
-        for (RefClass superClass : getOwnerClass().getBaseClasses()) {
-          RefMethodImpl superDefaultConstructor = (RefMethodImpl)superClass.getDefaultConstructor();
-
-          if (superDefaultConstructor != null) {
-            superDefaultConstructor.addInReference(this);
-            addOutReference(superDefaultConstructor);
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  @NotNull
-  public Collection<RefMethod> getSuperMethods() {
-    if (mySuperMethods == null) return EMPTY_METHOD_LIST;
-    if (mySuperMethods.size() > 10) {
-      LOG.info("method: " + getName() + " owner:" + getOwnerClass().getQualifiedName());
-    }
-    return mySuperMethods;
-  }
-
-  @Override
-  @NotNull
-  public Collection<RefMethod> getDerivedMethods() {
-    if (myDerivedMethods == null) return EMPTY_METHOD_LIST;
-    return myDerivedMethods;
-  }
-
-  @Override
-  public boolean isBodyEmpty() {
-    return checkFlag(IS_BODY_EMPTY_MASK);
-  }
-
-  @Override
-  public boolean isOnlyCallsSuper() {
-    return checkFlag(IS_ONLY_CALLS_SUPER_MASK);
-  }
-
-  @Override
-  public boolean hasBody() {
-    return !isAbstract() && !getOwnerClass().isInterface() || !isBodyEmpty();
-  }
-
-  private void initializeSuperMethods(PsiMethod method) {
-    for (PsiMethod psiSuperMethod : method.findSuperMethods()) {
-      if (getRefManager().belongsToScope(psiSuperMethod)) {
-        RefMethodImpl refSuperMethod = (RefMethodImpl)getRefManager().getReference(psiSuperMethod);
-        if (refSuperMethod != null) {
-          addSuperMethod(refSuperMethod);
-          refSuperMethod.markExtended(this);
-        }
-      }
-      else {
-        setLibraryOverride(true);
-      }
-    }
-  }
-
-  public void addSuperMethod(RefMethodImpl refSuperMethod) {
-    if (!getSuperMethods().contains(refSuperMethod) && !refSuperMethod.getSuperMethods().contains(this)) {
-      if (mySuperMethods == null){
-        mySuperMethods = new ArrayList<RefMethod>(1);
-      }
-      mySuperMethods.add(refSuperMethod);
-    }
-  }
-
-  public void markExtended(RefMethodImpl method) {
-    if (!getDerivedMethods().contains(method) && !method.getDerivedMethods().contains(this)) {
-      if (myDerivedMethods == null) {
-        myDerivedMethods = new ArrayList<RefMethod>(1);
-      }
-      myDerivedMethods.add(method);
-    }
-  }
-
-  @Override
-  @NotNull
-  public RefParameter[] getParameters() {
-    if (myParameters == null) return EMPTY_PARAMS_ARRAY;
-    return myParameters;
-  }
-
-  @Override
-  public void buildReferences() {
-    // Work on code block to find what we're referencing...
-    PsiMethod method = (PsiMethod) getElement();
-    if (method == null) return;
-    PsiCodeBlock body = method.getBody();
-    final RefJavaUtil refUtil = RefJavaUtil.getInstance();
-    refUtil.addReferences(method, this, body);
-    refUtil.addReferences(method, this, method.getModifierList());
-    checkForSuperCall(method);
-    setOnlyCallsSuper(refUtil.isMethodOnlyCallsSuper(method));
-
-    setBodyEmpty(isOnlyCallsSuper() || !isExternalOverride() && (body == null || body.getStatements().length == 0));
-
-    PsiType retType = method.getReturnType();
-    if (retType != null) {
-      PsiType psiType = retType;
-      RefClass ownerClass = refUtil.getOwnerClass(getRefManager(), method);
-
-      if (ownerClass != null) {
-        psiType = psiType.getDeepComponentType();
-
-        if (psiType instanceof PsiClassType) {
-          PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
-          if (psiClass != null && getRefManager().belongsToScope(psiClass)) {
-              RefClassImpl refClass = (RefClassImpl) getRefManager().getReference(psiClass);
-            if (refClass != null) {
-              refClass.addTypeReference(ownerClass);
-              refClass.addClassExporter(this);
-            }
-          }
-        }
-      }
-    }
-
-    for (RefParameter parameter : getParameters()) {
-      refUtil.setIsFinal(parameter, parameter.getElement().hasModifierProperty(PsiModifier.FINAL));
-    }
-
-    getRefManager().fireBuildReferences(this);
-  }
-
-  private void collectUncaughtExceptions(@NotNull PsiMethod method) {
-    if (isExternalOverride()) return;
-    @NonNls final String name = method.getName();
-    if (getOwnerClass().isTestCase() && name.startsWith("test")) return;
-
-    if (getSuperMethods().isEmpty()) {
-      PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
-      if (throwsList.length > 0) {
-        myUnThrownExceptions = throwsList.length == 1 ? new SmartList<String>() : new ArrayList<String>(throwsList.length);
-        for (final PsiClassType type : throwsList) {
-          PsiClass aClass = type.resolve();
-          String fqn = aClass == null ? null : aClass.getQualifiedName();
-          if (fqn != null) {
-            myUnThrownExceptions.add(fqn);
-          }
-        }
-      }
-    }
-
-    final PsiCodeBlock body = method.getBody();
-    if (body == null) return;
-
-    final Collection<PsiClassType> exceptionTypes = ExceptionUtil.collectUnhandledExceptions(body, method, false);
-    for (final PsiClassType exceptionType : exceptionTypes) {
-      updateThrowsList(exceptionType);
-    }
-  }
-
-  public void removeUnThrownExceptions(PsiClass unThrownException) {
-    if (myUnThrownExceptions != null) {
-      myUnThrownExceptions.remove(unThrownException.getQualifiedName());
-    }
-  }
-
-  @Override
-  public void accept(@NotNull final RefVisitor visitor) {
-    if (visitor instanceof RefJavaVisitor) {
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          ((RefJavaVisitor)visitor).visitMethod(RefMethodImpl.this);
-        }
-      });
-    } else {
-      super.accept(visitor);
-    }
-  }
-
-  @Override
-  public boolean isExternalOverride() {
-    return isLibraryOverride(new HashSet<RefMethod>());
-  }
-
-  private boolean isLibraryOverride(Collection<RefMethod> processed) {
-    if (processed.contains(this)) return false;
-    processed.add(this);
-
-    if (checkFlag(IS_LIBRARY_OVERRIDE_MASK)) return true;
-    for (RefMethod superMethod : getSuperMethods()) {
-      if (((RefMethodImpl)superMethod).isLibraryOverride(processed)) {
-        setFlag(true, IS_LIBRARY_OVERRIDE_MASK);
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Override
-  public boolean isAppMain() {
-    return checkFlag(IS_APPMAIN_MASK);
-  }
-
-  @Override
-  public boolean isAbstract() {
-    return checkFlag(IS_ABSTRACT_MASK);
-  }
-
-  @Override
-  public boolean hasSuperMethods() {
-    return !getSuperMethods().isEmpty() || isExternalOverride();
-  }
-
-  @Override
-  public boolean isReferenced() {
-    // Directly called from somewhere..
-    for (RefElement refCaller : getInReferences()) {
-      if (!getDerivedMethods().contains(refCaller)) return true;
-    }
-
-    // Library override probably called from library code.
-    return isExternalOverride();
-  }
-
-  @Override
-  public boolean hasSuspiciousCallers() {
-    // Directly called from somewhere..
-    for (RefElement refCaller : getInReferences()) {
-      if (((RefElementImpl)refCaller).isSuspicious() && !getDerivedMethods().contains(refCaller)) return true;
-    }
-
-    // Library override probably called from library code.
-    if (isExternalOverride()) return true;
-
-    // Class isn't instantiated. Most probably we have problem with class, not method.
-    if (!isStatic() && !isConstructor()) {
-      if (((RefClassImpl)getOwnerClass()).isSuspicious()) return true;
-
-      // Is an override. Probably called via reference to base class.
-      for (RefMethod refSuper : getSuperMethods()) {
-        if (((RefMethodImpl)refSuper).isSuspicious()) return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Override
-  public boolean isConstructor() {
-    return checkFlag(IS_CONSTRUCTOR_MASK);
-  }
-
-  @Override
-  public RefClass getOwnerClass() {
-    return (RefClass) getOwner();
-  }
-
-  @NotNull
-  @Override
-  public String getName() {
-    if (isValid()) {
-      final String[] result = new String[1];
-      final Runnable runnable = new Runnable() {
-        @Override
-        public void run() {
-          PsiMethod psiMethod = (PsiMethod) getElement();
-          if (psiMethod instanceof JspHolderMethod) {
-            result[0] = psiMethod.getName();
-          }
-          else {
-            result[0] = PsiFormatUtil.formatMethod(psiMethod,
-                                                   PsiSubstitutor.EMPTY,
-                                                   PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
-                                                   PsiFormatUtilBase.SHOW_TYPE
-            );
-          }
-        }
-      };
-
-      ApplicationManager.getApplication().runReadAction(runnable);
-
-      return result[0];
-    } else {
-      return super.getName();
-    }
-  }
-
-  @Override
-  public String getExternalName() {
-    final String[] result = new String[1];
-    final Runnable runnable = new Runnable() {
-      @Override
-      public void run() {
-        final PsiMethod psiMethod = (PsiMethod)getElement();
-        LOG.assertTrue(psiMethod != null);
-        result[0] = PsiFormatUtil.getExternalName(psiMethod);
-      }
-    };
-
-    ApplicationManager.getApplication().runReadAction(runnable);
-
-    return result[0];
-  }
-
-  @Nullable
-  public static RefMethod methodFromExternalName(RefManager manager, String externalName) {
-    return (RefMethod) manager.getReference(findPsiMethod(PsiManager.getInstance(manager.getProject()), externalName));
-  }
-
-  @Nullable
-  public static PsiMethod findPsiMethod(PsiManager manager, String externalName) {
-    final int spaceIdx = externalName.indexOf(' ');
-    final String className = externalName.substring(0, spaceIdx);
-    final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
-    if (psiClass == null) return null;
-    try {
-      PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory();
-      String methodSignature = externalName.substring(spaceIdx + 1);
-      PsiMethod patternMethod = factory.createMethodFromText(methodSignature, psiClass);
-      return psiClass.findMethodBySignature(patternMethod, false);
-    } catch (IncorrectOperationException e) {
-      // Do nothing. Returning null is acceptable in this case.
-      return null;
-    }
-  }
-
-  @Override
-  public void referenceRemoved() {
-    if (getOwnerClass() != null) {
-      ((RefClassImpl)getOwnerClass()).methodRemoved(this);
-    }
-
-    super.referenceRemoved();
-
-    for (RefMethod superMethod : getSuperMethods()) {
-      superMethod.getDerivedMethods().remove(this);
-    }
-
-    for (RefMethod subMethod : getDerivedMethods()) {
-      subMethod.getSuperMethods().remove(this);
-    }
-
-    ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>();
-    for (RefParameter parameter : getParameters()) {
-      getRefManager().removeRefElement(parameter, deletedRefs);
-    }
-  }
-
-  @Override
-  public boolean isSuspicious() {
-    if (isConstructor() && PsiModifier.PRIVATE.equals(getAccessModifier()) && getParameters().length == 0 && getOwnerClass().getConstructors().size() == 1) return false;
-    return super.isSuspicious();
-  }
-
-  public void setReturnValueUsed(boolean value) {
-    if (checkFlag(IS_RETURN_VALUE_USED_MASK) == value) return;
-    setFlag(value, IS_RETURN_VALUE_USED_MASK);
-    for (RefMethod refSuper : getSuperMethods()) {
-      ((RefMethodImpl)refSuper).setReturnValueUsed(value);
-    }
-  }
-
-  @Override
-  public boolean isReturnValueUsed() {
-    return checkFlag(IS_RETURN_VALUE_USED_MASK);
-  }
-
-  public void updateReturnValueTemplate(PsiExpression expression) {
-    if (myReturnValueTemplate == null) return;
-
-    if (!getSuperMethods().isEmpty()) {
-      for (final RefMethod refMethod : getSuperMethods()) {
-        RefMethodImpl refSuper = (RefMethodImpl)refMethod;
-        refSuper.updateReturnValueTemplate(expression);
-      }
-    }else {
-      String newTemplate = null;
-      final RefJavaUtil refUtil = RefJavaUtil.getInstance();
-      if (expression instanceof PsiLiteralExpression) {
-        PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
-        newTemplate = psiLiteralExpression.getText();
-      } else if (expression instanceof PsiReferenceExpression) {
-        PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
-        PsiElement resolved = referenceExpression.resolve();
-        if (resolved instanceof PsiField) {
-          PsiField psiField = (PsiField) resolved;
-          if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
-              psiField.hasModifierProperty(PsiModifier.FINAL) &&
-              refUtil.compareAccess(refUtil.getAccessModifier(psiField), getAccessModifier()) >= 0) {
-            newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtilBase.SHOW_NAME |
-                                                                 PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
-                                                                 PsiFormatUtilBase.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
-          }
-        }
-      } else if (refUtil.isCallToSuperMethod(expression, (PsiMethod) getElement())) return;
-
-      //noinspection StringEquality
-      if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) {
-        myReturnValueTemplate = newTemplate;
-      } else if (!Comparing.equal(myReturnValueTemplate, newTemplate)) {
-        myReturnValueTemplate = null;
-      }
-    }
-  }
-
-  public void updateParameterValues(PsiExpression[] args) {
-    if (isExternalOverride()) return;
-
-    if (!getSuperMethods().isEmpty()) {
-      for (RefMethod refSuper : getSuperMethods()) {
-        ((RefMethodImpl)refSuper).updateParameterValues(args);
-      }
-    } else {
-      final RefParameter[] params = getParameters();
-      if (params.length <= args.length && params.length > 0) {
-        for (int i = 0; i < args.length; i++) {
-          RefParameter refParameter;
-          if (params.length <= i){
-            refParameter = params[params.length - 1];
-          } else {
-            refParameter = params[i];
-          }
-          ((RefParameterImpl)refParameter).updateTemplateValue(args[i]);
-        }
-      }
-    }
-  }
-
-  @Override
-  public String getReturnValueIfSame() {
-    //noinspection StringEquality
-    if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) return null;
-    return myReturnValueTemplate;
-  }
-
-  public void updateThrowsList(PsiClassType exceptionType) {
-    if (!getSuperMethods().isEmpty()) {
-      for (RefMethod refSuper : getSuperMethods()) {
-        ((RefMethodImpl)refSuper).updateThrowsList(exceptionType);
-      }
-    }
-    else if (myUnThrownExceptions != null) {
-      if (exceptionType == null) {
-        myUnThrownExceptions = null;
-        return;
-      }
-      PsiClass exceptionClass = exceptionType.resolve();
-      JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
-      for (int i = myUnThrownExceptions.size() - 1; i >= 0; i--) {
-        String exceptionFqn = myUnThrownExceptions.get(i);
-        PsiClass classType = facade.findClass(exceptionFqn, GlobalSearchScope.allScope(getRefManager().getProject()));
-        if (InheritanceUtil.isInheritorOrSelf(exceptionClass, classType, true) ||
-            InheritanceUtil.isInheritorOrSelf(classType, exceptionClass, true)) {
-          myUnThrownExceptions.remove(i);
-        }
-      }
-
-      if (myUnThrownExceptions.isEmpty()) myUnThrownExceptions = null;
-    }
-  }
-
-  @Override
-  @Nullable
-  public PsiClass[] getUnThrownExceptions() {
-    if (myUnThrownExceptions == null) return null;
-    JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
-    List<PsiClass> result = new ArrayList<PsiClass>(myUnThrownExceptions.size());
-    for (String exception : myUnThrownExceptions) {
-      PsiClass element = facade.findClass(exception, GlobalSearchScope.allScope(myManager.getProject()));
-      if (element != null) result.add(element);
-    }
-    return result.toArray(new PsiClass[result.size()]);
-  }
-
-
-  public void setLibraryOverride(boolean libraryOverride) {
-    setFlag(libraryOverride, IS_LIBRARY_OVERRIDE_MASK);
-  }
-
-  private void setAppMain(boolean appMain) {
-    setFlag(appMain, IS_APPMAIN_MASK);
-  }
-
-  private void setAbstract(boolean anAbstract) {
-    setFlag(anAbstract, IS_ABSTRACT_MASK);
-  }
-
-  public void setBodyEmpty(boolean bodyEmpty) {
-    setFlag(bodyEmpty, IS_BODY_EMPTY_MASK);
-  }
-
-  private void setOnlyCallsSuper(boolean onlyCallsSuper) {
-    setFlag(onlyCallsSuper, IS_ONLY_CALLS_SUPER_MASK);
-  }
-
-
-
-  private void setConstructor(boolean constructor) {
-    setFlag(constructor, IS_CONSTRUCTOR_MASK);
-  }
-
-  @Override
-  public boolean isTestMethod() {
-    return checkFlag(IS_TEST_METHOD_MASK);
-  }
-
-  private void setTestMethod(boolean testMethod){
-    setFlag(testMethod, IS_TEST_METHOD_MASK);
-  }
-
-  @Override
-  public PsiModifierListOwner getElement() {
-    return (PsiModifierListOwner)super.getElement();
-  }
-
-  @Override
-  public boolean isCalledOnSubClass() {
-    return checkFlag(IS_CALLED_ON_SUBCLASS);
-  }
-
-  public void setCalledOnSubClass(boolean isCalledOnSubClass){
-    setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS);
-  }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java
deleted file mode 100644
index 32649b9..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Nov 15, 2001
- * Time: 5:17:38 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.util.PlatformIcons;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-
-public class RefPackageImpl extends RefEntityImpl implements RefPackage {
-  private final String myQualifiedName;
-
-  public RefPackageImpl(@NotNull String name, @NotNull RefManager refManager) {
-    super(getPackageSuffix(name), refManager);
-    myQualifiedName = name;
-  }
-
-  @NotNull
-  @Override
-  public String getQualifiedName() {
-    return myQualifiedName;
-  }
-
-  private static String getPackageSuffix(@NotNull String fullName) {
-    int dotIndex = fullName.lastIndexOf('.');
-    return (dotIndex >= 0) ? fullName.substring(dotIndex + 1) : fullName;
-  }
-
-
-  @Override
-  public void accept(@NotNull final RefVisitor visitor) {
-    if (visitor instanceof RefJavaVisitor) {
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          ((RefJavaVisitor)visitor).visitPackage(RefPackageImpl.this);
-        }
-      });
-    } else {
-      super.accept(visitor);
-    }
-  }
-
-  @Override
-  public String getExternalName() {
-    return getQualifiedName();
-  }
-
-  public static RefEntity packageFromFQName(final RefManager manager, final String name) {
-    return manager.getExtension(RefJavaManager.MANAGER).getPackage(name);
-  }
-
-  @Override
-  public boolean isValid() {
-    return true;
-  }
-
-  @Override
-  public Icon getIcon(final boolean expanded) {
-    return PlatformIcons.PACKAGE_ICON;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java
deleted file mode 100644
index f33145f..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 21, 2001
- * Time: 4:35:07 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class RefParameterImpl extends RefJavaElementImpl implements RefParameter {
-  private static final int USED_FOR_READING_MASK = 0x10000;
-  private static final int USED_FOR_WRITING_MASK = 0x20000;
-  private static final String VALUE_UNDEFINED = "#";
-
-  private final short myIndex;
-  private String myActualValueTemplate;
-
-  RefParameterImpl(PsiParameter parameter, int index, RefManager manager) {
-    super(parameter, manager);
-
-    myIndex = (short)index;
-    myActualValueTemplate = VALUE_UNDEFINED;
-    final RefElementImpl owner = (RefElementImpl)manager.getReference(PsiTreeUtil.getParentOfType(parameter, PsiMethod.class));
-    if (owner != null) {
-      owner.add(this);
-    }
-  }
-
-  @Override
-  public void parameterReferenced(boolean forWriting) {
-    if (forWriting) {
-      setUsedForWriting();
-    } else {
-      setUsedForReading();
-    }
-  }
-
-  @Override
-  public boolean isUsedForReading() {
-    return checkFlag(USED_FOR_READING_MASK);
-  }
-
-  private void setUsedForReading() {
-    setFlag(true, USED_FOR_READING_MASK);
-  }
-
-  @Override
-  public PsiParameter getElement() {
-    return (PsiParameter)super.getElement();
-  }
-
-  @Override
-  public boolean isUsedForWriting() {
-    return checkFlag(USED_FOR_WRITING_MASK);
-  }
-
-  private void setUsedForWriting() {
-    setFlag(true, USED_FOR_WRITING_MASK);
-  }
-
-  @Override
-  public void accept(@NotNull final RefVisitor visitor) {
-    if (visitor instanceof RefJavaVisitor) {
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          ((RefJavaVisitor)visitor).visitParameter(RefParameterImpl.this);
-        }
-      });
-    } else {
-      super.accept(visitor);
-    }
-  }
-
-  @Override
-  public int getIndex() {
-    return myIndex;
-  }
-
-  public void updateTemplateValue(PsiExpression expression) {
-    if (myActualValueTemplate == null) return;
-
-    String newTemplate = null;
-    if (expression instanceof PsiLiteralExpression) {
-      PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
-      newTemplate = psiLiteralExpression.getText();
-    } else if (expression instanceof PsiReferenceExpression) {
-      PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
-      PsiElement resolved = referenceExpression.resolve();
-      if (resolved instanceof PsiField) {
-        PsiField psiField = (PsiField) resolved;
-        if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
-            psiField.hasModifierProperty(PsiModifier.FINAL) &&
-            psiField.getContainingClass().getQualifiedName() != null) {
-          newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_CONTAINING_CLASS | PsiFormatUtil.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
-        }
-      }
-    }
-
-    if (myActualValueTemplate == VALUE_UNDEFINED) {
-      myActualValueTemplate = newTemplate;
-    } else if (!Comparing.equal(myActualValueTemplate, newTemplate)) {
-      myActualValueTemplate = null;
-    }
-  }
-
-  @Override
-  public String getActualValueIfSame() {
-    if (myActualValueTemplate == VALUE_UNDEFINED) return null;
-    return myActualValueTemplate;
-  }
-
-  @Override
-  protected void initialize() {
-  }
-
-  @Override
-  public String getExternalName() {
-    final String[] result = new String[1];
-    final Runnable runnable = new Runnable() {
-      @Override
-      public void run() {
-        PsiParameter parameter = getElement();
-        LOG.assertTrue(parameter != null);
-        result[0] = PsiFormatUtil.getExternalName(parameter);
-      }
-    };
-
-    ApplicationManager.getApplication().runReadAction(runnable);
-
-    return result[0];
-  }
-
-  @Nullable
-  public static RefElement parameterFromExternalName(final RefManager manager, final String fqName) {
-    final int idx = fqName.lastIndexOf(' ');
-    if (idx > 0) {
-      final String paramName = fqName.substring(idx + 1);
-      final String method = fqName.substring(0, idx);
-      final RefMethod refMethod = RefMethodImpl.methodFromExternalName(manager, method);
-      if (refMethod != null) {
-        final PsiMethod element = (PsiMethod)refMethod.getElement();
-        final PsiParameterList list = element.getParameterList();
-        final PsiParameter[] parameters = list.getParameters();
-        int paramIdx = 0;
-        for (PsiParameter parameter : parameters) {
-          final String name = parameter.getName();
-          if (name != null && name.equals(paramName)) {
-            return manager.getExtension(RefJavaManager.MANAGER).getParameterReference(parameter, paramIdx);
-          }
-          paramIdx++;
-        }
-      }
-    }
-    return null;
-  }
-
-  @Nullable
-  public static PsiParameter findPsiParameter(String fqName, final PsiManager manager) {
-    final int idx = fqName.lastIndexOf(' ');
-    if (idx > 0) {
-      final String paramName = fqName.substring(idx + 1);
-      final String method = fqName.substring(0, idx);
-      final PsiMethod psiMethod = RefMethodImpl.findPsiMethod(manager, method);
-      if (psiMethod != null) {
-        final PsiParameterList list = psiMethod.getParameterList();
-        final PsiParameter[] parameters = list.getParameters();
-        for (PsiParameter parameter : parameters) {
-          final String name = parameter.getName();
-          if (name != null && name.equals(paramName)) {
-            return parameter;
-          }
-        }
-      }
-    }
-    return null;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
index 0f75668..12e26f8 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -41,7 +41,7 @@
 /**
  * @author max
  */
-public class SameParameterValueInspection extends GlobalJavaInspectionTool {
+public class SameParameterValueInspection extends GlobalJavaBatchInspectionTool {
   private static final Logger LOG = Logger.getInstance("#" + SameParameterValueInspection.class.getName());
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java
deleted file mode 100644
index 7d4c353..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.sameReturnValue;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.psi.PsiMethod;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author max
- */
-public class SameReturnValueInspection extends GlobalJavaInspectionTool {
-  @Override
-  @Nullable
-  public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity, @NotNull AnalysisScope scope, @NotNull InspectionManager manager, @NotNull GlobalInspectionContext globalContext,
-                                                @NotNull ProblemDescriptionsProcessor processor) {
-    if (refEntity instanceof RefMethod) {
-      final RefMethod refMethod = (RefMethod)refEntity;
-
-      if (refMethod.isConstructor()) return null;
-      if (refMethod.hasSuperMethods()) return null;
-
-      String returnValue = refMethod.getReturnValueIfSame();
-      if (returnValue != null) {
-        final String message;
-        if (refMethod.getDerivedMethods().isEmpty()) {
-          message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor", "<code>" + returnValue + "</code>");
-        } else if (refMethod.hasBody()) {
-          message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor1", "<code>" + returnValue + "</code>");
-        } else {
-          message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor2", "<code>" + returnValue + "</code>");
-        }
-
-        return new ProblemDescriptor[] {manager.createProblemDescriptor(refMethod.getElement().getNavigationElement(), message, false, null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING)};
-      }
-    }
-
-    return null;
-  }
-
-
-  @Override
-  protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor processor) {
-    manager.iterate(new RefJavaVisitor() {
-      @Override public void visitElement(@NotNull RefEntity refEntity) {
-        if (refEntity instanceof RefElement && processor.getDescriptions(refEntity) != null) {
-          refEntity.accept(new RefJavaVisitor() {
-            @Override public void visitMethod(@NotNull final RefMethod refMethod) {
-              globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
-                @Override
-                public boolean process(PsiMethod derivedMethod) {
-                  processor.ignoreElement(refMethod);
-                  return false;
-                }
-              });
-            }
-          });
-        }
-      }
-    });
-
-    return false;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return InspectionsBundle.message("inspection.same.return.value.display.name");
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getShortName() {
-    return "SameReturnValue";
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
index 7363d43..b02ce22 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
@@ -15,7 +15,7 @@
  */
 package com.intellij.codeInspection.ui;
 
-import com.intellij.codeInspection.deadCode.DummyEntryPointsTool;
+import com.intellij.codeInspection.deadCode.DummyEntryPointsEP;
 import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
 import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
 import com.intellij.codeInspection.ex.InspectionToolWrapper;
@@ -33,7 +33,7 @@
   }
 
   private static InspectionToolWrapper createDummyWrapper(@NotNull GlobalInspectionContextImpl context) {
-    InspectionToolWrapper toolWrapper = new GlobalInspectionToolWrapper(new DummyEntryPointsTool());
+    InspectionToolWrapper toolWrapper = new GlobalInspectionToolWrapper(new DummyEntryPointsEP());
     toolWrapper.initialize(context);
     return toolWrapper;
   }
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 24cc9d1..b740fcf 100644
--- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
@@ -24,14 +24,12 @@
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInsight.intention.QuickFixFactory;
 import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.*;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.util.Pass;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.util.*;
 import org.intellij.lang.annotations.Pattern;
@@ -168,8 +166,13 @@
 
   @NotNull
   @Override
-  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
-    return new UncheckedWarningsVisitor(isOnTheFly){
+  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
+                                        boolean isOnTheFly,
+                                        @NotNull LocalInspectionToolSession session) {
+    LanguageLevel languageLevel = PsiUtil.getLanguageLevel(session.getFile());
+    if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return super.buildVisitor(holder, isOnTheFly, session);
+
+    return new UncheckedWarningsVisitor(isOnTheFly, languageLevel){
       @Override
       protected void registerProblem(@NotNull String message, @NotNull PsiElement psiElement, @NotNull LocalQuickFix[] quickFixes) {
         holder.registerProblem(psiElement, message, quickFixes);
@@ -179,10 +182,12 @@
 
   private abstract class UncheckedWarningsVisitor extends JavaElementVisitor {
     private final boolean myOnTheFly;
+    @NotNull private final LanguageLevel myLanguageLevel;
     private final LocalQuickFix[] myGenerifyFixes;
 
-    public UncheckedWarningsVisitor(boolean onTheFly) {
+    public UncheckedWarningsVisitor(boolean onTheFly, @NotNull LanguageLevel level) {
       myOnTheFly = onTheFly;
+      myLanguageLevel = level;
       myGenerifyFixes = onTheFly ? new LocalQuickFix[]{new GenerifyFileFix()} : LocalQuickFix.EMPTY_ARRAY;
     }
 
@@ -192,9 +197,8 @@
     @Override
     public void visitReferenceExpression(PsiReferenceExpression expression) {
       if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
       final JavaResolveResult result = expression.advancedResolve(false);
-      if (JavaGenericsUtil.isUncheckedWarning(expression, result)) {
+      if (JavaGenericsUtil.isUncheckedWarning(expression, result, myLanguageLevel)) {
         registerProblem("Unchecked generics array creation for varargs parameter", expression, LocalQuickFix.EMPTY_ARRAY);
       }
     }
@@ -203,9 +207,8 @@
     public void visitNewExpression(PsiNewExpression expression) {
       super.visitNewExpression(expression);
       if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
       final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
-      if (JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics())) {
+      if (classReference != null && JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics(), myLanguageLevel)) {
         registerProblem("Unchecked generics array creation for varargs parameter", classReference, LocalQuickFix.EMPTY_ARRAY);
       }
     }
@@ -214,7 +217,6 @@
     public void visitTypeCastExpression(PsiTypeCastExpression expression) {
       super.visitTypeCastExpression(expression);
       if (IGNORE_UNCHECKED_CAST) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
       final PsiTypeElement typeElement = expression.getCastType();
       if (typeElement == null) return;
       final PsiType castType = typeElement.getType();
@@ -234,7 +236,6 @@
     @Override
     public void visitCallExpression(PsiCallExpression callExpression) {
       super.visitCallExpression(callExpression);
-      if (!PsiUtil.isLanguageLevel5OrHigher(callExpression)) return;
       final JavaResolveResult result = callExpression.resolveMethodGenerics();
       final String description = getUncheckedCallDescription(result);
       if (description != null) {
@@ -273,7 +274,6 @@
     public void visitVariable(PsiVariable variable) {
       super.visitVariable(variable);
       if (IGNORE_UNCHECKED_ASSIGNMENT) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(variable)) return;
       PsiExpression initializer = variable.getInitializer();
       if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return;
       final PsiType initializerType = initializer.getType();
@@ -285,13 +285,11 @@
     public void visitForeachStatement(PsiForeachStatement statement) {
       super.visitForeachStatement(statement);
       if (IGNORE_UNCHECKED_ASSIGNMENT) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
       final PsiParameter parameter = statement.getIterationParameter();
       final PsiType parameterType = parameter.getType();
       final PsiExpression iteratedValue = statement.getIteratedValue();
       if (iteratedValue == null) return;
       final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
-      if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
       checkRawToGenericsAssignment(parameter, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY);
     }
 
@@ -299,7 +297,6 @@
     public void visitAssignmentExpression(PsiAssignmentExpression expression) {
       super.visitAssignmentExpression(expression);
       if (IGNORE_UNCHECKED_ASSIGNMENT) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
       if (!"=".equals(expression.getOperationSign().getText())) return;
       PsiExpression lExpr = expression.getLExpression();
       PsiExpression rExpr = expression.getRExpression();
@@ -321,7 +318,6 @@
     public void visitArrayInitializerExpression(PsiArrayInitializerExpression arrayInitializer) {
       super.visitArrayInitializerExpression(arrayInitializer);
       if (IGNORE_UNCHECKED_ASSIGNMENT) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(arrayInitializer)) return;
       final PsiType type = arrayInitializer.getType();
       if (!(type instanceof PsiArrayType)) return;
       final PsiType componentType = ((PsiArrayType)type).getComponentType();
@@ -372,7 +368,6 @@
     public void visitMethod(PsiMethod method) {
       super.visitMethod(method);
       if (IGNORE_UNCHECKED_OVERRIDING) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(method)) return;
       if (!method.isConstructor()) {
         List<HierarchicalMethodSignature> superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
         if (!superMethodSignatures.isEmpty() && !method.hasModifierProperty(PsiModifier.STATIC)) {
@@ -403,7 +398,6 @@
     public void visitReturnStatement(PsiReturnStatement statement) {
       super.visitReturnStatement(statement);
       if (IGNORE_UNCHECKED_ASSIGNMENT) return;
-      if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
       final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
       if (method != null) {
         final PsiType returnType = method.getReturnType();
diff --git a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java
deleted file mode 100644
index 0ee3c67..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.intellij.codeInspection.unnecessaryModuleDependency;
-
-import com.intellij.codeInspection.reference.RefElement;
-import com.intellij.codeInspection.reference.RefGraphAnnotator;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.util.Key;
-import com.intellij.psi.PsiElement;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * User: anna
- * Date: 09-Jan-2006
- */
-public class UnnecessaryModuleDependencyAnnotator extends RefGraphAnnotator {
-  public static final Key<Set<Module>> DEPENDENCIES = Key.create("inspection.dependencies");
-
-  private final RefManager myManager;
-
-  public UnnecessaryModuleDependencyAnnotator(final RefManager manager) {
-    myManager = manager;
-  }
-
-
-
-  @Override
-  public void onMarkReferenced(RefElement refWhat, RefElement refFrom, boolean referencedFromClassInitializer) {
-    final PsiElement onElement = refWhat.getElement();
-    final PsiElement fromElement = refFrom.getElement();
-    if (onElement != null && fromElement!= null){
-      final Module onModule = ModuleUtil.findModuleForPsiElement(onElement);
-      final Module fromModule = ModuleUtil.findModuleForPsiElement(fromElement);
-      if (onModule != null && fromModule != null && onModule != fromModule){
-        final RefModule refModule = myManager.getRefModule(fromModule);
-        if (refModule != null) {
-          Set<Module> modules = refModule.getUserData(DEPENDENCIES);
-          if (modules == null){
-            modules = new HashSet<Module>();
-            refModule.putUserData(DEPENDENCIES, modules);
-          }
-          modules.add(onModule);
-        }
-      }
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java
deleted file mode 100644
index 87e99c5..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.intellij.codeInspection.unnecessaryModuleDependency;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.reference.RefGraphAnnotator;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModifiableRootModel;
-import com.intellij.openapi.roots.ModuleOrderEntry;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.OrderEntry;
-import com.intellij.openapi.util.Comparing;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * User: anna
- * Date: 09-Jan-2006
- */
-public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool {
-
-  @Override
-  public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
-    return new UnnecessaryModuleDependencyAnnotator(refManager);
-  }
-
-  @Override
-  public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity, @NotNull AnalysisScope scope, @NotNull InspectionManager manager, @NotNull final GlobalInspectionContext globalContext) {
-    if (refEntity instanceof RefModule){
-      final RefModule refModule = (RefModule)refEntity;
-      final Module module = refModule.getModule();
-      final Module[] declaredDependencies = ModuleRootManager.getInstance(module).getDependencies();
-      List<CommonProblemDescriptor> descriptors = new ArrayList<CommonProblemDescriptor>();
-      final Set<Module> modules = refModule.getUserData(UnnecessaryModuleDependencyAnnotator.DEPENDENCIES);
-      for (final Module dependency : declaredDependencies) {
-        if (modules == null || !modules.contains(dependency)) {
-         final CommonProblemDescriptor problemDescriptor;
-          if (scope.containsModule(dependency)) { //external references are rejected -> annotator doesn't provide any information on them -> false positives
-            problemDescriptor = manager.createProblemDescriptor(
-              InspectionsBundle.message("unnecessary.module.dependency.problem.descriptor", module.getName(), dependency.getName()),
-              new RemoveModuleDependencyFix(module, dependency));
-          } else {
-            String message = InspectionsBundle
-              .message("suspected.module.dependency.problem.descriptor", module.getName(), dependency.getName(), scope.getDisplayName(),
-                       dependency.getName());
-            problemDescriptor = manager.createProblemDescriptor(message);
-          }
-          descriptors.add(problemDescriptor);
-        }
-      }
-      return descriptors.isEmpty() ? null : descriptors.toArray(new CommonProblemDescriptor[descriptors.size()]);
-    }
-    return null;
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return InspectionsBundle.message("unnecessary.module.dependency.display.name");
-  }
-
-  @Override
-  @NotNull
-  @NonNls
-  public String getShortName() {
-    return "UnnecessaryModuleDependencyInspection";
-  }
-
-  public static class RemoveModuleDependencyFix implements QuickFix {
-    private final Module myModule;
-    private final Module myDependency;
-
-    public RemoveModuleDependencyFix(Module module, Module dependency) {
-      myModule = module;
-      myDependency = dependency;
-    }
-
-    @Override
-    @NotNull
-    public String getName() {
-      return "Remove dependency";
-    }
-
-    @Override
-    @NotNull
-    public String getFamilyName() {
-      return getName();
-    }
-
-    @Override
-    public void applyFix(@NotNull Project project, @NotNull CommonProblemDescriptor descriptor) {
-      final ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel();
-      for (OrderEntry entry : model.getOrderEntries()) {
-        if (entry instanceof ModuleOrderEntry) {
-          final Module mDependency = ((ModuleOrderEntry)entry).getModule();
-          if (Comparing.equal(mDependency, myDependency)) {
-            model.removeOrderEntry(entry);
-            break;
-          }
-        }
-      }
-      model.commit();
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java b/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
deleted file mode 100644
index 8810af9..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.unneededThrows;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.ExceptionUtil;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.Processor;
-import com.intellij.util.Query;
-import com.intellij.util.containers.BidirectionalMap;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author max
- */
-public class RedundantThrows extends GlobalJavaInspectionTool {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.unneededThrows.RedundantThrows");
-  private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.redundant.throws.display.name");
-  private final BidirectionalMap<String, QuickFix> myQuickFixes = new BidirectionalMap<String, QuickFix>();
-  @NonNls private static final String SHORT_NAME = "RedundantThrows";
-
-  @Override
-  @Nullable
-  public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
-                                                @NotNull AnalysisScope scope,
-                                                @NotNull InspectionManager manager,
-                                                @NotNull GlobalInspectionContext globalContext,
-                                                @NotNull ProblemDescriptionsProcessor processor) {
-    if (refEntity instanceof RefMethod) {
-      final RefMethod refMethod = (RefMethod)refEntity;
-      if (refMethod.isSyntheticJSP()) return null;
-
-      if (refMethod.hasSuperMethods()) return null;
-
-      if (refMethod.isEntry()) return null;
-
-      PsiClass[] unThrown = refMethod.getUnThrownExceptions();
-      if (unThrown == null) return null;
-
-      PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
-      PsiClassType[] throwsList = psiMethod.getThrowsList().getReferencedTypes();
-      PsiJavaCodeReferenceElement[] throwsRefs = psiMethod.getThrowsList().getReferenceElements();
-      List<ProblemDescriptor> problems = null;
-
-      final PsiManager psiManager = psiMethod.getManager();
-      for (int i = 0; i < throwsList.length; i++) {
-        final PsiClassType throwsType = throwsList[i];
-        final String throwsClassName = throwsType.getClassName();
-        final PsiJavaCodeReferenceElement throwsRef = throwsRefs[i];
-        if (ExceptionUtil.isUncheckedException(throwsType)) continue;
-        if (declaredInRemotableMethod(psiMethod, throwsType)) continue;
-
-        for (PsiClass s : unThrown) {
-          final PsiClass throwsResolvedType = throwsType.resolve();
-          if (psiManager.areElementsEquivalent(s, throwsResolvedType)) {
-            if (problems == null) problems = new ArrayList<ProblemDescriptor>(1);
-
-            if (refMethod.isAbstract() || refMethod.getOwnerClass().isInterface()) {
-              problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
-                "inspection.redundant.throws.problem.descriptor", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
-                                                           false));
-            }
-            else if (!refMethod.getDerivedMethods().isEmpty()) {
-              problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
-                "inspection.redundant.throws.problem.descriptor1", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
-                                                           false));
-            }
-            else {
-              problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
-                "inspection.redundant.throws.problem.descriptor2", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
-                                                           false));
-            }
-          }
-        }
-      }
-
-      if (problems != null) {
-        return problems.toArray(new CommonProblemDescriptor[problems.size()]);
-      }
-    }
-
-    return null;
-  }
-
-  private static boolean declaredInRemotableMethod(final PsiMethod psiMethod, final PsiClassType throwsType) {
-    if (!throwsType.equalsToText("java.rmi.RemoteException")) return false;
-    PsiClass aClass = psiMethod.getContainingClass();
-    if (aClass == null) return false;
-    PsiClass remote =
-      JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.rmi.Remote", GlobalSearchScope.allScope(aClass.getProject()));
-    return remote != null && aClass.isInheritor(remote, true);
-  }
-
-
-  @Override
-  protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor processor) {
-    manager.iterate(new RefJavaVisitor() {
-      @Override public void visitElement(@NotNull RefEntity refEntity) {
-        if (processor.getDescriptions(refEntity) != null) {
-          refEntity.accept(new RefJavaVisitor() {
-            @Override public void visitMethod(@NotNull final RefMethod refMethod) {
-              globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
-                @Override
-                public boolean process(PsiMethod derivedMethod) {
-                  processor.ignoreElement(refMethod);
-                  return true;
-                }
-              });
-            }
-          });
-        }
-      }
-    });
-
-    return false;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return DISPLAY_NAME;
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getShortName() {
-    return SHORT_NAME;
-  }
-
-  private LocalQuickFix getFix(final ProblemDescriptionsProcessor processor, final String hint) {
-    QuickFix fix = myQuickFixes.get(hint);
-    if (fix == null) {
-      fix = new MyQuickFix(processor, hint);
-      if (hint != null) {
-        myQuickFixes.put(hint, fix);
-      }
-    }
-    return (LocalQuickFix)fix;
-  }
-
-
-  @Override
-  @Nullable
-  public QuickFix getQuickFix(String hint) {
-    return getFix(null, hint);
-  }
-
-  @Override
-  @Nullable
-  public String getHint(@NotNull final QuickFix fix) {
-    final List<String> hints = myQuickFixes.getKeysByValue(fix);
-    LOG.assertTrue(hints != null && hints.size() == 1);
-    return hints.get(0);
-  }
-
-  private static class MyQuickFix implements LocalQuickFix {
-    private final ProblemDescriptionsProcessor myProcessor;
-    private final String myHint;
-
-    public MyQuickFix(final ProblemDescriptionsProcessor processor, final String hint) {
-      myProcessor = processor;
-      myHint = hint;
-    }
-
-    @Override
-    @NotNull
-    public String getName() {
-      return InspectionsBundle.message("inspection.redundant.throws.remove.quickfix");
-    }
-
-    @Override
-    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
-      if (myProcessor != null) {
-        RefElement refElement = (RefElement)myProcessor.getElement(descriptor);
-        if (refElement instanceof RefMethod && refElement.isValid()) {
-          RefMethod refMethod = (RefMethod)refElement;
-          final CommonProblemDescriptor[] problems = myProcessor.getDescriptions(refMethod);
-          if (problems != null) {
-            removeExcessiveThrows(refMethod, null, problems);
-          }
-        }
-      }
-      else {
-        final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethod.class);
-        if (psiMethod != null) {
-          removeExcessiveThrows(null, psiMethod, new CommonProblemDescriptor[]{descriptor});
-        }
-      }
-    }
-
-    @Override
-    @NotNull
-    public String getFamilyName() {
-      return getName();
-    }
-
-    private void removeExcessiveThrows(@Nullable RefMethod refMethod, @Nullable final PsiModifierListOwner element, final CommonProblemDescriptor[] problems) {
-      try {
-        @Nullable final PsiMethod psiMethod;
-        if (element == null) {
-          LOG.assertTrue(refMethod != null);
-          psiMethod = (PsiMethod)refMethod.getElement();
-        }
-        else {
-          psiMethod = (PsiMethod)element;
-        }
-        if (psiMethod == null) return; //invalid refMethod
-        final Project project = psiMethod.getProject();
-        final PsiManager psiManager = PsiManager.getInstance(project);
-        final List<PsiJavaCodeReferenceElement> refsToDelete = new ArrayList<PsiJavaCodeReferenceElement>();
-        for (CommonProblemDescriptor problem : problems) {
-          final PsiElement psiElement = ((ProblemDescriptor)problem).getPsiElement();
-          if (psiElement instanceof PsiJavaCodeReferenceElement) {
-            final PsiJavaCodeReferenceElement classRef = (PsiJavaCodeReferenceElement)psiElement;
-            final PsiType psiType = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(classRef);
-            removeException(refMethod, psiType, refsToDelete, psiMethod);
-          } else {
-            final PsiReferenceList throwsList = psiMethod.getThrowsList();
-            final PsiClassType[] classTypes = throwsList.getReferencedTypes();
-            for (PsiClassType classType : classTypes) {
-              final String text = classType.getClassName();
-              if (Comparing.strEqual(myHint, text)) {
-                removeException(refMethod, classType, refsToDelete, psiMethod);
-                break;
-              }
-            }
-          }
-        }
-
-        //check read-only status for derived methods
-        if (!FileModificationService.getInstance().preparePsiElementsForWrite(refsToDelete)) return;
-
-        for (final PsiJavaCodeReferenceElement aRefsToDelete : refsToDelete) {
-          aRefsToDelete.delete();
-        }
-      }
-      catch (IncorrectOperationException e) {
-        LOG.error(e);
-      }
-    }
-
-    private static void removeException(final RefMethod refMethod,
-                                        final PsiType exceptionType,
-                                        final List<PsiJavaCodeReferenceElement> refsToDelete,
-                                        final PsiMethod psiMethod) {
-      PsiManager psiManager = psiMethod.getManager();
-
-      PsiJavaCodeReferenceElement[] refs = psiMethod.getThrowsList().getReferenceElements();
-      for (PsiJavaCodeReferenceElement ref : refs) {
-        PsiType refType = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(ref);
-        if (exceptionType.isAssignableFrom(refType)) {
-          refsToDelete.add(ref);
-        }
-      }
-
-      if (refMethod != null) {
-        for (RefMethod refDerived : refMethod.getDerivedMethods()) {
-          removeException(refDerived, exceptionType, refsToDelete, (PsiMethod)refDerived.getElement());
-        }
-      } else {
-        final Query<Pair<PsiMethod,PsiMethod>> query = AllOverridingMethodsSearch.search(psiMethod.getContainingClass());
-        query.forEach(new Processor<Pair<PsiMethod, PsiMethod>>(){
-          @Override
-          public boolean process(final Pair<PsiMethod, PsiMethod> pair) {
-            if (pair.first == psiMethod) {
-              removeException(null, exceptionType, refsToDelete, pair.second);
-            }
-            return true;
-          }
-        });
-      }
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
index 807cf4b..a8feaf9 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
@@ -20,6 +20,7 @@
 import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
 import com.intellij.codeInspection.InspectionsBundle;
 import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
+import com.siyeh.ig.imports.UnusedImportInspection;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
@@ -55,8 +56,9 @@
     return true;
   }
 
+  @NotNull
   @Override
   public String getInspectionForBatchShortName() {
-    return "UnusedImport";
+    return new UnusedImportInspection().getShortName();
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java
deleted file mode 100644
index a8a6be9..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 18-Apr-2007
- */
-package com.intellij.codeInspection.unusedLibraries;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.ex.JobDescriptor;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.impl.ProgressManagerImpl;
-import com.intellij.openapi.progress.util.ProgressIndicatorBase;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.*;
-import com.intellij.openapi.roots.libraries.Library;
-import com.intellij.openapi.roots.libraries.LibraryUtil;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VfsUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.packageDependencies.BackwardDependenciesBuilder;
-import com.intellij.psi.PsiCompiledElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiRecursiveElementVisitor;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.GlobalSearchScopes;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.PackageSetFactory;
-import com.intellij.psi.search.scope.packageSet.ParsingException;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-public class UnusedLibrariesInspection extends GlobalInspectionTool {
-  private static final Logger LOG = Logger.getInstance("#" + UnusedLibrariesInspection.class.getName());
-  private final JobDescriptor BACKWARD_ANALYSIS = new JobDescriptor(InspectionsBundle.message("unused.library.backward.analysis.job.description"));
-
-  @Override
-  public void runInspection(@NotNull AnalysisScope scope,
-                            @NotNull InspectionManager manager,
-                            @NotNull final GlobalInspectionContext globalContext,
-                            @NotNull ProblemDescriptionsProcessor problemProcessor) {
-    ((GlobalInspectionContextImpl)globalContext).appendJobDescriptor(BACKWARD_ANALYSIS);
-    final Project project = manager.getProject();
-    final ArrayList<VirtualFile> libraryRoots = new ArrayList<VirtualFile>();
-    if (scope.getScopeType() == AnalysisScope.PROJECT) {
-      ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(project, false, false));
-    }
-    else {
-      final Set<Module> modules = new HashSet<Module>();
-      scope.accept(new PsiRecursiveElementVisitor() {
-        @Override
-        public void visitFile(PsiFile file) {
-          if (!(file instanceof PsiCompiledElement)) {
-            final VirtualFile virtualFile = file.getVirtualFile();
-            if (virtualFile != null) {
-              final Module module = ModuleUtil.findModuleForFile(virtualFile, project);
-              if (module != null) {
-                modules.add(module);
-              }
-            }
-          }
-        }
-      });
-      ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(modules.toArray(new Module[modules.size()]), false, false));
-    }
-    if (libraryRoots.isEmpty()) {
-      return;
-    }
-
-    GlobalSearchScope searchScope;
-    try {
-      @NonNls final String libsName = "libs";
-      NamedScope libScope = new NamedScope(libsName, PackageSetFactory.getInstance().compile("lib:*..*"));
-      searchScope = GlobalSearchScopes.filterScope(project, libScope);
-    }
-    catch (ParsingException e) {
-      //can't be
-      LOG.error(e);
-      return;
-    }
-    final AnalysisScope analysisScope = new AnalysisScope(searchScope, project);
-    analysisScope.setSearchInLibraries(true);
-    final BackwardDependenciesBuilder builder = new BackwardDependenciesBuilder(project, analysisScope);
-
-    final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
-
-    BACKWARD_ANALYSIS.setTotalAmount(builder.getTotalFileCount());
-    ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(new Runnable(){
-      @Override
-      public void run() {
-        builder.analyze();
-      }
-    }, new ProgressIndicatorBase() {
-      @Override
-      public void setFraction(final double fraction) {
-        super.setFraction(fraction);
-        int nextAmount = (int)(fraction * BACKWARD_ANALYSIS.getTotalAmount());
-        if (nextAmount > BACKWARD_ANALYSIS.getDoneAmount() && nextAmount < BACKWARD_ANALYSIS.getTotalAmount()) {
-          BACKWARD_ANALYSIS.setDoneAmount(nextAmount);
-          globalContext.incrementJobDoneAmount(BACKWARD_ANALYSIS, getText2());
-        }
-      }
-
-      @Override
-      public boolean isCanceled() {
-        return progressIndicator != null && progressIndicator.isCanceled() || super.isCanceled();
-      }
-    });
-    BACKWARD_ANALYSIS.setDoneAmount(BACKWARD_ANALYSIS.getTotalAmount());
-    final Map<PsiFile, Set<PsiFile>> dependencies = builder.getDependencies();
-    for (PsiFile file : dependencies.keySet()) {
-      final VirtualFile virtualFile = file.getVirtualFile();
-      LOG.assertTrue(virtualFile != null);
-      for (Iterator<VirtualFile> i = libraryRoots.iterator(); i.hasNext();) {
-        if (VfsUtil.isAncestor(i.next(), virtualFile, false)) {
-          i.remove();
-        }
-      }
-    }
-    if (libraryRoots.isEmpty()) {
-      return;
-    }
-    ProjectFileIndex projectIndex = ProjectRootManager.getInstance(project).getFileIndex();
-    Map<OrderEntry, Set<VirtualFile>> unusedLibs = new HashMap<OrderEntry, Set<VirtualFile>>();
-    for (VirtualFile libraryRoot : libraryRoots) {
-      final List<OrderEntry> orderEntries = projectIndex.getOrderEntriesForFile(libraryRoot);
-      for (OrderEntry orderEntry : orderEntries) {
-        Set<VirtualFile> files = unusedLibs.get(orderEntry);
-        if (files == null) {
-          files = new HashSet<VirtualFile>();
-          unusedLibs.put(orderEntry, files);
-        }
-        files.add(libraryRoot);
-      }
-    }
-    final RefManager refManager = globalContext.getRefManager();
-    for (OrderEntry orderEntry : unusedLibs.keySet()) {
-      if (!(orderEntry instanceof LibraryOrderEntry)) continue;
-      final RefModule refModule = refManager.getRefModule(orderEntry.getOwnerModule());
-      final Set<VirtualFile> files = unusedLibs.get(orderEntry);
-      final VirtualFile[] roots = ((LibraryOrderEntry)orderEntry).getRootFiles(OrderRootType.CLASSES);
-      if (files.size() < roots.length) {
-        final String unusedLibraryRoots = StringUtil.join(files, new Function<VirtualFile, String>() {
-            @Override
-            public String fun(final VirtualFile file) {
-              return file.getPresentableName();
-            }
-          }, ",");
-        String message =
-          InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, orderEntry.getPresentableName());
-        problemProcessor.addProblemElement(refModule,
-                                           manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, files)));
-      }
-      else {
-        String message = InspectionsBundle.message("unused.library.problem.descriptor", orderEntry.getPresentableName());
-        problemProcessor.addProblemElement(refModule,
-                                           manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, null)));
-      }
-    }
-  }
-
-  @Override
-  public boolean isEnabledByDefault() {
-    return false;
-  }
-
-  @Override
-  @Nls
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return InspectionsBundle.message("unused.library.display.name");
-  }
-
-  @Override
-  @NonNls
-  @NotNull
-  public String getShortName() {
-    return "UnusedLibrary";
-  }
-
-  private static class RemoveUnusedLibrary implements QuickFix {
-    private final RefModule myRefModule;
-    private final OrderEntry myOrderEntry;
-    private final Set<VirtualFile> myFiles;
-
-    public RemoveUnusedLibrary(final RefModule refModule, final OrderEntry orderEntry, final Set<VirtualFile> files) {
-      myRefModule = refModule;
-      myOrderEntry = orderEntry;
-      myFiles = files;
-    }
-
-    @Override
-    @NotNull
-    public String getName() {
-      return myFiles == null ? InspectionsBundle.message("detach.library.quickfix.name") : InspectionsBundle.message("detach.library.roots.quickfix.name");
-    }
-
-    @Override
-    @NotNull
-    public String getFamilyName() {
-      return getName();
-    }
-
-    @Override
-    public void applyFix(@NotNull final Project project, @NotNull final CommonProblemDescriptor descriptor) {
-      final Module module = myRefModule.getModule();
-
-      ApplicationManager.getApplication().runWriteAction(new Runnable() {
-        @Override
-        public void run() {
-          final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
-          for (OrderEntry entry : model.getOrderEntries()) {
-            if (entry instanceof LibraryOrderEntry && Comparing.strEqual(entry.getPresentableName(), myOrderEntry.getPresentableName())) {
-              if (myFiles == null) {
-                model.removeOrderEntry(entry);
-              }
-              else {
-                final Library library = ((LibraryOrderEntry)entry).getLibrary();
-                if (library != null) {
-                  final Library.ModifiableModel modifiableModel = library.getModifiableModel();
-                  for (VirtualFile file : myFiles) {
-                    modifiableModel.removeRoot(file.getUrl(), OrderRootType.CLASSES);
-                  }
-                  modifiableModel.commit();
-                }
-              }
-            }
-          }
-          model.commit();
-        }
-      });
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
index 5d576bb..9750838 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
@@ -28,9 +28,10 @@
 import com.intellij.codeInsight.FileModificationService;
 import com.intellij.codeInsight.daemon.GroupNames;
 import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
+import com.intellij.codeInspection.ex.EntryPointsManager;
 import com.intellij.codeInspection.reference.*;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectUtil;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.psi.*;
 import com.intellij.psi.search.PsiReferenceProcessor;
@@ -52,8 +53,7 @@
 import java.util.Collection;
 import java.util.List;
 
-public class UnusedParametersInspection extends GlobalJavaInspectionTool {
-
+public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
   @NonNls public static final String SHORT_NAME = "UnusedParameters";
 
   @Override
@@ -83,7 +83,7 @@
       if (refMethod.isEntry()) return null;
 
       final PsiModifierListOwner element = refMethod.getElement();
-      if (element != null && EntryPointsManagerImpl.getInstance(manager.getProject()).isEntryPoint(element)) return null;
+      if (element != null && EntryPointsManager.getInstance(manager.getProject()).isEntryPoint(element)) return null;
 
       final List<ProblemDescriptor> result = new ArrayList<ProblemDescriptor>();
       for (RefParameter refParameter : unusedParameters) {
@@ -235,7 +235,8 @@
   @Override
   public JComponent createOptionsPanel() {
     final JPanel panel = new JPanel(new GridBagLayout());
-    panel.add(EntryPointsManagerImpl.createConfigureAnnotationsBtn(panel),
+    Project project = ProjectUtil.guessCurrentProject(panel);
+    panel.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(),
               new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
                                      new Insets(0, 0, 0, 0), 0, 0));
     return panel;
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java b/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
index 2bfbdf8..1ca2c0e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
@@ -41,7 +41,7 @@
 /**
  * @author max
  */
-public class UnusedReturnValue extends GlobalJavaInspectionTool{
+public class UnusedReturnValue extends GlobalJavaBatchInspectionTool{
   private MakeVoidQuickFix myQuickFix;
 
   public boolean IGNORE_BUILDER_PATTERN = false;
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
index f88e751..1f7434e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
@@ -22,10 +22,12 @@
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
 import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
-import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
+import com.intellij.codeInspection.ex.EntryPointsManager;
+import com.intellij.codeInspection.ex.EntryPointsManagerBase;
 import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
 import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectUtil;
 import com.intellij.psi.PsiModifierListOwner;
 import org.intellij.lang.annotations.Pattern;
 import org.jetbrains.annotations.Nls;
@@ -92,6 +94,7 @@
     return true;
   }
 
+  @NotNull
   @Override
   public String getInspectionForBatchShortName() {
     return UnusedDeclarationInspection.SHORT_NAME;
@@ -136,7 +139,8 @@
       myCheckClassesCheckBox.addActionListener(listener);
       myCheckParametersCheckBox.addActionListener(listener);
       myReportUnusedParametersInPublics.addActionListener(listener);
-      myAnnos.add(EntryPointsManagerImpl.createConfigureAnnotationsBtn(myPanel),
+      Project project = ProjectUtil.guessCurrentProject(myPanel);
+      myAnnos.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(),
                   new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
                                          new Insets(10, 0, 0, 0), 0, 0));
     }
@@ -153,7 +157,7 @@
   }
 
   public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) {
-    final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(project);
+    final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
     return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
       QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
       QuickFixBundle.message("fix.unused.symbol.injection.family"),
@@ -161,6 +165,6 @@
   }
 
   public static boolean isInjected(final PsiModifierListOwner modifierListOwner) {
-    return EntryPointsManagerImpl.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
+    return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
   }
 }
diff --git a/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java b/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java
deleted file mode 100644
index 4e9f11a..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 1, 2001
- * Time: 11:42:56 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.util;
-
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.reference.RefJavaElement;
-import com.intellij.codeInspection.reference.RefParameter;
-
-public abstract class RefFilter {
-  // Default accepts implementation accepts element if one under unaccepted one. Thus it will accept all and only upper level classes.
-  public int getElementProblemCount(RefJavaElement refElement) {
-    if (refElement instanceof RefParameter) return 0;
-    RefEntity refOwner = refElement.getOwner();
-    if (refOwner == null || !(refOwner instanceof RefJavaElement)) return 1;
-
-    return 1 - getElementProblemCount((RefJavaElement)refOwner);
-  }
-
-  public final boolean accepts(RefJavaElement refElement) {
-    return getElementProblemCount(refElement) > 0;
-  }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
deleted file mode 100644
index ab0a63e..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.visibility;
-
-import com.intellij.codeInspection.ProblemDescriptionsProcessor;
-import com.intellij.codeInspection.reference.RefManager;
-import org.jetbrains.annotations.NotNull;
-
-public interface VisibilityExtension {
-  void fillIgnoreList(@NotNull RefManager refManager, @NotNull ProblemDescriptionsProcessor processor);
-}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
deleted file mode 100644
index 88ff09b..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 21, 2001
- * Time: 8:46:41 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.visibility;
-
-import com.intellij.ExtensionPoints;
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.EntryPointsManager;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
-import com.intellij.psi.search.PsiSearchHelper;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.util.List;
-
-public class VisibilityInspection extends GlobalJavaInspectionTool {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.visibility.VisibilityInspection");
-  public boolean SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = true;
-  public boolean SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = true;
-  public boolean SUGGEST_PRIVATE_FOR_INNERS = false;
-  private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.visibility.display.name");
-  @NonNls private static final String SHORT_NAME = "WeakerAccess";
-  private static final String CAN_BE_PRIVATE = InspectionsBundle.message("inspection.visibility.compose.suggestion", "private");
-  private static final String CAN_BE_PACKAGE_LOCAL = InspectionsBundle.message("inspection.visibility.compose.suggestion", "package local");
-  private static final String CAN_BE_PROTECTED = InspectionsBundle.message("inspection.visibility.compose.suggestion", "protected");
-
-  private class OptionsPanel extends JPanel {
-    private final JCheckBox myPackageLocalForMembersCheckbox;
-    private final JCheckBox myPrivateForInnersCheckbox;
-    private final JCheckBox myPackageLocalForTopClassesCheckbox;
-
-    private OptionsPanel() {
-      super(new GridBagLayout());
-
-      GridBagConstraints gc = new GridBagConstraints();
-      gc.fill = GridBagConstraints.HORIZONTAL;
-      gc.weightx = 1;
-      gc.weighty = 0;
-      gc.anchor = GridBagConstraints.NORTHWEST;
-
-      myPackageLocalForMembersCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option"));
-      myPackageLocalForMembersCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS);
-      myPackageLocalForMembersCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = myPackageLocalForMembersCheckbox.isSelected();
-        }
-      });
-
-      gc.gridy = 0;
-      add(myPackageLocalForMembersCheckbox, gc);
-
-      myPackageLocalForTopClassesCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option1"));
-      myPackageLocalForTopClassesCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES);
-      myPackageLocalForTopClassesCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = myPackageLocalForTopClassesCheckbox.isSelected();
-        }
-      });
-
-      gc.gridy = 1;
-      add(myPackageLocalForTopClassesCheckbox, gc);
-
-
-      myPrivateForInnersCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option2"));
-      myPrivateForInnersCheckbox.setSelected(SUGGEST_PRIVATE_FOR_INNERS);
-      myPrivateForInnersCheckbox.getModel().addChangeListener(new ChangeListener() {
-        @Override
-        public void stateChanged(ChangeEvent e) {
-          SUGGEST_PRIVATE_FOR_INNERS = myPrivateForInnersCheckbox.isSelected();
-        }
-      });
-
-      gc.gridy = 2;
-      gc.weighty = 1;
-      add(myPrivateForInnersCheckbox, gc);
-    }
-  }
-
-  @Override
-  public JComponent createOptionsPanel() {
-    return new OptionsPanel();
-  }
-
-  @Override
-  @NotNull
-  public String getDisplayName() {
-    return DISPLAY_NAME;
-  }
-
-  @Override
-  @NotNull
-  public String getGroupDisplayName() {
-    return GroupNames.DECLARATION_REDUNDANCY;
-  }
-
-  @Override
-  @NotNull
-  public String getShortName() {
-    return SHORT_NAME;
-  }
-
-  @Override
-  @Nullable
-  public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
-                                                @NotNull final AnalysisScope scope,
-                                                @NotNull final InspectionManager manager,
-                                                @NotNull final GlobalInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor processor) {
-    if (refEntity instanceof RefJavaElement) {
-      final RefJavaElement refElement = (RefJavaElement)refEntity;
-
-      if (refElement instanceof RefParameter) return null;
-      if (refElement.isSyntheticJSP()) return null;
-
-      //ignore entry points.
-      if (refElement.isEntry()) return null;
-
-      //ignore implicit constructors. User should not be able to see them.
-      if (refElement instanceof RefImplicitConstructor) return null;
-
-      if (refElement instanceof RefField && ((RefField)refElement).getElement() instanceof PsiEnumConstant) return null;
-
-      //ignore library override methods.
-      if (refElement instanceof RefMethod) {
-        RefMethod refMethod = (RefMethod) refElement;
-        if (refMethod.isExternalOverride()) return null;
-        if (refMethod.isEntry()) return null;
-      }
-
-      //ignore anonymous classes. They do not have access modifiers.
-      if (refElement instanceof RefClass) {
-        RefClass refClass = (RefClass) refElement;
-        if (refClass.isAnonymous() || refClass.isEntry() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null;
-        if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
-      }
-
-      //ignore unreferenced code. They could be a potential entry points.
-      if (refElement.getInReferences().isEmpty()) return null;
-
-      //ignore interface members. They always have public access modifier.
-      if (refElement.getOwner() instanceof RefClass) {
-        RefClass refClass = (RefClass) refElement.getOwner();
-        if (refClass.isInterface()) return null;
-      }
-      String access = getPossibleAccess(refElement);
-      if (access != refElement.getAccessModifier() && access != null) {
-        final PsiElement element = refElement.getElement();
-        final PsiElement nameIdentifier = element != null ? HighlightUsagesHandler.getNameIdentifier(element) : null;
-        if (nameIdentifier != null) {
-          return new ProblemDescriptor[]{manager.createProblemDescriptor(nameIdentifier,
-                                                                         access.equals(PsiModifier.PRIVATE)
-                                                                          ? CAN_BE_PRIVATE
-                                                                          : access.equals(PsiModifier.PACKAGE_LOCAL)
-                                                                            ? CAN_BE_PACKAGE_LOCAL
-                                                                            : CAN_BE_PROTECTED,
-                                                                         new AcceptSuggestedAccess(globalContext.getRefManager(), access),
-                                                                         ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
-        }
-      }
-    }
-    return null;
-  }
-
-  @Nullable
-  @PsiModifier.ModifierConstant
-  public String getPossibleAccess(@Nullable RefJavaElement refElement) {
-    if (refElement == null) return null;
-    String curAccess = refElement.getAccessModifier();
-    String weakestAccess = PsiModifier.PRIVATE;
-
-    if (isTopLevelClass(refElement) || isCalledOnSubClasses(refElement)) {
-      weakestAccess = PsiModifier.PACKAGE_LOCAL;
-    }
-
-    if (isAbstractMethod(refElement)) {
-      weakestAccess = PsiModifier.PROTECTED;
-    }
-
-    if (curAccess == weakestAccess) return curAccess;
-
-    while (true) {
-      String weakerAccess = getWeakerAccess(curAccess, refElement);
-      if (weakerAccess == null || RefJavaUtil.getInstance().compareAccess(weakerAccess, weakestAccess) < 0) break;
-      if (isAccessible(refElement, weakerAccess)) {
-        curAccess = weakerAccess;
-      }
-      else {
-        break;
-      }
-    }
-
-    return curAccess;
-  }
-
-  private static boolean isCalledOnSubClasses(RefElement refElement) {
-    return refElement instanceof RefMethod && ((RefMethod)refElement).isCalledOnSubClass();
-  }
-
-  private static boolean isAbstractMethod(RefElement refElement) {
-    return refElement instanceof RefMethod && ((RefMethod) refElement).isAbstract();
-  }
-
-  private static boolean isTopLevelClass(RefElement refElement) {
-    return refElement instanceof RefClass && RefJavaUtil.getInstance().getTopLevelClass(refElement) == refElement;
-  }
-
-  @Nullable
-  @PsiModifier.ModifierConstant
-  private String getWeakerAccess(@PsiModifier.ModifierConstant String curAccess, RefElement refElement) {
-    if (curAccess == PsiModifier.PUBLIC) {
-      return isTopLevelClass(refElement) ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PROTECTED;
-    }
-    if (curAccess == PsiModifier.PROTECTED) {
-      return SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PRIVATE;
-    }
-    if (curAccess == PsiModifier.PACKAGE_LOCAL) {
-      return PsiModifier.PRIVATE;
-    }
-
-    return null;
-  }
-
-  private boolean isAccessible(RefJavaElement to, @PsiModifier.ModifierConstant String accessModifier) {
-
-    for (RefElement refElement : to.getInReferences()) {
-      if (!isAccessibleFrom(refElement, to, accessModifier)) return false;
-    }
-
-    if (to instanceof RefMethod) {
-      RefMethod refMethod = (RefMethod) to;
-
-      if (refMethod.isAbstract() && (refMethod.getDerivedMethods().isEmpty() || refMethod.getAccessModifier() == PsiModifier.PRIVATE)) return false;
-
-      for (RefMethod refOverride : refMethod.getDerivedMethods()) {
-        if (!isAccessibleFrom(refOverride, to, accessModifier)) return false;
-      }
-
-      for (RefMethod refSuper : refMethod.getSuperMethods()) {
-        if (RefJavaUtil.getInstance().compareAccess(refSuper.getAccessModifier(), accessModifier) > 0) return false;
-      }
-    }
-
-    if (to instanceof RefClass) {
-      RefClass refClass = (RefClass) to;
-      for (RefClass subClass : refClass.getSubClasses()) {
-        if (!isAccessibleFrom(subClass, to, accessModifier)) return false;
-      }
-
-      List children = refClass.getChildren();
-      if (children != null) {
-        for (Object refElement : children) {
-          if (!isAccessible((RefJavaElement)refElement, accessModifier)) return false;
-        }
-      }
-
-      for (final RefElement refElement : refClass.getInTypeReferences()) {
-        if (!isAccessibleFrom(refElement, refClass, accessModifier)) return false;
-      }
-
-      List<RefJavaElement> classExporters = ((RefClassImpl)refClass).getClassExporters();
-      if (classExporters != null) {
-        for (RefJavaElement refExporter : classExporters) {
-          if (getAccessLevel(accessModifier) < getAccessLevel(refExporter.getAccessModifier())) return false;
-        }
-      }
-    }
-
-    return true;
-  }
-
-  private static int getAccessLevel(@PsiModifier.ModifierConstant String access) {
-    if (access == PsiModifier.PRIVATE) return 1;
-    if (access == PsiModifier.PACKAGE_LOCAL) return 2;
-    if (access == PsiModifier.PROTECTED) return 3;
-    return 4;
-  }
-
-  private boolean isAccessibleFrom(RefElement from, RefJavaElement to, String accessModifier) {
-    if (accessModifier == PsiModifier.PUBLIC) return true;
-
-    final RefJavaUtil refUtil = RefJavaUtil.getInstance();
-    if (accessModifier == PsiModifier.PACKAGE_LOCAL) {
-      return RefJavaUtil.getPackage(from) == RefJavaUtil.getPackage(to);
-    }
-
-    RefClass fromTopLevel = refUtil.getTopLevelClass(from);
-    RefClass toTopLevel = refUtil.getTopLevelClass(to);
-    RefClass fromOwner = refUtil.getOwnerClass(from);
-    RefClass toOwner = refUtil.getOwnerClass(to);
-
-    if (accessModifier == PsiModifier.PROTECTED) {
-      if (SUGGEST_PRIVATE_FOR_INNERS) {
-        return refUtil.isInheritor(fromTopLevel, toOwner)
-               || fromOwner != null && refUtil.isInheritor(fromOwner, toTopLevel)
-               || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
-      }
-
-      return refUtil.isInheritor(fromTopLevel, toOwner);
-    }
-
-    if (accessModifier == PsiModifier.PRIVATE) {
-      if (SUGGEST_PRIVATE_FOR_INNERS) {
-        if (isInExtendsList(to, fromTopLevel.getElement().getExtendsList())) return false;
-        if (isInExtendsList(to, fromTopLevel.getElement().getImplementsList())) return false;
-        if (isInAnnotations(to, fromTopLevel)) return false;
-        return fromTopLevel == toOwner || fromOwner == toTopLevel || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
-      }
-
-      if (fromOwner != null && fromOwner.isStatic() && !to.isStatic() && refUtil.isInheritor(fromOwner, toOwner)) return false;
-
-      if (fromTopLevel == toOwner) {
-        if (from instanceof RefClass && to instanceof RefClass) {
-          final PsiClass fromClass = ((RefClass)from).getElement();
-          LOG.assertTrue(fromClass != null);
-          if (isInExtendsList(to, fromClass.getExtendsList())) return false;
-          if (isInExtendsList(to, fromClass.getImplementsList())) return false;
-        }
-
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  private static boolean isInAnnotations(final RefJavaElement to, final RefClass fromTopLevel) {
-    final PsiModifierList modifierList = fromTopLevel.getElement().getModifierList();
-    if (modifierList == null) return false;
-    final PsiElement toElement = to.getElement();
-
-    final boolean [] resolved = new boolean[] {false};
-    modifierList.accept(new JavaRecursiveElementWalkingVisitor() {
-      @Override
-      public void visitReferenceExpression(PsiReferenceExpression expression) {
-        if (resolved[0]) return;
-        super.visitReferenceExpression(expression);
-        if (expression.resolve() == toElement) {
-          resolved[0] = true;
-        }
-      }
-    });
-    return resolved[0];
-  }
-
-  private static boolean isInExtendsList(final RefJavaElement to, final PsiReferenceList extendsList) {
-    if (extendsList != null) {
-      final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
-      for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
-        final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
-        if (parameterList != null) {
-          for (PsiType type : parameterList.getTypeArguments()) {
-            if (extendsList.getManager().areElementsEquivalent(PsiUtil.resolveClassInType(type), to.getElement())) {
-              return true;
-            }
-          }
-        }
-      }
-    }
-    return false;
-  }
-
-
-  @Override
-  protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
-                                                @NotNull final GlobalJavaInspectionContext globalContext,
-                                                @NotNull final ProblemDescriptionsProcessor processor) {
-    final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
-    for (RefElement entryPoint : entryPointsManager.getEntryPoints()) {
-      ignoreElement(processor, entryPoint);
-    }
-
-    ExtensionPoint<VisibilityExtension> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.VISIBLITY_TOOL);
-    for (VisibilityExtension addin : point.getExtensions()) {
-      addin.fillIgnoreList(manager, processor);
-    }
-    manager.iterate(new RefJavaVisitor() {
-      @Override public void visitElement(@NotNull final RefEntity refEntity) {
-        if (!(refEntity instanceof RefElement)) return;
-        if (processor.getDescriptions(refEntity) == null) return;
-        refEntity.accept(new RefJavaVisitor() {
-          @Override public void visitField(@NotNull final RefField refField) {
-            if (refField.getAccessModifier() != PsiModifier.PRIVATE) {
-              globalContext.enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
-                @Override
-                public boolean process(PsiReference psiReference) {
-                  ignoreElement(processor, refField);
-                  return false;
-                }
-              });
-            }
-          }
-
-          @Override public void visitMethod(@NotNull final RefMethod refMethod) {
-            if (!refMethod.isExternalOverride() && refMethod.getAccessModifier() != PsiModifier.PRIVATE &&
-                !(refMethod instanceof RefImplicitConstructor)) {
-              globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
-                @Override
-                public boolean process(PsiMethod derivedMethod) {
-                  ignoreElement(processor, refMethod);
-                  return false;
-                }
-              });
-
-              globalContext.enqueueMethodUsagesProcessor(refMethod, new GlobalJavaInspectionContext.UsagesProcessor() {
-                @Override
-                public boolean process(PsiReference psiReference) {
-                  ignoreElement(processor, refMethod);
-                  return false;
-                }
-              });
-
-              if (entryPointsManager.isAddNonJavaEntries()) {
-                final RefClass ownerClass = refMethod.getOwnerClass();
-                if (refMethod.isConstructor() && ownerClass.getDefaultConstructor() != null) {
-                  String qualifiedName = ownerClass.getElement().getQualifiedName();
-                  if (qualifiedName != null) {
-                    final Project project = manager.getProject();
-                    PsiSearchHelper.SERVICE.getInstance(project)
-                      .processUsagesInNonJavaFiles(qualifiedName, new PsiNonJavaFileReferenceProcessor() {
-                        @Override
-                        public boolean process(PsiFile file, int startOffset, int endOffset) {
-                          entryPointsManager.addEntryPoint(refMethod, false);
-                          ignoreElement(processor, refMethod);
-                          return false;
-                        }
-                      }, GlobalSearchScope.projectScope(project));
-                  }
-                }
-              }
-            }
-          }
-
-          @Override public void visitClass(@NotNull final RefClass refClass) {
-            if (!refClass.isAnonymous()) {
-              globalContext.enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
-                @Override
-                public boolean process(PsiClass inheritor) {
-                  ignoreElement(processor, refClass);
-                  return false;
-                }
-              });
-
-              globalContext.enqueueClassUsagesProcessor(refClass, new GlobalJavaInspectionContext.UsagesProcessor() {
-                @Override
-                public boolean process(PsiReference psiReference) {
-                  ignoreElement(processor, refClass);
-                  return false;
-                }
-              });
-            }
-          }
-        });
-
-      }
-    });
-    return false;
-  }
-
-  private static void ignoreElement(@NotNull ProblemDescriptionsProcessor processor, @NotNull RefEntity refElement){
-    processor.ignoreElement(refElement);
-
-    if (refElement instanceof RefClass) {
-      RefClass refClass = (RefClass) refElement;
-      RefMethod defaultConstructor = refClass.getDefaultConstructor();
-      if (defaultConstructor != null) {
-        processor.ignoreElement(defaultConstructor);
-        return;
-      }
-    }
-
-    RefEntity owner = refElement.getOwner();
-    if (owner instanceof RefElement) {
-      processor.ignoreElement(owner);
-    }
-  }
-
-  @Override
-  public void compose(@NotNull final StringBuffer buf, @NotNull final RefEntity refEntity, @NotNull final HTMLComposer composer) {
-    composer.appendElementInReferences(buf, (RefElement)refEntity);
-  }
-
-  @Override
-  @Nullable
-  public QuickFix getQuickFix(final String hint) {
-    return new AcceptSuggestedAccess(null, hint);
-  }
-
-  @Override
-  @Nullable
-  public String getHint(@NotNull final QuickFix fix) {
-    return ((AcceptSuggestedAccess)fix).getHint();
-  }
-
-  private static class AcceptSuggestedAccess implements LocalQuickFix{
-    private final RefManager myManager;
-    @PsiModifier.ModifierConstant private final String myHint;
-
-    private AcceptSuggestedAccess(final RefManager manager, @PsiModifier.ModifierConstant String hint) {
-      myManager = manager;
-      myHint = hint;
-    }
-
-    @Override
-    @NotNull
-    public String getName() {
-      return InspectionsBundle.message("inspection.visibility.accept.quickfix");
-    }
-
-    @Override
-    @NotNull
-    public String getFamilyName() {
-      return getName();
-    }
-
-    @Override
-    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
-      if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
-      final PsiModifierListOwner element = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiModifierListOwner.class);
-      if (element != null) {
-        RefElement refElement = null;
-        if (myManager != null) {
-          refElement = myManager.getReference(element);
-        }
-        try {
-          if (element instanceof PsiVariable) {
-            ((PsiVariable)element).normalizeDeclaration();
-          }
-
-          PsiModifierList list = element.getModifierList();
-
-          LOG.assertTrue(list != null);
-
-          if (element instanceof PsiMethod) {
-            PsiMethod psiMethod = (PsiMethod)element;
-            PsiClass containingClass = psiMethod.getContainingClass();
-            if (containingClass != null && containingClass.getParent() instanceof PsiFile &&
-                myHint == PsiModifier.PRIVATE &&
-                list.hasModifierProperty(PsiModifier.FINAL)) {
-              list.setModifierProperty(PsiModifier.FINAL, false);
-            }
-          }
-
-          list.setModifierProperty(myHint, true);
-          if (refElement instanceof RefJavaElement) {
-            RefJavaUtil.getInstance().setAccessModifier((RefJavaElement)refElement, myHint);
-          }
-        }
-        catch (IncorrectOperationException e) {
-          LOG.error(e);
-        }
-      }
-    }
-
-    public String getHint() {
-      return myHint;
-    }
-  }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java
new file mode 100644
index 0000000..0f2d3de
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java
@@ -0,0 +1,50 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ArrayListKeyDescriptor<E> implements KeyDescriptor<List<E>> {
+
+  private final DataExternalizer<E> myDataExternalizer;
+
+  public ArrayListKeyDescriptor(final DataExternalizer<E> dataExternalizer) {
+    myDataExternalizer = dataExternalizer;
+  }
+
+  @Override
+  public void save(final DataOutput out, final List<E> list) throws IOException {
+    out.writeInt(list.size());
+    for (final E element : list) {
+      myDataExternalizer.save(out, element);
+    }
+  }
+
+  @Override
+  public ArrayList<E> read(final DataInput in) throws IOException {
+    final int size = in.readInt();
+    final ArrayList<E> list = new ArrayList<E>(size);
+    for (int i = 0; i < size; i++) {
+      list.add(myDataExternalizer.read(in));
+    }
+    return list;
+  }
+
+  @Override
+  public int getHashCode(final List<E> value) {
+    return value.hashCode();
+  }
+
+  @Override
+  public boolean isEqual(final List<E> val1, final List<E> val2) {
+    return val1.equals(val2);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java
new file mode 100644
index 0000000..1f012dd
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java
@@ -0,0 +1,54 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class HashMapKeyDescriptor<K, V> implements KeyDescriptor<Map<K, V>> {
+
+  private final DataExternalizer<K> myKeyDataExternalizer;
+  private final DataExternalizer<V> myValueDataExternalizer;
+
+  public HashMapKeyDescriptor(final DataExternalizer<K> keyDataExternalizer, final DataExternalizer<V> valueDataExternalizer) {
+    myKeyDataExternalizer = keyDataExternalizer;
+    myValueDataExternalizer = valueDataExternalizer;
+  }
+
+  @Override
+  public void save(final DataOutput out, final Map<K, V> map) throws IOException {
+    final int size = map.size();
+    out.writeInt(size);
+    for (final Map.Entry<K, V> e : map.entrySet()) {
+      myKeyDataExternalizer.save(out, e.getKey());
+      myValueDataExternalizer.save(out, e.getValue());
+    }
+  }
+
+  @Override
+  public Map<K, V> read(final DataInput in) throws IOException {
+    final int size = in.readInt();
+    final HashMap<K, V> map = new HashMap<K, V>(size);
+    for (int i = 0; i < size; i++) {
+      map.put(myKeyDataExternalizer.read(in), myValueDataExternalizer.read(in));
+    }
+    return map;
+  }
+
+  @Override
+  public int getHashCode(final Map<K, V> map) {
+    return map.hashCode();
+  }
+
+  @Override
+  public boolean isEqual(final Map<K, V> val1, final Map<K, V> val2) {
+    return val1.equals(val2);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java
new file mode 100644
index 0000000..1201ccf
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java
@@ -0,0 +1,54 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class HashSetKeyDescriptor<K> implements KeyDescriptor<Set<K>> {
+
+  private final DataExternalizer<K> keyDataExternalizer;
+
+  public HashSetKeyDescriptor(final DataExternalizer<K> keyDataExternalizer) {
+    this.keyDataExternalizer = keyDataExternalizer;
+  }
+
+  @Override
+  public void save(final DataOutput out, final Set<K> set) throws IOException {
+    out.writeInt(set.size());
+    for (final K k : set) {
+      keyDataExternalizer.save(out, k);
+    }
+  }
+
+  @Override
+  public HashSet<K> read(final DataInput in) throws IOException {
+    final int size = in.readInt();
+    final HashSet<K> set = new HashSet<K>(size);
+    for (int i = 0; i < size; i++) {
+      set.add(keyDataExternalizer.read(in));
+    }
+    return set;
+  }
+
+  public static <K> HashSetKeyDescriptor<K> of(final DataExternalizer<K> keyDataExternalizer) {
+    return new HashSetKeyDescriptor<K>(keyDataExternalizer);
+  }
+
+  @Override
+  public int getHashCode(final Set<K> value) {
+    return value.hashCode();
+  }
+
+  @Override
+  public boolean isEqual(final Set<K> val1, final Set<K> val2) {
+    return val1.equals(val2);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
new file mode 100644
index 0000000..45f761e
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
@@ -0,0 +1,129 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.asm4.Type;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class AsmUtil implements Opcodes {
+
+  private AsmUtil() {}
+
+  public static boolean isStaticMethodDeclaration(final int access) {
+    return (access & Opcodes.ACC_STATIC) != 0;
+  }
+
+  public static boolean isStaticMethodInvocation(final int opcode) {
+    return opcode == Opcodes.INVOKESTATIC;
+  }
+
+  public static String getQualifiedClassName(final String name) {
+    return asJavaInnerClassQName(Type.getObjectType(name).getClassName());
+  }
+
+  public static String getReturnType(final String desc) {
+    return asJavaInnerClassQName(Type.getReturnType(desc).getClassName());
+  }
+
+  public static String[] getQualifiedClassNames(final String[] classNames, final String... yetAnotherClassNames) {
+    final List<String> qualifiedClassNames = new ArrayList<String>(classNames.length + yetAnotherClassNames.length);
+    for (final String className : classNames) {
+      qualifiedClassNames.add(getQualifiedClassName(className));
+    }
+    for (final String className : yetAnotherClassNames) {
+      if (className != null) {
+        qualifiedClassNames.add(getQualifiedClassName(className));
+      }
+    }
+    return ArrayUtil.toStringArray(qualifiedClassNames);
+  }
+
+  public static String[] getParamsTypes(final String desc) {
+    final Type[] types = Type.getArgumentTypes(desc);
+    final String[] typesAsString = new String[types.length];
+    for (int i = 0; i < types.length; i++) {
+      typesAsString[i] = types[i].getClassName();
+    }
+    return typesAsString;
+  }
+
+  @Nullable
+  public static String getSignature(final PsiMethod psiMethod) {
+    final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
+    final StringBuilder sb = new StringBuilder();
+    sb.append("(");
+    for (final PsiParameter p : parameters) {
+      final String desc = getDescriptor(p);
+      if (desc == null) {
+        return null;
+      }
+      sb.append(desc);
+    }
+    sb.append(")");
+    final String desc = getDescriptor(psiMethod.getReturnType());
+    if (desc == null) {
+      return null;
+    }
+    sb.append(desc);
+    return sb.toString();
+  }
+
+  @Nullable
+  private static String getDescriptor(final PsiParameter parameter) {
+    return getDescriptor(parameter.getType());
+  }
+
+  @Nullable
+  private static String getDescriptor(@Nullable final PsiType type) {
+    if (type == null) {
+      return null;
+    }
+    if (type instanceof PsiPrimitiveType) {
+      final PsiPrimitiveType primitiveType = (PsiPrimitiveType) type;
+      if (PsiType.INT.equals(primitiveType)) {
+        return "I";
+      } else if (primitiveType.equals(PsiType.VOID)) {
+        return "V";
+      } else if (primitiveType.equals(PsiType.BOOLEAN)) {
+        return "Z";
+      } else if (primitiveType.equals(PsiType.BYTE)) {
+        return "B";
+      } else if (primitiveType.equals(PsiType.CHAR)) {
+        return "C";
+      } else if (primitiveType.equals(PsiType.SHORT)) {
+        return "S";
+      } else if (primitiveType.equals(PsiType.DOUBLE)) {
+        return "D";
+      } else if (primitiveType.equals(PsiType.FLOAT)) {
+        return "F";
+      } else /* if (primitiveType.equals(PsiType.LONG)) */ {
+        return "J";
+      }
+    } else if (type instanceof PsiArrayType) {
+      return "[" + getDescriptor(((PsiArrayType) type).getComponentType());
+    } else {
+      final PsiClassType classType = (PsiClassType) type;
+      final PsiClass aClass = classType.resolve();
+      if (aClass == null) {
+        return null;
+      }
+      final String qName = aClass.getQualifiedName();
+      if (qName == null) {
+        return null;
+      }
+      return "L" + StringUtil.replace(qName, ".", "/") + ";";
+    }
+  }
+
+  private static String asJavaInnerClassQName(final String byteCodeClassQName) {
+    return StringUtil.replaceChar(byteCodeClassQName, '$', '.');
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
new file mode 100644
index 0000000..ef41370
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
@@ -0,0 +1,64 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.compiler.CompilerPaths;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class CompilerOutputFilesUtil {
+
+  private CompilerOutputFilesUtil() {}
+
+  public final static String CLASS_FILES_SUFFIX = ".class";
+
+  public static void iterateProjectClassFiles(@NotNull final Project project, @NotNull final Consumer<File> fileConsumer) {
+    for (final Module module : ModuleManager.getInstance(project).getModules()) {
+      iterateModuleClassFiles(module, fileConsumer);
+    }
+  }
+
+  public static void iterateModuleClassFiles(@NotNull final Module module, @NotNull final Consumer<File> fileConsumer) {
+    final VirtualFile moduleOutputDirectory = CompilerPaths.getModuleOutputDirectory(module, false);
+    if (moduleOutputDirectory == null) {
+      return;
+    }
+    final String canonicalPath = moduleOutputDirectory.getCanonicalPath();
+    if (canonicalPath == null) {
+      return;
+    }
+    final File root = new File(canonicalPath);
+    iterateClassFilesOverRoot(root, fileConsumer);
+  }
+
+  public static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer) {
+    iterateClassFilesOverRoot(file, fileConsumer, new HashSet<File>());
+  }
+
+  private static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer, final Set<File> visited) {
+    if (file.isDirectory()) {
+      final File[] files = file.listFiles();
+      if (files != null) {
+        for (final File childFile : files) {
+          if (visited.add(childFile)) {
+            iterateClassFilesOverRoot(childFile.getAbsoluteFile(), fileConsumer, visited);
+          }
+        }
+      }
+    }
+    else {
+      if (file.getName().endsWith(CLASS_FILES_SUFFIX)) {
+        fileConsumer.consume(file);
+      }
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
new file mode 100644
index 0000000..9a7f00b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
@@ -0,0 +1,53 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.util.Consumer;
+
+import java.io.File;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public interface FileVisitorService {
+
+  interface Visitor {
+    void visit(File file);
+  }
+
+  void visit(final Consumer<File> visitor);
+
+  class ProjectClassFiles implements FileVisitorService {
+    private final Project myProject;
+
+    public ProjectClassFiles(final Project project) {
+      myProject = project;
+    }
+
+    @Override
+    public void visit(final Consumer<File> visitor) {
+      CompilerOutputFilesUtil.iterateProjectClassFiles(myProject, visitor);
+    }
+  }
+
+  class DirectoryClassFiles implements FileVisitorService {
+    private final File myDir;
+
+    public DirectoryClassFiles(final File dir) {
+      if (!dir.isDirectory()) {
+        throw new IllegalArgumentException();
+      }
+      myDir = dir;
+    }
+
+    @Override
+    public void visit(final Consumer<File> visitor) {
+      //noinspection ConstantConditions
+      for (final File file : myDir.listFiles()) {
+        if (file.getName().endsWith(CompilerOutputFilesUtil.CLASS_FILES_SUFFIX)) {
+          visitor.consume(file);
+        }
+      }
+    }
+  }
+}
+
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
new file mode 100644
index 0000000..a37368b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
@@ -0,0 +1,141 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Factory;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.asm4.ClassReader;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+import static com.intellij.util.indexing.IndexInfrastructure.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class CompilerOutputBaseIndex<K, V> {
+  public final static ExtensionPointName<CompilerOutputBaseIndex> EXTENSION_POINT_NAME =
+    ExtensionPointName.create("com.intellij.java.compilerOutputIndex");
+
+  private final static Logger LOG = Logger.getInstance(CompilerOutputBaseIndex.class);
+  private final KeyDescriptor<K> myKeyDescriptor;
+  private final DataExternalizer<V> myValueExternalizer;
+
+  protected volatile MapReduceIndex<K, V, ClassReader> myIndex;
+
+  private volatile Project myProject;
+
+  public CompilerOutputBaseIndex(final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer) {
+    myKeyDescriptor = keyDescriptor;
+    myValueExternalizer = valueExternalizer;
+  }
+
+  public final boolean init(final Project project) {
+    myProject = project;
+    final MapReduceIndex<K, V, ClassReader> index;
+    final Ref<Boolean> rewriteIndex = new Ref<Boolean>(false);
+    try {
+      final ID<K, V> indexId = getIndexId();
+      if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) {
+        rewriteIndex.set(true);
+      }
+      final File storageFile = IndexInfrastructure.getStorageFile(indexId);
+      final MapIndexStorage<K, V> indexStorage = new MapIndexStorage<K, V>(storageFile, myKeyDescriptor, myValueExternalizer, 1024);
+      index = new MapReduceIndex<K, V, ClassReader>(indexId, getIndexer(), indexStorage);
+      index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
+        @Override
+        public PersistentHashMap<Integer, Collection<K>> create() {
+          Exception failCause = null;
+          for (int attempts = 0; attempts < 2; attempts++) {
+            try {
+              return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
+            }
+            catch (IOException e) {
+              failCause = e;
+              FileUtil.delete(IndexInfrastructure.getInputIndexStorageFile(getIndexId()));
+              rewriteIndex.set(true);
+            }
+          }
+          throw new RuntimeException("couldn't create index", failCause);
+        }
+      });
+      final File versionFile = getVersionFile(indexId);
+      if (versionFile.exists()) {
+        if (versionDiffers(versionFile, getVersion())) {
+          rewriteVersion(versionFile, getVersion());
+          rewriteIndex.set(true);
+          try {
+            LOG.info("clearing index for updating index version");
+            index.clear();
+          }
+          catch (StorageException e) {
+            LOG.error("couldn't clear index for reinitializing");
+            throw new RuntimeException(e);
+          }
+        }
+      }
+      else if (versionFile.createNewFile()) {
+        rewriteVersion(versionFile, getVersion());
+        rewriteIndex.set(true);
+      }
+      else {
+        LOG.error(String.format("problems while access to index version file to index %s ", indexId));
+      }
+    }
+    catch (IOException e) {
+      LOG.error("couldn't initialize index");
+      throw new RuntimeException(e);
+    }
+    myIndex = index;
+    return rewriteIndex.get();
+  }
+
+  protected abstract ID<K, V> getIndexId();
+
+  protected abstract int getVersion();
+
+  protected abstract DataIndexer<K, V, ClassReader> getIndexer();
+
+  public final void projectClosed() {
+    if (myIndex != null) {
+      try {
+        myIndex.flush();
+      }
+      catch (StorageException ignored) {
+      }
+      myIndex.dispose();
+    }
+  }
+
+  public void update(final int id, final ClassReader classReader) {
+    Boolean result = myIndex.update(id, classReader).compute();
+    if (result == Boolean.FALSE) throw new RuntimeException();
+  }
+
+  public void clear() {
+    try {
+      myIndex.clear();
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  protected final ID<K, V> generateIndexId(final String indexName) {
+    return CompilerOutputIndexUtil.generateIndexId(indexName, myProject);
+  }
+
+  protected final ID<K, V> generateIndexId(final Class aClass) {
+    final String className = StringUtil.getShortName(aClass);
+    return generateIndexId(StringUtil.trimEnd(className, "Index"));
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
new file mode 100644
index 0000000..c096cc8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
@@ -0,0 +1,21 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.ID;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class CompilerOutputIndexUtil {
+  private CompilerOutputIndexUtil() {}
+
+  public static <K, V> ID<K, V> generateIndexId(final String indexName, final Project project) {
+    return ID.create(String.format("compilerOutputIndex.%s.%d", indexName, Math.abs(project.getBasePath().hashCode())));
+  }
+
+  public static boolean isSetterOrConstructorMethodName(final String methodName) {
+    return MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(methodName) || methodName.startsWith("set");
+
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
new file mode 100644
index 0000000..83da828
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
@@ -0,0 +1,360 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.compilerOutputIndex.api.fs.CompilerOutputFilesUtil;
+import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.registry.RegistryValue;
+import com.intellij.openapi.util.registry.RegistryValueListener;
+import com.intellij.util.Consumer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.IndexInfrastructure;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.PersistentEnumeratorDelegate;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.asm4.ClassReader;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CompilerOutputIndexer extends AbstractProjectComponent {
+  private final static Logger LOG = Logger.getInstance(CompilerOutputIndexer.class);
+
+  public final static String REGISTRY_KEY = "completion.enable.relevant.method.chain.suggestions";
+  public final static String TITLE = "Compiler output indexer in progress...";
+
+  private volatile CompilerOutputBaseIndex[] myIndexes;
+  private volatile Map<String, CompilerOutputBaseIndex> myIndexTypeQNameToIndex;
+  private volatile PersistentHashMap<String, Long> myFileTimestampsIndex;
+  private volatile PersistentEnumeratorDelegate<String> myFileEnumerator;
+  private volatile boolean myInitialized = false;
+
+  private final Lock myLock = new ReentrantLock();
+  private final AtomicBoolean myInProgress = new AtomicBoolean(false);
+  private AtomicBoolean myEnabled = new AtomicBoolean(false);
+
+  public static CompilerOutputIndexer getInstance(final Project project) {
+    return project.getComponent(CompilerOutputIndexer.class);
+  }
+
+  protected CompilerOutputIndexer(final Project project) {
+    super(project);
+  }
+
+  public boolean isEnabled() {
+    return myEnabled.get();
+  }
+
+  private ID<String, Long> getFileTimestampsIndexId() {
+    return CompilerOutputIndexUtil.generateIndexId("ProjectCompilerOutputClassFilesTimestamps", myProject);
+  }
+
+  @Override
+  public final void projectOpened() {
+    Registry.get(REGISTRY_KEY).addListener(new RegistryValueListener.Adapter() {
+      @Override
+      public void afterValueChanged(final RegistryValue value) {
+        myEnabled.set(value.asBoolean());
+        if (myEnabled.get()) {
+          doEnable();
+        }
+      }
+    }, myProject);
+
+    myEnabled = new AtomicBoolean(Registry.is(REGISTRY_KEY) || ApplicationManager.getApplication().isUnitTestMode());
+    if (myEnabled.get()) {
+      doEnable();
+    }
+  }
+
+  private void doEnable() {
+    if (!myInitialized) {
+      myIndexes = Extensions.getExtensions(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject);
+      myIndexTypeQNameToIndex = new HashMap<String, CompilerOutputBaseIndex>();
+      boolean needReindex = false;
+      for (final CompilerOutputBaseIndex index : myIndexes) {
+        if (index.init(myProject)) {
+          needReindex = true;
+        }
+        myIndexTypeQNameToIndex.put(index.getClass().getCanonicalName(), index);
+      }
+      initTimestampIndex(needReindex);
+      try {
+        myFileEnumerator = new PersistentEnumeratorDelegate<String>(
+          IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject)),
+          new EnumeratorStringDescriptor(), 2048);
+      }
+      catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+      CompilerManager.getInstance(myProject).addAfterTask(new CompileTask() {
+        @Override
+        public boolean execute(final CompileContext context) {
+          if (myEnabled.get() && myInProgress.compareAndSet(false, true)) {
+            myLock.lock();
+            try {
+              context.getProgressIndicator().setText("Compiler output indexing in progress");
+              final Consumer<File> fileConsumer = new Consumer<File>() {
+                @Override
+                public void consume(final File file) {
+                  try {
+                    doIndexing(file, context.getProgressIndicator());
+                  }
+                  catch (ProcessCanceledException e0) {
+                    throw e0;
+                  }
+                  catch (RuntimeException e) {
+                    LOG.error(e);
+                  }
+                }
+              };
+              for (final Module module : context.getCompileScope().getAffectedModules()) {
+                CompilerOutputFilesUtil.iterateModuleClassFiles(module, fileConsumer);
+              }
+            }
+            finally {
+              myLock.unlock();
+              myInProgress.set(false);
+            }
+          }
+          return true;
+        }
+      });
+      if (needReindex) {
+        reindexAllProjectInBackground();
+      }
+      myInitialized = true;
+    }
+  }
+
+  private void initTimestampIndex(final boolean needReindex) {
+    if (needReindex) {
+      FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+    }
+    for (int attempts = 0; attempts < 2; attempts++) {
+      try {
+        myFileTimestampsIndex = new PersistentHashMap<String, Long>(IndexInfrastructure.getStorageFile(getFileTimestampsIndexId()),
+                                                                    new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
+          @Override
+          public void save(final DataOutput out, final Long value) throws IOException {
+            out.writeLong(value);
+          }
+
+          @Override
+          public Long read(final DataInput in) throws IOException {
+            return in.readLong();
+          }
+        });
+      }
+      catch (IOException e) {
+        FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+      }
+      if (myFileTimestampsIndex != null) {
+        return;
+      }
+    }
+    throw new RuntimeException("Timestamps index not initialized");
+  }
+
+
+  public void reindex(final FileVisitorService visitorService, @NotNull final ProgressIndicator indicator) {
+    myLock.lock();
+    try {
+      indicator.setText(TITLE);
+      visitorService.visit(new Consumer<File>() {
+        @Override
+        public void consume(final File file) {
+          try {
+            doIndexing(file, indicator);
+          }
+          catch (ProcessCanceledException e0) {
+            throw e0;
+          }
+          catch (RuntimeException e) {
+            LOG.error(e);
+          }
+        }
+      });
+    }
+    finally {
+      myLock.unlock();
+    }
+  }
+
+  public void reindexAllProjectInBackground() {
+    if (myInProgress.compareAndSet(false, true)) {
+      ProgressManager.getInstance().run(new Task.Backgroundable(myProject, TITLE) {
+
+        @Override
+        public void onCancel() {
+          myIndexTypeQNameToIndex.clear();
+          myInProgress.set(false);
+        }
+
+        @Override
+        public void onSuccess() {
+          myInProgress.set(false);
+        }
+
+        @Override
+        public void run(@NotNull final ProgressIndicator indicator) {
+          reindexAllProject(indicator);
+        }
+      });
+    }
+  }
+
+  public void reindexAllProject(@NotNull final ProgressIndicator indicator) {
+    reindex(new FileVisitorService.ProjectClassFiles(myProject), indicator);
+  }
+
+  @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+  private void doIndexing(@NotNull final File file, @NotNull final ProgressIndicator indicator) {
+    final String filePath;
+    try {
+      filePath = file.getCanonicalPath();
+    }
+    catch (IOException e) {
+      LOG.error(e);
+      return;
+    }
+    final Long timestamp = getTimestamp(filePath);
+    ProgressManager.checkCanceled();
+    final long currentTimeStamp = file.lastModified();
+    if (timestamp == null || timestamp != currentTimeStamp) {
+      putTimestamp(filePath, currentTimeStamp);
+      final ClassReader reader;
+      InputStream is = null;
+      try {
+        is = new FileInputStream(file);
+        reader = new ClassReader(is);
+      }
+      catch (IOException e) {
+        removeTimestamp(filePath);
+        return;
+      }
+      finally {
+        if (is != null) {
+          try {
+            is.close();
+          }
+          catch (IOException ignored) {
+          }
+        }
+      }
+      try {
+        indicator.setText2(filePath);
+        final int id = myFileEnumerator.enumerate(filePath);
+        for (final CompilerOutputBaseIndex index : myIndexes) {
+          index.update(id, reader);
+        }
+      }
+      catch (RuntimeException e) {
+        LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
+      }
+      catch (IOException e) {
+        LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
+      }
+    }
+  }
+
+  public void clear() {
+    try {
+      myFileTimestampsIndex.close();
+    }
+    catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    initTimestampIndex(true);
+    for (final CompilerOutputBaseIndex index : myIndexes) {
+      index.clear();
+    }
+  }
+
+  private void removeTimestamp(final String fileId) {
+    try {
+      myFileTimestampsIndex.remove(fileId);
+    }
+    catch (IOException e) {
+      LOG.error(e);
+    }
+  }
+
+  @Nullable
+  private Long getTimestamp(final String fileName) {
+    try {
+      return myFileTimestampsIndex.get(fileName);
+    }
+    catch (IOException e) {
+      LOG.error(e);
+      return 0L;
+    }
+  }
+
+  private void putTimestamp(final String fileName, final long timestamp) {
+    try {
+      myFileTimestampsIndex.put(fileName, timestamp);
+    }
+    catch (IOException e) {
+      LOG.error(e);
+    }
+  }
+
+
+  @Override
+  public void projectClosed() {
+    if (myInitialized) {
+      for (final CompilerOutputBaseIndex index : myIndexes) {
+        index.projectClosed();
+      }
+      try {
+        myFileTimestampsIndex.close();
+        myFileEnumerator.close();
+      }
+      catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  @TestOnly
+  public void removeIndexes() {
+    for (final CompilerOutputBaseIndex index : myIndexes) {
+      FileUtil.delete(IndexInfrastructure.getIndexRootDir(index.getIndexId()));
+    }
+    FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends CompilerOutputBaseIndex> T getIndex(final Class<T> tClass) {
+    final CompilerOutputBaseIndex index = myIndexTypeQNameToIndex.get(tClass.getCanonicalName());
+    if (index == null) {
+      throw new RuntimeException(String.format("index class with name %s not found", tClass.getName()));
+    }
+    return (T)index;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java
new file mode 100644
index 0000000..f0a7c27
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java
@@ -0,0 +1,116 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.MethodVisitor;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ClassFileData {
+  private final List<MethodData> myMethodDatas;
+
+  public ClassFileData(final ClassReader classReader) {
+    this(classReader, true);
+  }
+
+  public ClassFileData(final ClassReader classReader, final boolean checkForPrimitiveReturn) {
+    myMethodDatas = new ArrayList<MethodData>();
+    classReader.accept(new ClassVisitor(Opcodes.ASM4) {
+      @Override
+      public MethodVisitor visitMethod(final int access,
+                                       final String name,
+                                       final String desc,
+                                       final String signature,
+                                       final String[] exceptions) {
+        final MethodDataAccumulator methodDataAccumulator = new MethodDataAccumulator(checkForPrimitiveReturn);
+        myMethodDatas.add(methodDataAccumulator.getMethodData());
+        return methodDataAccumulator;
+      }
+    }, Opcodes.ASM4);
+  }
+
+  public List<MethodData> getMethodDatas() {
+    return myMethodDatas;
+  }
+
+  public static class MethodData {
+    private final List<MethodInsnSignature> myMethodInsnSignatures = new ArrayList<MethodInsnSignature>();
+
+    private void addSign(final MethodInsnSignature signature) {
+      myMethodInsnSignatures.add(signature);
+    }
+
+    public List<MethodInsnSignature> getMethodInsnSignatures() {
+      return myMethodInsnSignatures;
+    }
+  }
+
+  private static class MethodDataAccumulator extends MethodVisitor {
+    private final MethodData myMethodData = new MethodData();
+    private final boolean myCheckForPrimitiveReturn;
+
+    public MethodDataAccumulator(final boolean checkForPrimitiveReturn) {
+      super(Opcodes.ASM4);
+      myCheckForPrimitiveReturn = checkForPrimitiveReturn;
+    }
+
+    private MethodData getMethodData() {
+      return myMethodData;
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+      if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name)) {
+        return;
+      }
+      final String ownerClassName = AsmUtil.getQualifiedClassName(owner);
+      if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(ownerClassName)) {
+        return;
+      }
+      if (myCheckForPrimitiveReturn) {
+        final String returnType = AsmUtil.getReturnType(desc);
+        if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(returnType)) {
+          return;
+        }
+      }
+      myMethodData.addSign(new MethodInsnSignature(opcode, owner, name, desc));
+    }
+  }
+
+  public static class MethodInsnSignature {
+    private final int myOpcode;
+    private final String myOwner;
+    private final String myName;
+    private final String myDesc;
+
+    private MethodInsnSignature(final int opcode, final String owner, final String name, final String desc) {
+      myOpcode = opcode;
+      myOwner = owner;
+      myName = name;
+      myDesc = desc;
+    }
+
+    public int getOpcode() {
+      return myOpcode;
+    }
+
+    public String getOwner() {
+      return myOwner;
+    }
+
+    public String getName() {
+      return myName;
+    }
+
+    public String getDesc() {
+      return myDesc;
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java
new file mode 100644
index 0000000..b1afc83
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java
@@ -0,0 +1,47 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.util.TreeSet;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public abstract class CompilerOutputBaseGramsIndex<K> extends CompilerOutputBaseIndex<K, Multiset<MethodIncompleteSignature>> {
+
+  protected CompilerOutputBaseGramsIndex(final KeyDescriptor<K> keyDescriptor) {
+    super(keyDescriptor, new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()));
+  }
+
+  public TreeSet<UsageIndexValue> getValues(final K key) {
+    try {
+      final ValueContainer<Multiset<MethodIncompleteSignature>> valueContainer = myIndex.getData(key);
+      final Multiset<MethodIncompleteSignature> rawValues = HashMultiset.create();
+      valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodIncompleteSignature>>() {
+        @Override
+        public boolean perform(final int id, final Multiset<MethodIncompleteSignature> values) {
+          for (final Multiset.Entry<MethodIncompleteSignature> entry : values.entrySet()) {
+            rawValues.add(entry.getElement(), entry.getCount());
+          }
+          return true;
+        }
+      });
+      return rawValuesToValues(rawValues);
+    } catch (StorageException e) {
+      throw new RuntimeException();
+    }
+  }
+
+  private static TreeSet<UsageIndexValue> rawValuesToValues(final Multiset<MethodIncompleteSignature> rawValues) {
+    final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
+    for (final Multiset.Entry<MethodIncompleteSignature> entry : rawValues.entrySet()) {
+      values.add(new UsageIndexValue(entry.getElement(), entry.getCount()));
+    }
+    return values;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
new file mode 100644
index 0000000..fe36071
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.util.io.DataExternalizer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class GuavaHashMultiSetExternalizer<K> implements DataExternalizer<Multiset<K>> {
+  private final DataExternalizer<K> myKeyDataExternalizer;
+
+  public GuavaHashMultiSetExternalizer(final DataExternalizer<K> keyDataExternalizer) {
+    myKeyDataExternalizer = keyDataExternalizer;
+  }
+
+  @Override
+  public void save(final DataOutput out, final Multiset<K> multiset) throws IOException {
+    final Set<Multiset.Entry<K>> entries = multiset.entrySet();
+    out.writeInt(entries.size());
+    for (final Multiset.Entry<K> entry : entries) {
+      myKeyDataExternalizer.save(out, entry.getElement());
+      out.writeInt(entry.getCount());
+    }
+  }
+
+  @Override
+  public Multiset<K> read(final DataInput in) throws IOException {
+    final int size = in.readInt();
+    final Multiset<K> multiset = HashMultiset.create(size);
+    for (int i = 0; i < size; i++) {
+      multiset.add(myKeyDataExternalizer.read(in), in.readInt());
+    }
+    return multiset;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
new file mode 100644
index 0000000..ad85322
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
@@ -0,0 +1,183 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodIncompleteSignature {
+
+  public static final String CONSTRUCTOR_METHOD_NAME = "<init>";
+
+  @NotNull
+  private final String myOwner;
+  @NotNull
+  private final String myReturnType;
+  @NotNull
+  private final String myName;
+  private final boolean myStatic;
+
+  public MethodIncompleteSignature(@NotNull final String owner,
+                                   @NotNull final String returnType,
+                                   @NotNull final String name,
+                                   final boolean aStatic) {
+    myOwner = owner;
+    myReturnType = returnType;
+    myName = name;
+    myStatic = aStatic;
+  }
+
+  public static MethodIncompleteSignature constructor(@NotNull final String className) {
+    return new MethodIncompleteSignature(className, className, CONSTRUCTOR_METHOD_NAME, true);
+  }
+
+  @NotNull
+  public String getOwner() {
+    return myOwner;
+  }
+
+  @NotNull
+  public String getReturnType() {
+    return myReturnType;
+  }
+
+  @NotNull
+  public String getName() {
+    return myName;
+  }
+
+  public boolean isStatic() {
+    return myStatic;
+  }
+
+  @NotNull
+  public PsiMethod[] resolveNotDeprecated(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
+    return notDeprecated(resolve(javaPsiFacade, scope));
+  }
+
+  @NotNull
+  public PsiMethod[] resolve(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
+    if (CONSTRUCTOR_METHOD_NAME.equals(getName())) {
+      return PsiMethod.EMPTY_ARRAY;
+    }
+    final PsiClass aClass = javaPsiFacade.findClass(getOwner(), scope);
+    if (aClass == null) {
+      return PsiMethod.EMPTY_ARRAY;
+    }
+    final PsiMethod[] methods = aClass.findMethodsByName(getName(), true);
+    final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
+    for (final PsiMethod method : methods) {
+      if (method.hasModifierProperty(PsiModifier.STATIC) == isStatic()) {
+        final PsiType returnType = method.getReturnType();
+        if (returnType != null && returnType.equalsToText(getReturnType())) {
+          filtered.add(method);
+        }
+      }
+    }
+    return filtered.toArray(new PsiMethod[filtered.size()]);
+  }
+
+  public static KeyDescriptor<MethodIncompleteSignature> createKeyDescriptor() {
+    final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
+    return new KeyDescriptor<MethodIncompleteSignature>() {
+      @Override
+      public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
+        stringDescriptor.save(out, value.getOwner());
+        stringDescriptor.save(out, value.getReturnType());
+        stringDescriptor.save(out, value.getName());
+        out.writeBoolean(value.isStatic());
+      }
+
+      @Override
+      public MethodIncompleteSignature read(final DataInput in) throws IOException {
+        return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
+                                             in.readBoolean());
+      }
+
+      @Override
+      public int getHashCode(final MethodIncompleteSignature value) {
+        return value.hashCode();
+      }
+
+      @Override
+      public boolean isEqual(final MethodIncompleteSignature val1, final MethodIncompleteSignature val2) {
+        return val1.equals(val2);
+      }
+    };
+  }
+
+  @NotNull
+  private static PsiMethod[] notDeprecated(@NotNull final PsiMethod[] methods) {
+    final List<PsiMethod> filtered = ContainerUtil.filter(methods, NOT_DEPRECATED_CONDITION);
+    return filtered.toArray(new PsiMethod[filtered.size()]);
+  }
+
+  private final static Condition<PsiMethod> NOT_DEPRECATED_CONDITION = new Condition<PsiMethod>() {
+    @Override
+    public boolean value(final PsiMethod method) {
+      return !method.isDeprecated();
+    }
+  };
+
+  public final static Comparator<MethodIncompleteSignature> COMPARATOR = new Comparator<MethodIncompleteSignature>() {
+    @Override
+    public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) {
+      int sub = o1.getOwner().compareTo(o2.getOwner());
+      if (sub != 0) {
+        return sub;
+      }
+      sub = o1.getName().compareTo(o2.getName());
+      if (sub != 0) {
+        return sub;
+      }
+      sub = o1.getReturnType().compareTo(o2.getReturnType());
+      if (sub != 0) {
+        return sub;
+      }
+      if (o1.isStatic() && !o2.isStatic()) {
+        return 1;
+      }
+      if (o2.isStatic() && !o1.isStatic()) {
+        return -1;
+      }
+      return 0;
+    }
+  };
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final MethodIncompleteSignature that = (MethodIncompleteSignature)o;
+
+    if (myStatic != that.myStatic) return false;
+    if (!myName.equals(that.myName)) return false;
+    if (!myOwner.equals(that.myOwner)) return false;
+    if (!myReturnType.equals(that.myReturnType)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myOwner.hashCode();
+    result = 31 * result + myReturnType.hashCode();
+    result = 31 * result + myName.hashCode();
+    result = 31 * result + (myStatic ? 1 : 0);
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
new file mode 100644
index 0000000..a11e731
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
@@ -0,0 +1,44 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodIncompleteSignatureChain {
+  private final List<MethodIncompleteSignature> myMethodIncompleteSignatures;
+
+  public MethodIncompleteSignatureChain(final List<MethodIncompleteSignature> methodIncompleteSignatures) {
+    myMethodIncompleteSignatures = methodIncompleteSignatures;
+  }
+
+  public List<MethodIncompleteSignature> list() {
+    return myMethodIncompleteSignatures;
+  }
+
+  public boolean isEmpty() {
+    return myMethodIncompleteSignatures.isEmpty();
+  }
+
+  @Nullable
+  public MethodIncompleteSignature getFirstInvocation() {
+    final int size = myMethodIncompleteSignatures.size();
+    return size == 0 ? null : myMethodIncompleteSignatures.get(0);
+  }
+
+  @Nullable
+  public MethodIncompleteSignature getLastInvocation() {
+    final int size = myMethodIncompleteSignatures.size();
+    return size == 0 ? null : myMethodIncompleteSignatures.get(size -1);
+  }
+
+  public int size() {
+    return myMethodIncompleteSignatures.size();
+  }
+
+  public MethodIncompleteSignature get(final int index) {
+    return myMethodIncompleteSignatures.get(index);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
new file mode 100644
index 0000000..e07c038
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
@@ -0,0 +1,91 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsUsageIndex extends CompilerOutputBaseGramsIndex<String> {
+
+  public static MethodsUsageIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(MethodsUsageIndex.class);
+  }
+
+  public MethodsUsageIndex() {
+    super(new EnumeratorStringDescriptor());
+  }
+
+  @Override
+  protected DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassReader> getIndexer() {
+    return new DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<String, Multiset<MethodIncompleteSignature>> map(final ClassReader inputData) {
+        final Map<String, Multiset<MethodIncompleteSignature>> map = new HashMap<String, Multiset<MethodIncompleteSignature>>();
+        for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
+          for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
+            final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
+            final String returnType = AsmUtil.getReturnType(ms.getDesc());
+            if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(ms.getName())) {
+              addToIndex(map, ownerClassName, MethodIncompleteSignature.constructor(ownerClassName));
+            }
+            else {
+              final boolean isStatic = ms.getOpcode() == Opcodes.INVOKESTATIC;
+              if (!ownerClassName.equals(returnType) || isStatic) {
+                addToIndex(map, returnType, new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), isStatic));
+              }
+            }
+          }
+        }
+        return map;
+      }
+
+
+    };
+  }
+
+  public void clear() {
+    try {
+      myIndex.clear();
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected ID<String, Multiset<MethodIncompleteSignature>> getIndexId() {
+    return generateIndexId(MethodsUsageIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  private static void addToIndex(final Map<String, Multiset<MethodIncompleteSignature>> map,
+                                 final String key,
+                                 final MethodIncompleteSignature mi) {
+    Multiset<MethodIncompleteSignature> occurrences = map.get(key);
+    if (occurrences == null) {
+      occurrences = HashMultiset.create();
+      map.put(key, occurrences);
+    }
+    occurrences.add(mi);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
new file mode 100644
index 0000000..f99a0de
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
@@ -0,0 +1,69 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class UsageIndexValue implements Comparable<UsageIndexValue> {
+  private final int myOccurrences;
+  private final MethodIncompleteSignature myMethodIncompleteSignature;
+
+  public UsageIndexValue(final MethodIncompleteSignature signature, final int occurrences) {
+    myOccurrences = occurrences;
+    myMethodIncompleteSignature = signature;
+  }
+
+  public int getOccurrences() {
+    return myOccurrences;
+  }
+
+  public MethodIncompleteSignature getMethodIncompleteSignature() {
+    return myMethodIncompleteSignature;
+  }
+
+  public static DataExternalizer<UsageIndexValue> createDataExternalizer() {
+    final DataExternalizer<MethodIncompleteSignature> methodInvocationDataExternalizer = MethodIncompleteSignature.createKeyDescriptor();
+    return new DataExternalizer<UsageIndexValue>() {
+      @Override
+      public void save(final DataOutput out, final UsageIndexValue value) throws IOException {
+        methodInvocationDataExternalizer.save(out, value.myMethodIncompleteSignature);
+        out.writeInt(value.myOccurrences);
+      }
+
+      @Override
+      public UsageIndexValue read(final DataInput in) throws IOException {
+        return new UsageIndexValue(methodInvocationDataExternalizer.read(in), in.readInt());
+      }
+    };
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final UsageIndexValue that = (UsageIndexValue)o;
+
+    return myOccurrences == that.myOccurrences && myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myOccurrences;
+    result = 31 * result + myMethodIncompleteSignature.hashCode();
+    return result;
+  }
+
+  @Override
+  public int compareTo(@NotNull final UsageIndexValue that) {
+    final int sub = -myOccurrences + that.myOccurrences;
+    if (sub != 0) return sub;
+    return MethodIncompleteSignature.COMPARATOR.compare(myMethodIncompleteSignature, that.myMethodIncompleteSignature);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java
new file mode 100644
index 0000000..f5f4ff8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java
@@ -0,0 +1,22 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class Bigram<E> extends Pair<E, E> {
+  public Bigram(@NotNull final E first, @NotNull final E second) {
+    super(first, second);
+  }
+
+  public Bigram<E> swap() {
+    return new Bigram<E>(second, first);
+  }
+
+  @Override
+  public String toString() {
+    return String.format("%s - %s", first, second);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java
new file mode 100644
index 0000000..1f4d7e2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java
@@ -0,0 +1,86 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.ClassFileData;
+import com.intellij.compilerOutputIndex.impl.CompilerOutputBaseGramsIndex;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.SmartList;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class BigramMethodsUsageIndex extends CompilerOutputBaseGramsIndex<MethodIncompleteSignature> {
+  public static BigramMethodsUsageIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(BigramMethodsUsageIndex.class);
+  }
+
+  public BigramMethodsUsageIndex() {
+    super(MethodIncompleteSignature.createKeyDescriptor());
+  }
+
+  @Override
+  protected ID<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> getIndexId() {
+    return generateIndexId(BigramMethodsUsageIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  @Override
+  protected DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>, ClassReader> getIndexer() {
+    //
+    // not fair way, but works fast
+    //
+    return new DataIndexer<MethodIncompleteSignature,Multiset<MethodIncompleteSignature>,ClassReader>() {
+      @NotNull
+      @Override
+      public Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map(final ClassReader inputData) {
+        final Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map =
+          new HashMap<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>>();
+        for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
+          final SimpleBigramsExtractor extractor = new SimpleBigramsExtractor(new SimpleBigramsExtractor.BigramMethodIncompleteSignatureProcessor() {
+            @Override
+            public void process(final Bigram<MethodIncompleteSignature> bigram) {
+              final MethodIncompleteSignature secondGram = bigram.getSecond();
+              Multiset<MethodIncompleteSignature> occurrences = map.get(secondGram);
+              if (occurrences == null) {
+                occurrences = HashMultiset.create();
+                map.put(secondGram, occurrences);
+              }
+              occurrences.add(bigram.getFirst());
+            }
+          });
+          for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
+            final List<MethodIncompleteSignature> methodInvocations = new SmartList<MethodIncompleteSignature>();
+            final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
+            final String returnType = AsmUtil.getReturnType(ms.getDesc());
+
+            if (ms.getName().equals(MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME)) {
+              methodInvocations.add(MethodIncompleteSignature.constructor(ownerClassName));
+            }
+            else {
+              methodInvocations.add(new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), ms.getOpcode() == Opcodes.INVOKESTATIC));
+            }
+            extractor.addChain(new MethodIncompleteSignatureChain(methodInvocations));
+          }
+        }
+        return map;
+      }
+    };
+  }
+
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java
new file mode 100644
index 0000000..d231a07
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java
@@ -0,0 +1,55 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+* @author Dmitry Batkovich
+*/
+class SimpleBigramsExtractor {
+  private final Map<String, MethodIncompleteSignature> myHolder = new HashMap<String, MethodIncompleteSignature>();
+  private final BigramMethodIncompleteSignatureProcessor myProcessor;
+
+  public SimpleBigramsExtractor(final BigramMethodIncompleteSignatureProcessor processor) {
+    myProcessor = processor;
+  }
+
+  public void addChain(final MethodIncompleteSignatureChain chain) {
+    if (chain.isEmpty()) {
+      return;
+    }
+    final MethodIncompleteSignature firstInvocation = chain.getFirstInvocation();
+    assert firstInvocation != null;
+    final MethodIncompleteSignature head = firstInvocation.isStatic() ? null : myHolder.get(firstInvocation.getOwner());
+    for (final Bigram<MethodIncompleteSignature> bigram : toBigrams(head, chain)) {
+      myProcessor.process(bigram);
+    }
+    final MethodIncompleteSignature lastInvocation = chain.getLastInvocation();
+    assert lastInvocation != null;
+    myHolder.put(lastInvocation.getReturnType(), lastInvocation);
+  }
+
+  private static Collection<Bigram<MethodIncompleteSignature>> toBigrams(final @Nullable MethodIncompleteSignature head,
+                                                                         final @NotNull MethodIncompleteSignatureChain chain) {
+    MethodIncompleteSignature currentLast = null;
+    if (head != null) {
+      currentLast = head;
+    }
+    final List<Bigram<MethodIncompleteSignature>> bigrams = new ArrayList<Bigram<MethodIncompleteSignature>>(chain.size());
+    for (final MethodIncompleteSignature current : chain.list()) {
+      if (currentLast != null) {
+        bigrams.add(new Bigram<MethodIncompleteSignature>(currentLast, current));
+      }
+      currentLast = current;
+    }
+    return bigrams;
+  }
+
+  public interface BigramMethodIncompleteSignatureProcessor {
+    void process(Bigram<MethodIncompleteSignature> bigram);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java
new file mode 100644
index 0000000..b2a1541
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java
@@ -0,0 +1,71 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class CallingLocation {
+  @NotNull
+  private final MethodIncompleteSignature myMethodIncompleteSignature;
+  @NotNull
+  private final VariableType myVariableType;
+
+  public CallingLocation(@NotNull final MethodIncompleteSignature methodIncompleteSignature, @NotNull final VariableType variableType) {
+    myMethodIncompleteSignature = methodIncompleteSignature;
+    myVariableType = variableType;
+  }
+
+  @NotNull
+  public MethodIncompleteSignature getMethodIncompleteSignature() {
+    return myMethodIncompleteSignature;
+  }
+
+  @NotNull
+  public VariableType getVariableType() {
+    return myVariableType;
+  }
+
+  public static DataExternalizer<CallingLocation> createDataExternalizer() {
+    final KeyDescriptor<MethodIncompleteSignature> methodIncompleteSignatureKeyDescriptor = MethodIncompleteSignature.createKeyDescriptor();
+    return new DataExternalizer<CallingLocation>() {
+      @Override
+      public void save(final DataOutput out, final CallingLocation value) throws IOException {
+        methodIncompleteSignatureKeyDescriptor.save(out, value.getMethodIncompleteSignature());
+        VariableType.KEY_DESCRIPTOR.save(out, value.getVariableType());
+      }
+
+      @Override
+      public CallingLocation read(final DataInput in) throws IOException {
+        return new CallingLocation(methodIncompleteSignatureKeyDescriptor.read(in), VariableType.KEY_DESCRIPTOR.read(in));
+      }
+    };
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final CallingLocation that = (CallingLocation)o;
+
+    if (!myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature)) return false;
+    if (myVariableType != that.myVariableType) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myMethodIncompleteSignature.hashCode();
+    result = 31 * result + myVariableType.hashCode();
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java
new file mode 100644
index 0000000..f5cdadb
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java
@@ -0,0 +1,157 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+import org.jetbrains.asm4.commons.AnalyzerAdapter;
+import org.jetbrains.asm4.commons.JSRInlinerAdapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodCallingLocationExtractor {
+  private MethodCallingLocationExtractor() {
+  }
+
+  public static Map<MethodNameAndQualifier, List<CallingLocation>> extract(final ClassReader classReader) {
+    final MyClassVisitor classVisitor = new MyClassVisitor();
+    classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
+    return classVisitor.getExtractedMethodsCallings();
+  }
+
+  private static class MyClassVisitor extends ClassVisitor {
+    public MyClassVisitor() {
+      super(Opcodes.ASM4);
+    }
+
+    private final Map<MethodNameAndQualifier, List<CallingLocation>> myExtractedMethodsCallings =
+      new HashMap<MethodNameAndQualifier, List<CallingLocation>>();
+
+    private String myClassName;
+    private String myRawClassName;
+
+    private Map<MethodNameAndQualifier, List<CallingLocation>> getExtractedMethodsCallings() {
+      return myExtractedMethodsCallings;
+    }
+
+    @Override
+    public void visit(final int version,
+                      final int access,
+                      final String className,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+      myRawClassName = className;
+      myClassName = AsmUtil.getQualifiedClassName(className);
+    }
+
+    @Nullable
+    @Override
+    public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+
+      if (name.charAt(0) == '<') {
+        return null;
+      }
+      final boolean isStaticMethod = AsmUtil.isStaticMethodDeclaration(access);
+      if (isStaticMethod) {
+        return null;
+      }
+      @SuppressWarnings("UnnecessaryLocalVariable") final String methodName = name;
+      final String[] methodParams = AsmUtil.getParamsTypes(desc);
+      final MethodIncompleteSignature currentMethodSignature =
+        new MethodIncompleteSignature(myClassName, AsmUtil.getReturnType(desc), methodName, isStaticMethod);
+      return new JSRInlinerAdapter(new AnalyzerAdapter(Opcodes.ASM4, myRawClassName, access, name, desc, null) {
+        private final Map<Integer, Variable> myFieldsAndParamsPositionInStack = new HashMap<Integer, Variable>();
+
+        @Override
+        public void visitInsn(final int opcode) {
+          super.visitInsn(opcode);
+        }
+
+        @Override
+        public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+          boolean onThis = false;
+          if (stack != null && opcode == Opcodes.GETFIELD && !ChainCompletionStringUtil.isPrimitiveOrArray(AsmUtil.getReturnType(desc))) {
+            final Object objectRef = stack.get(stack.size() - 1);
+            if (objectRef instanceof String && objectRef.equals(myRawClassName)) {
+              onThis = true;
+            }
+          }
+          super.visitFieldInsn(opcode, owner, name, desc);
+          if (onThis) {
+            final int index = stack.size() - 1;
+            final Object marker = stack.get(index);
+            myFieldsAndParamsPositionInStack.put(index, new Variable(marker, VariableType.FIELD));
+          }
+        }
+
+        @Override
+        public void visitVarInsn(final int opcode, final int varIndex) {
+          super.visitVarInsn(opcode, varIndex);
+          if (stack != null && opcode == Opcodes.ALOAD &&
+              varIndex > 0 &&
+              varIndex <= methodParams.length &&
+              !ChainCompletionStringUtil.isPrimitiveOrArray(methodParams[varIndex - 1])) {
+            final int stackPos = stack.size() - 1;
+            myFieldsAndParamsPositionInStack.put(stackPos, new Variable(stack.get(stackPos), VariableType.METHOD_PARAMETER));
+          }
+        }
+
+        @Override
+        public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+          if (stack != null && opcode != Opcodes.INVOKESTATIC && !methodName.startsWith("<")) {
+            final int index = stack.size() - 1 - AsmUtil.getParamsTypes(desc).length;
+            final Object stackValue = stack.get(index);
+            final Variable variable = myFieldsAndParamsPositionInStack.get(index);
+            if (variable != null && variable.getMarker() == stackValue /*equality by reference is not mistake*/) {
+              final CallingLocation callingLocation = new CallingLocation(currentMethodSignature, variable.getVariableType());
+              final MethodNameAndQualifier invokedMethod = new MethodNameAndQualifier(name, AsmUtil.getQualifiedClassName(owner));
+              List<CallingLocation> callingLocations = myExtractedMethodsCallings.get(invokedMethod);
+              if (callingLocations == null) {
+                callingLocations = new ArrayList<CallingLocation>();
+                myExtractedMethodsCallings.put(invokedMethod, callingLocations);
+              }
+              callingLocations.add(callingLocation);
+            }
+          }
+          super.visitMethodInsn(opcode, owner, name, desc);
+        }
+      }, access, name, desc, signature, exceptions);
+    }
+  }
+
+  private static class Variable {
+    private final Object myMarker;
+    private final VariableType myVariableType;
+
+    private Variable(final Object marker, final VariableType variableType) {
+      myMarker = marker;
+      myVariableType = variableType;
+    }
+
+    private Object getMarker() {
+      return myMarker;
+    }
+
+    private VariableType getVariableType() {
+      return myVariableType;
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java
new file mode 100644
index 0000000..c55273a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java
@@ -0,0 +1,94 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.descriptor.ArrayListKeyDescriptor;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodCallingLocationIndex extends CompilerOutputBaseIndex<MethodNameAndQualifier, List<CallingLocation>> {
+
+  public static MethodCallingLocationIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(MethodCallingLocationIndex.class);
+  }
+
+  public MethodCallingLocationIndex() {
+    super(MethodNameAndQualifier.createKeyDescriptor(),
+          new ArrayListKeyDescriptor<CallingLocation>(CallingLocation.createDataExternalizer()));
+  }
+
+  @Override
+  protected ID<MethodNameAndQualifier, List<CallingLocation>> getIndexId() {
+    return generateIndexId(MethodCallingLocationIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  public List<CallingLocation> getAllLocations(final MethodNameAndQualifier methodNameAndQualifier) {
+    try {
+      final List<CallingLocation> result = new ArrayList<CallingLocation>();
+      myIndex.getData(methodNameAndQualifier).forEach(new ValueContainer.ContainerAction<List<CallingLocation>>() {
+        @Override
+        public boolean perform(final int id, final List<CallingLocation> values) {
+          result.addAll(values);
+          return true;
+        }
+      });
+      return result;
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Multiset<MethodIncompleteSignature> getLocationsAsParam(final MethodNameAndQualifier methodNameAndQualifier) {
+    final Multiset<MethodIncompleteSignature> result = HashMultiset.create();
+    try {
+      myIndex.getData(methodNameAndQualifier).forEach(new ValueContainer.ContainerAction<List<CallingLocation>>() {
+        @Override
+        public boolean perform(final int id, final List<CallingLocation> values) {
+          for (final CallingLocation value : values) {
+            if (value.getVariableType().equals(VariableType.METHOD_PARAMETER)) {
+              result.add(value.getMethodIncompleteSignature());
+            }
+          }
+          return true;
+        }
+      });
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+    return result;
+  }
+
+
+  @Override
+  protected DataIndexer<MethodNameAndQualifier, List<CallingLocation>, ClassReader> getIndexer() {
+    return new DataIndexer<MethodNameAndQualifier, List<CallingLocation>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<MethodNameAndQualifier, List<CallingLocation>> map(final ClassReader inputData) {
+        return MethodCallingLocationExtractor.extract(inputData);
+      }
+    };
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java
new file mode 100644
index 0000000..e69d4f3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java
@@ -0,0 +1,81 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodNameAndQualifier {
+  @NotNull
+  private final String myMethodName;
+  @NotNull
+  private final String myQualifierName;
+
+  public MethodNameAndQualifier(@NotNull final String methodName, @NotNull final String qualifierName) {
+    myMethodName = methodName;
+    myQualifierName = qualifierName;
+  }
+
+  @NotNull
+  public String getMethodName() {
+    return myMethodName;
+  }
+
+  @NotNull
+  public String getQualifierName() {
+    return myQualifierName;
+  }
+
+  public static KeyDescriptor<MethodNameAndQualifier> createKeyDescriptor() {
+    final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
+    return new KeyDescriptor<MethodNameAndQualifier>() {
+      @Override
+      public void save(final DataOutput out, final MethodNameAndQualifier value) throws IOException {
+        stringDataExternalizer.save(out, value.myMethodName);
+        stringDataExternalizer.save(out, value.myQualifierName);
+      }
+
+      @Override
+      public MethodNameAndQualifier read(final DataInput in) throws IOException {
+        return new MethodNameAndQualifier(stringDataExternalizer.read(in), stringDataExternalizer.read(in));
+      }
+
+      @Override
+      public int getHashCode(final MethodNameAndQualifier value) {
+        return value.hashCode();
+      }
+
+      @Override
+      public boolean isEqual(final MethodNameAndQualifier val1, final MethodNameAndQualifier val2) {
+        return val1.equals(val2);
+      }
+    };
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final MethodNameAndQualifier that = (MethodNameAndQualifier)o;
+
+    if (!myMethodName.equals(that.myMethodName)) return false;
+    if (!myQualifierName.equals(that.myQualifierName)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myMethodName.hashCode();
+    result = 31 * result + myQualifierName.hashCode();
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java
new file mode 100644
index 0000000..6cf1ff2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java
@@ -0,0 +1,15 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.util.io.EnumDataDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public enum VariableType {
+  FIELD,
+  METHOD_PARAMETER,
+  OTHER;
+
+  public static final KeyDescriptor<VariableType> KEY_DESCRIPTOR = new EnumDataDescriptor<VariableType>(VariableType.class);
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java
new file mode 100644
index 0000000..9a136f5
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java
@@ -0,0 +1,96 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.compilerOutputIndex.api.descriptor.HashSetKeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.asm4.Type;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class QuickInheritanceIndex extends CompilerOutputBaseIndex<String, Set<String>> {
+
+  public static QuickInheritanceIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(QuickInheritanceIndex.class);
+  }
+
+  public QuickInheritanceIndex() {
+    super(new EnumeratorStringDescriptor(), new HashSetKeyDescriptor<String>(new EnumeratorStringDescriptor()));
+  }
+
+  @Override
+  protected ID<String, Set<String>> getIndexId() {
+    return generateIndexId(QuickInheritanceIndex.class);
+  }
+
+  protected Set<String> getSupers(final String classQName) {
+    try {
+      final ValueContainer<Set<String>> valueContainer = myIndex.getData(classQName);
+      final Ref<Set<String>> setRef = Ref.create();
+      valueContainer.forEach(new ValueContainer.ContainerAction<Set<String>>() {
+        @Override
+        public boolean perform(final int id, final Set<String> value) {
+          setRef.set(value);
+          return false;
+        }
+      });
+      final Set<String> supers = setRef.get();
+      if (supers == null) {
+        return Collections.emptySet();
+      }
+      return supers;
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  @Override
+  protected DataIndexer<String, Set<String>, ClassReader> getIndexer() {
+    return new DataIndexer<String, Set<String>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<String, Set<String>> map(final ClassReader inputData) {
+        final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+        inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+          @Override
+          public void visit(final int version,
+                            final int access,
+                            final String name,
+                            final String signature,
+                            final String superName,
+                            final String[] interfaces) {
+            final String className = Type.getObjectType(name).getClassName();
+            if (className != null) {
+              final HashSet<String> value = ContainerUtil.newHashSet(AsmUtil.getQualifiedClassNames(interfaces, superName));
+              value.remove(CommonClassNames.JAVA_LANG_OBJECT);
+              map.put(className, value);
+            }
+          }
+        }, Opcodes.ASM4);
+        return map;
+      }
+    };
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java
new file mode 100644
index 0000000..d857706
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java
@@ -0,0 +1,103 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.compilerOutputIndex.api.descriptor.HashSetKeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.MethodVisitor;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class QuickMethodsIndex extends CompilerOutputBaseIndex<String, Set<String>> {
+
+  public static QuickMethodsIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(QuickMethodsIndex.class);
+  }
+
+  public QuickMethodsIndex() {
+    super(new EnumeratorStringDescriptor(), new HashSetKeyDescriptor<String>(new EnumeratorStringDescriptor()));
+  }
+
+  @Override
+  protected ID<String, Set<String>> getIndexId() {
+    return generateIndexId(QuickMethodsIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  protected Set<String> getMethodsNames(final String classQName) {
+    final Ref<Set<String>> methodsRef = Ref.create();
+    try {
+      myIndex.getData(classQName).forEach(new ValueContainer.ContainerAction<Set<String>>() {
+        @Override
+        public boolean perform(final int id, final Set<String> value) {
+          methodsRef.set(value);
+          return true;
+        }
+      });
+      final Set<String> methods = methodsRef.get();
+      return methods == null ? Collections.<String>emptySet() : methods;
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected DataIndexer<String, Set<String>, ClassReader> getIndexer() {
+    return new DataIndexer<String, Set<String>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<String, Set<String>> map(final ClassReader inputData) {
+        final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+        inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+
+          private String myClassName;
+          private final HashSet<String> myMethodNames = new HashSet<String>();
+
+          @Override
+          public void visit(final int i, final int i2, final String name, final String s2, final String s3, final String[] strings) {
+            myClassName = AsmUtil.getQualifiedClassName(name);
+          }
+
+          @Override
+          public void visitEnd() {
+            map.put(myClassName, myMethodNames);
+          }
+
+          @Nullable
+          @Override
+          public MethodVisitor visitMethod(final int access,
+                                           final String name,
+                                           final String desc,
+                                           final String sign,
+                                           final String[] exceptions) {
+            if ((access & Opcodes.ACC_STATIC) == 0) {
+              myMethodNames.add(name);
+            }
+            return null;
+          }
+        }, Opcodes.ASM4);
+        return map;
+      }
+    };
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java
new file mode 100644
index 0000000..78583aa
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java
@@ -0,0 +1,23 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class QuickOverrideUtil {
+
+  private QuickOverrideUtil() {}
+
+  public static boolean isMethodOverriden(final String classQName, final String methodName,
+                                          final QuickInheritanceIndex quickInheritanceIndex,
+                                          final QuickMethodsIndex quickMethodsIndex) {
+    for (final String aSuper : quickInheritanceIndex.getSupers(classQName)) {
+      if (quickMethodsIndex.getMethodsNames(aSuper).contains(methodName)) {
+        return true;
+      }
+      if (isMethodOverriden(aSuper, methodName, quickInheritanceIndex, quickMethodsIndex)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java
new file mode 100644
index 0000000..a1ef812
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java
@@ -0,0 +1,71 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodShortSignature {
+  @NotNull
+  private final String myName;
+  @NotNull
+  private final String mySignature; //in raw asm type
+
+  public MethodShortSignature(final @NotNull String name, final @NotNull String signature) {
+    myName = name;
+    mySignature = signature;
+  }
+
+  @NotNull
+  public String getName() {
+    return myName;
+  }
+
+  @NotNull
+  public String getSignature() {
+    return mySignature;
+  }
+
+  public static DataExternalizer<MethodShortSignature> createDataExternalizer() {
+    final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
+    return new DataExternalizer<MethodShortSignature>() {
+
+      @Override
+      public void save(final DataOutput out, final MethodShortSignature value) throws IOException {
+        stringDescriptor.save(out, value.getName());
+        stringDescriptor.save(out, value.getSignature());
+      }
+
+      @Override
+      public MethodShortSignature read(final DataInput in) throws IOException {
+        return new MethodShortSignature(stringDescriptor.read(in), stringDescriptor.read(in));
+      }
+    };
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final MethodShortSignature that = (MethodShortSignature) o;
+
+    if (!myName.equals(that.myName)) return false;
+    if (!mySignature.equals(that.mySignature)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myName.hashCode();
+    result = 31 * result + mySignature.hashCode();
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java
new file mode 100644
index 0000000..a6381ec
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java
@@ -0,0 +1,53 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodShortSignatureWithWeight {
+  private final MethodShortSignature myMethodShortSignature;
+  private final int myWeight;
+
+  public MethodShortSignatureWithWeight(final MethodShortSignature methodShortSignature, final int weight) {
+    myMethodShortSignature = methodShortSignature;
+    myWeight = weight;
+  }
+
+  public MethodShortSignature getMethodShortSignature() {
+    return myMethodShortSignature;
+  }
+
+  public int getWeight() {
+    return myWeight;
+  }
+
+  public static Comparator<MethodShortSignatureWithWeight> COMPARATOR = new Comparator<MethodShortSignatureWithWeight>() {
+    @Override
+    public int compare(final MethodShortSignatureWithWeight o1, final MethodShortSignatureWithWeight o2) {
+      return o1.getWeight() - o2.getWeight();
+    }
+  }   ;
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final MethodShortSignatureWithWeight that = (MethodShortSignatureWithWeight) o;
+
+    if (myWeight != that.myWeight) return false;
+    if (!myMethodShortSignature.equals(that.myMethodShortSignature)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myMethodShortSignature.hashCode();
+    result = 31 * result + myWeight;
+    return result;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java
new file mode 100644
index 0000000..dff423b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java
@@ -0,0 +1,116 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.GuavaHashMultiSetExternalizer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ParamsInMethodOccurrencesIndex extends CompilerOutputBaseIndex<String, Multiset<MethodShortSignature>> {
+
+  public static ParamsInMethodOccurrencesIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(ParamsInMethodOccurrencesIndex.class);
+  }
+
+  public ParamsInMethodOccurrencesIndex() {
+    super(new EnumeratorStringDescriptor(), new GuavaHashMultiSetExternalizer<MethodShortSignature>(MethodShortSignature.createDataExternalizer()));
+  }
+
+  @Override
+  protected ID<String, Multiset<MethodShortSignature>> getIndexId() {
+    return generateIndexId(ParamsInMethodOccurrencesIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  public Pair<List<MethodShortSignatureWithWeight>, Integer> getParameterOccurrences(final String parameterTypeName) {
+    try {
+      final Multiset<MethodShortSignature> resultAsMultiset = HashMultiset.create();
+      final ValueContainer<Multiset<MethodShortSignature>> valueContainer = myIndex.getData(parameterTypeName);
+      valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodShortSignature>>() {
+        @Override
+        public boolean perform(final int id, final Multiset<MethodShortSignature> localMap) {
+          for (final Multiset.Entry<MethodShortSignature> e : localMap.entrySet()) {
+            resultAsMultiset.add(e.getElement(), e.getCount());
+          }
+          return true;
+        }
+      });
+
+      final List<MethodShortSignatureWithWeight> result = new ArrayList<MethodShortSignatureWithWeight>(resultAsMultiset.elementSet().size());
+      int sumWeight = 0;
+      for (final Multiset.Entry<MethodShortSignature> e : resultAsMultiset.entrySet()) {
+        sumWeight += e.getCount();
+        result.add(new MethodShortSignatureWithWeight(e.getElement(), e.getCount()));
+      }
+      Collections.sort(result, MethodShortSignatureWithWeight.COMPARATOR);
+
+      return Pair.create(result, sumWeight);
+    } catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected DataIndexer<String, Multiset<MethodShortSignature>, ClassReader> getIndexer() {
+    return new DataIndexer<String, Multiset<MethodShortSignature>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<String, Multiset<MethodShortSignature>> map(final ClassReader inputData) {
+        final Map<String, Multiset<MethodShortSignature>> result = new HashMap<String, Multiset<MethodShortSignature>>();
+        inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+          @Nullable
+          @Override
+          public MethodVisitor visitMethod(final int i, final String name, final String desc, final String signature, final String[] exception) {
+            if (CompilerOutputIndexUtil.isSetterOrConstructorMethodName(name))  {
+              return null;
+            }
+            final String[] parameters = AsmUtil.getParamsTypes(desc);
+            final MethodShortSignature thisMethodShortSignature = new MethodShortSignature(name, desc);
+            for (final String parameter : parameters) {
+              Multiset<MethodShortSignature> methods = result.get(parameter);
+              if (methods == null) {
+                methods = HashMultiset.create();
+                result.put(parameter, methods);
+              }
+              methods.add(thisMethodShortSignature);
+            }
+            return new MethodVisitor(Opcodes.ASM4) {
+              @Override
+              public void visitLocalVariable(final String s, final String desc, final String signature, final Label label, final Label label2, final int i) {
+                final String varType = AsmUtil.getQualifiedClassName(desc);
+                Multiset<MethodShortSignature> methods = result.get(varType);
+                if (methods == null) {
+                  methods = HashMultiset.create();
+                  result.put(varType, methods);
+                }
+                methods.add(thisMethodShortSignature);
+              }
+            };
+          }
+        }, Opcodes.ASM4);
+        return result;
+      }
+    };
+  }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java
new file mode 100644
index 0000000..8a04b72
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java
@@ -0,0 +1,137 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.descriptor.ArrayListKeyDescriptor;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorIntegerDescriptor;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class TwinVariablesIndex extends CompilerOutputBaseIndex<String, List<Integer>> {
+  public static TwinVariablesIndex getInstance(final Project project) {
+    return CompilerOutputIndexer.getInstance(project).getIndex(TwinVariablesIndex.class);
+  }
+
+  public TwinVariablesIndex() {
+    super(new EnumeratorStringDescriptor(), new ArrayListKeyDescriptor<Integer>(EnumeratorIntegerDescriptor.INSTANCE));
+  }
+
+  @Override
+  protected ID<String, List<Integer>> getIndexId() {
+    return generateIndexId(TwinVariablesIndex.class);
+  }
+
+  @Override
+  protected int getVersion() {
+    return 0;
+  }
+
+  @NotNull
+  public List<Integer> getTwinInfo(final String typeQName) {
+    try {
+      final ValueContainer<List<Integer>> valueContainer = myIndex.getData(typeQName);
+      final List<Integer> result = new ArrayList<Integer>(valueContainer.size());
+      valueContainer.forEach(new ValueContainer.ContainerAction<List<Integer>>() {
+        @Override
+        public boolean perform(final int id, final List<Integer> value) {
+          result.addAll(value);
+          return true;
+        }
+      });
+      return result;
+    }
+    catch (StorageException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected DataIndexer<String, List<Integer>, ClassReader> getIndexer() {
+    return new DataIndexer<String, List<Integer>, ClassReader>() {
+      @NotNull
+      @Override
+      public Map<String, List<Integer>> map(final ClassReader inputData) {
+        final Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
+        inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+
+          @Nullable
+          @Override
+          public MethodVisitor visitMethod(final int access,
+                                           final String name,
+                                           final String desc,
+                                           final String signature,
+                                           final String[] exceptions) {
+            if (CompilerOutputIndexUtil.isSetterOrConstructorMethodName(name)) {
+              return null;
+            }
+            final Multiset<String> myTypesOccurrences = HashMultiset.create();
+            final String[] paramsTypes = AsmUtil.getParamsTypes(desc);
+            Collections.addAll(myTypesOccurrences, paramsTypes);
+            return new MethodVisitor(Opcodes.ASM4) {
+              private final Set<String> myLocalVarNames = new HashSet<String>();
+
+              @SuppressWarnings("unchecked")
+              @Override
+              public void visitEnd() {
+                for (final Multiset.Entry<String> e: myTypesOccurrences.entrySet()) {
+                  final String key = e.getElement();
+                  if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(key)) {
+                    List<Integer> values = map.get(key);
+                    if (values == null) {
+                      values = new ArrayList<Integer>();
+                      map.put(key, values);
+                    }
+                    values.add(e.getCount());
+                  }
+                }
+              }
+
+              private final Set<String> myUsedReadFieldsIndex = new HashSet<String>();
+
+              @Override
+              public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+                final String fieldTypeQName = AsmUtil.getReturnType(desc);
+                if ((opcode == Opcodes.GETSTATIC || opcode == Opcodes.GETFIELD)) {
+                  if (myUsedReadFieldsIndex.add(owner + name)) {
+                    myTypesOccurrences.add(fieldTypeQName);
+                  }
+                }
+              }
+
+              @Override
+              public void visitLocalVariable(final String name,
+                                             final String desc,
+                                             final String signature,
+                                             final Label start,
+                                             final Label end,
+                                             final int index) {
+                if (index > paramsTypes.length && myLocalVarNames.add(name)) {
+                  final String type = AsmUtil.getReturnType(desc);
+                  myTypesOccurrences.add(type);
+                }
+              }
+            };
+          }
+        }, Opcodes.ASM4);
+        return map;
+      }
+    };
+  }
+}
diff --git a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
index 9deea91..fb632cd 100644
--- a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
+++ b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
@@ -43,7 +43,7 @@
 
   private static final LanguageLevel  DEFAULT_LANGUAGE_LEVEL = LanguageLevel.JDK_1_6;
   private static final JavaSdkVersion DEFAULT_JDK_VERSION    = JavaSdkVersion.JDK_1_6;
-  private static final Pattern        JDK_VERSION_PATTERN    = Pattern.compile(".*1\\.(\\d+).*");
+  private static final Pattern        JDK_VERSION_PATTERN    = Pattern.compile(".*1.(\\d+).*");
 
   @NotNull private JavaSdkVersion myJdkVersion    = DEFAULT_JDK_VERSION;
   @NotNull private LanguageLevel  myLanguageLevel = DEFAULT_LANGUAGE_LEVEL;
@@ -128,6 +128,13 @@
 
   public void setLanguageLevel(@Nullable String languageLevel) {
     LanguageLevel level = LanguageLevel.parse(languageLevel);
+    if (level == null) {
+      Matcher matcher = JDK_VERSION_PATTERN.matcher(languageLevel);
+      if (matcher.matches()) {
+        String versionAsString = matcher.group(1);
+        level = LanguageLevel.parse("1." + versionAsString);
+      }
+    }
     if (level != null) {
       myLanguageLevel = level;
     }
diff --git a/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java b/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
index a6c302b..e80c05e 100644
--- a/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
+++ b/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
@@ -15,12 +15,14 @@
  */
 package com.intellij.ide.actions;
 
+import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 
 import javax.swing.*;
 
-public abstract class JavaCreateTemplateInPackageAction<T extends PsiElement> extends CreateTemplateInPackageAction<T> {
+public abstract class JavaCreateTemplateInPackageAction<T extends PsiElement> extends CreateTemplateInPackageAction<T> implements
+                                                                                                                       DumbAware {
 
   protected JavaCreateTemplateInPackageAction(String text, String description, Icon icon, boolean inSourceOnly) {
     super(text, description, icon, inSourceOnly);
diff --git a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
index de3446e..13ac82b 100644
--- a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
+++ b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
@@ -72,6 +72,9 @@
       if (containingClass == null) return null;
       String classFqn = containingClass.getQualifiedName();
       if (classFqn == null) return member.getName();  // refer to member of anonymous class by simple name
+      if (member instanceof PsiMethod && containingClass.findMethodsByName(member.getName(), false).length > 1) {
+        return classFqn + "#" + member.getName() + getParameterString((PsiMethod)member);
+      }
       return classFqn + "#" + member.getName();
     }
     return null;
@@ -89,17 +92,18 @@
     final int endIndex = fqn.indexOf('#');
     if (endIndex != -1) {
       String className = fqn.substring(0, endIndex);
-      if (className != null) {
-        aClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
-        if (aClass != null) {
-          String memberName = fqn.substring(endIndex + 1);
-          PsiField field = aClass.findFieldByName(memberName, false);
-          if (field != null) {
-            return field;
-          }
-          PsiMethod[] methods = aClass.findMethodsByName(memberName, false);
-          if (methods.length != 0) {
-            return methods[0];
+      int paramIndex = fqn.indexOf('(', endIndex);
+      aClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
+      if (aClass != null) {
+        String memberName = fqn.substring(endIndex + 1, paramIndex < 0 ? fqn.length() : paramIndex);
+        PsiField field = aClass.findFieldByName(memberName, false);
+        if (field != null) {
+          return field;
+        }
+        String paramString = paramIndex < 0 ? "" : fqn.substring(paramIndex);
+        for (PsiMethod overload : aClass.findMethodsByName(memberName, false)) {
+          if (StringUtil.isEmpty(paramString) || paramString.equals(getParameterString(overload))) {
+            return overload;
           }
         }
       }
@@ -161,14 +165,7 @@
       if (toInsert.length() != 0) toInsert += "#";
       toInsert += member.getName();
       if (member instanceof PsiMethod) {
-        toInsert += "(";
-        PsiParameter[] parameters = ((PsiMethod)member).getParameterList().getParameters();
-        for (int i = 0; i < parameters.length; i++) {
-          PsiParameter parameter = parameters[i];
-          if (i != 0) toInsert += ", ";
-          toInsert += parameter.getType().getCanonicalText();
-        }
-        toInsert += ")";
+        toInsert += getParameterString((PsiMethod)member);
       }
     }
     else if (elementAtCaret == null ||
@@ -256,6 +253,18 @@
     editor.getCaretModel().moveToOffset(caretOffset);
   }
 
+  private static String getParameterString(PsiMethod method) {
+    String toInsert = "(";
+    PsiParameter[] parameters = method.getParameterList().getParameters();
+    for (int i = 0; i < parameters.length; i++) {
+      PsiParameter parameter = parameters[i];
+      if (i != 0) toInsert += ", ";
+      toInsert += parameter.getType().getCanonicalText();
+    }
+    toInsert += ")";
+    return toInsert;
+  }
+
   private static boolean isReferencedTo(PsiReferenceExpression referenceExpression, PsiMember targetElement) {
     PsiElement resolved = referenceExpression.advancedResolve(true).getElement();
     if (!(resolved instanceof PsiMember)) return false;
diff --git a/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java b/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
index a025a1e..3f81ae3 100644
--- a/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
+++ b/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
@@ -119,7 +119,7 @@
   public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
     final TreePath path = event.getPath();
     if (path == null) return;
-    final DefaultMutableTreeNode node = (PackageDependenciesNode)path.getLastPathComponent();
+    final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
     if (node instanceof DirectoryNode) {
       Set<FileNode> fileNodes = null;
       for (int i = node.getChildCount() - 1; i >= 0; i--) {
diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java
new file mode 100644
index 0000000..8fdf05c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java
@@ -0,0 +1,301 @@
+package com.intellij.jarFinder;
+
+import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.download.DownloadableFileDescription;
+import com.intellij.util.download.DownloadableFileService;
+import org.apache.xerces.parsers.DOMParser;
+import org.jetbrains.annotations.NotNull;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public abstract class FindJarFix<T extends PsiElement> implements IntentionAction, Iconable {
+  private static final String CLASS_ROOT_URL = "http://findjar.com/class/";
+  private static final String CLASS_PAGE_EXT = ".html";
+  private static final String SERVICE_URL = "http://findjar.com";
+  private static final String LINK_TAG_NAME = "a";
+  private static final String LINK_ATTR_NAME = "href";
+
+  protected final T myRef;
+  protected final Module myModule;
+  protected JComponent myEditorComponent;
+
+  public FindJarFix(T ref) {
+    myRef = ref;
+    myModule = ModuleUtil.findModuleForPsiElement(ref);
+  }
+
+  @NotNull
+  @Override
+  public String getText() {
+    return "Find jar on web";
+  }
+
+  @NotNull
+  @Override
+  public String getFamilyName() {
+    return "Family name";
+  }
+
+  @Override
+  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+    return myRef.isValid()
+           && JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, file.getResolveScope()) != null
+           && myModule != null
+           && isFqnsOk(project, getPossibleFqns(myRef));
+  }
+
+  private static boolean isFqnsOk(Project project, List<String> fqns) {
+    if (fqns.isEmpty()) return false;
+    final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+    final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+    for (String fqn : fqns) {
+      if (facade.findClass(fqn, scope) != null) return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void invoke(@NotNull Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+    final List<String> fqns = getPossibleFqns(myRef);
+    myEditorComponent = editor.getComponent();
+    if (fqns.size() > 1) {
+      final JBList listOfFqns = new JBList(fqns);
+      JBPopupFactory.getInstance()
+        .createListPopupBuilder(listOfFqns)
+        .setTitle("Select Qualified Name")
+        .setItemChoosenCallback(new Runnable() {
+          @Override
+          public void run() {
+            final Object value = listOfFqns.getSelectedValue();
+            if (value instanceof String) {
+              findJarsForFqn(((String)value), editor);
+            }
+          }
+        }).createPopup().showInBestPositionFor(editor);
+    }
+    else if (fqns.size() == 1) {
+      findJarsForFqn(fqns.get(0), editor);
+    }
+  }
+
+  private void findJarsForFqn(final String fqn, final Editor editor) {
+    final Map<String, String> libs = new HashMap<String, String>();
+
+    final Runnable runnable = new Runnable() {
+      public void run() {
+        try {
+          final DOMParser parser = new DOMParser();
+          parser.parse(CLASS_ROOT_URL + fqn.replace('.', '/') + CLASS_PAGE_EXT);
+          final Document doc = parser.getDocument();
+          if (doc != null) {
+            final NodeList links = doc.getElementsByTagName(LINK_TAG_NAME);
+            for (int i = 0; i < links.getLength(); i++) {
+              final Node link = links.item(i);
+              final String libName = link.getTextContent();
+              final NamedNodeMap attributes = link.getAttributes();
+              if (attributes != null) {
+                final Node href = attributes.getNamedItem(LINK_ATTR_NAME);
+                if (href != null) {
+                  final String pathToJar = href.getTextContent();
+                  if (pathToJar != null && (pathToJar.startsWith("/jar/") || pathToJar.startsWith("/class/../"))) {
+                    libs.put(libName, SERVICE_URL + pathToJar);
+                  }
+                }
+              }
+            }
+          }
+        }
+        catch (IOException ignore) {//
+        }
+        catch (SAXException e) {//
+        }
+      }
+    };
+
+    final Task.Modal task = new Task.Modal(editor.getProject(), "Looking for libraries", true) {
+      @Override
+      public void run(@NotNull ProgressIndicator indicator) {
+        indicator.setIndeterminate(true);
+        runnable.run();
+      }
+
+      @Override
+      public void onSuccess() {
+        super.onSuccess();
+        if (libs.isEmpty()) {
+          HintManager.getInstance().showInformationHint(editor, "No libraries found for '" + fqn + "'");
+        } else {
+          final ArrayList<String> variants = new ArrayList<String>(libs.keySet());
+          Collections.sort(variants, new Comparator<String>() {
+            @Override
+            public int compare(String o1, String o2) {
+              return o1.compareTo(o2);
+            }
+          });
+          final JBList libNames = new JBList(variants);
+          libNames.installCellRenderer(new NotNullFunction<Object, JComponent>() {
+            @NotNull
+            @Override
+            public JComponent fun(Object o) {
+              return new JLabel(o.toString(), PlatformIcons.JAR_ICON, SwingConstants.LEFT);
+            }
+          });
+          if (libs.size() == 1) {
+            final String jarName = libs.keySet().iterator().next();
+            final String url = libs.get(jarName);
+            initiateDownload(url, jarName);
+          } else {
+            JBPopupFactory.getInstance()
+            .createListPopupBuilder(libNames)
+            .setTitle("Select a jar file")
+            .setItemChoosenCallback(new Runnable() {
+              @Override
+              public void run() {
+                final Object value = libNames.getSelectedValue();
+                if (value instanceof String) {
+                  final String jarName = (String)value;
+                  final String url = libs.get(jarName);
+                  if (url != null) {
+                    initiateDownload(url, jarName);
+                  }
+                }
+              }
+            })
+            .createPopup().showInBestPositionFor(editor);
+          }
+        }
+      }
+    };
+
+    ProgressManager.getInstance().run(task);
+  }
+
+  private void initiateDownload(String url, String jarName) {
+    DOMParser parser = new DOMParser();
+    try {
+      parser.parse(url);
+      final Document doc = parser.getDocument();
+      if (doc != null) {
+        final NodeList links = doc.getElementsByTagName(LINK_TAG_NAME);
+        if (links != null) {
+          for (int i = 0; i < links.getLength(); i++) {
+            final Node item = links.item(i);
+            if (item != null) {
+              final NamedNodeMap attributes = item.getAttributes();
+              if (attributes != null) {
+                final Node link = attributes.getNamedItem(LINK_ATTR_NAME);
+                if (link != null) {
+                  final String jarUrl = link.getTextContent();
+                  if (jarUrl != null && jarUrl.endsWith(jarName)) {
+                    downloadJar(jarUrl, jarName);
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    catch (SAXException e) {//
+    }
+    catch (IOException e) {//
+    }
+  }
+
+  private void downloadJar(String jarUrl, String jarName) {
+    final Project project = myModule.getProject();
+    final String dirPath = PropertiesComponent.getInstance(project).getValue("findjar.last.used.dir");
+    VirtualFile toSelect = dirPath == null ? null : LocalFileSystem.getInstance().findFileByIoFile(new File(dirPath));
+    final VirtualFile file = FileChooser.chooseFile(FileChooserDescriptorFactory.createSingleFolderDescriptor(), project, toSelect);
+    if (file != null) {
+      PropertiesComponent.getInstance(project).setValue("findjar.last.used.dir", file.getPath());
+      final DownloadableFileService downloader = DownloadableFileService.getInstance();
+      final DownloadableFileDescription description = downloader.createFileDescription(jarUrl, jarName);
+      final VirtualFile[] jars = downloader.createDownloader(Arrays.asList(description), project, myEditorComponent, jarName)
+        .toDirectory(file.getPath()).download();
+      if (jars != null && jars.length == 1) {
+        AccessToken token = WriteAction.start();
+        try {
+          OrderEntryFix.addJarToRoots(jars[0].getPresentableUrl(), myModule, myRef);
+        }
+        finally {
+          token.finish();
+        }
+      }
+    }
+  }
+
+  protected abstract Collection<String> getFqns(@NotNull T ref);
+  
+  protected List<String> getPossibleFqns(T ref) {
+    Collection<String> fqns = getFqns(ref);
+    
+    List<String> res = new ArrayList<String>(fqns.size());
+
+    for (String fqn : fqns) {
+      if (fqn.startsWith("java.") || fqn.startsWith("javax.swing.")) {
+        continue;
+      }
+      final int index = fqn.lastIndexOf('.');
+      if (index == -1) {
+        continue;
+      }
+      final String className = fqn.substring(index + 1);
+      if (className.length() == 0 || Character.isLowerCase(className.charAt(0))) {
+        continue;
+      }
+
+      res.add(fqn);
+    }
+
+    return res;
+  }
+
+  @Override
+  public boolean startInWriteAction() {
+    return false;
+  }
+
+  @Override
+  public Icon getIcon(int flags) {
+    return PlatformIcons.WEB_ICON;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
new file mode 100644
index 0000000..9cf66d3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
@@ -0,0 +1,22 @@
+package com.intellij.jarFinder;
+
+import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
+import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
+import com.intellij.psi.PsiJavaCodeReferenceElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class FindJarQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
+  @Override
+  public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
+    registrar.register(new JavaFindJarFix(ref));
+  }
+
+  @NotNull
+  @Override
+  public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
+    return PsiJavaCodeReferenceElement.class;
+  }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java b/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java
new file mode 100644
index 0000000..98e5a67
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java
@@ -0,0 +1,78 @@
+package com.intellij.jarFinder;
+
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PsiImportStaticStatementImpl;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class JavaFindJarFix extends FindJarFix<PsiQualifiedReferenceElement> {
+  public JavaFindJarFix(PsiQualifiedReferenceElement ref) {
+    super(ref);
+  }
+
+  @Override
+  protected Collection<String> getFqns(@NotNull PsiQualifiedReferenceElement ref) {
+    final PsiImportStatementBase importStatement = PsiTreeUtil.getParentOfType(ref.getElement(), PsiImportStatementBase.class);
+
+    //from static imports
+    if (importStatement != null) {
+      if (importStatement instanceof PsiImportStatement) {
+        final String importFQN = ((PsiImportStatement)importStatement).getQualifiedName();
+        if (importFQN != null && !importFQN.endsWith("*")) {
+          return Collections.singleton(importFQN);
+        }
+      }
+      else if (importStatement instanceof PsiImportStaticStatementImpl) {
+        final PsiJavaCodeReferenceElement classRef = ((PsiImportStaticStatementImpl)importStatement).getClassReference();
+        if (classRef != null) {
+          final String importFQN = classRef.getQualifiedName();
+          if (importFQN != null) {
+            return Collections.singleton(importFQN);
+          }
+        }
+      }
+      return Collections.emptyList();
+    }
+
+    final PsiElement qualifier = ref.getQualifier();
+    if (qualifier instanceof PsiQualifiedReference) {
+      //PsiQualifiedReference r = (PsiQualifiedReference)qualifier;
+      //TODO[kb] get fqn from expressions like org.unresolvedPackage.MyClass.staticMethodCall(...);
+      return Collections.emptyList();
+    }
+    final String className = ref.getReferenceName();
+    PsiFile file = ref.getContainingFile().getOriginalFile();
+    if (className != null && file instanceof PsiJavaFile) {
+      final PsiImportList importList = ((PsiJavaFile)file).getImportList();
+      if (importList != null) {
+        final PsiImportStatementBase statement = importList.findSingleImportStatement(className);
+        if (statement instanceof PsiImportStatement) {
+          final String importFQN = ((PsiImportStatement)statement).getQualifiedName();
+          if (importFQN != null) {
+            return Collections.singleton(importFQN);
+          }
+        }
+        else {
+          List<String> res = new ArrayList<String>();
+          // iterate through *
+          for (PsiImportStatementBase imp : importList.getAllImportStatements()) {
+            if (imp.isOnDemand() && imp instanceof PsiImportStatement) {
+              res.add(((PsiImportStatement)imp).getQualifiedName() + "." + className);
+            }
+          }
+
+          return res;
+        }
+      }
+    }
+    return Collections.emptyList();
+  }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java
new file mode 100644
index 0000000..deaed59
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java
@@ -0,0 +1,70 @@
+package com.intellij.jarFinder;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.xpath.XPath;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class MavenCentralSourceSearcher extends SourceSearcher {
+
+  private static final Logger LOG = Logger.getInstance(MavenCentralSourceSearcher.class);
+
+  @Nullable
+  @Override
+  protected String findSourceJar(@NotNull ProgressIndicator indicator,
+                                               @NotNull String artifactId,
+                                               @NotNull String version) throws SourceSearchException {
+    try {
+      indicator.setIndeterminate(true);
+      indicator.setText("Connecting to http://search.maven.org");
+
+      indicator.checkCanceled();
+
+      String url = "http://search.maven.org/solrsearch/select?rows=3&wt=xml&q=a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22";
+      Document document = readDocumentCancelable(indicator, url);
+
+      indicator.checkCanceled();
+
+      List<Element> artifactList = (List<Element>)XPath.newInstance("/response/result/doc/str[@name='g']").selectNodes(document);
+      if (artifactList.isEmpty()) {
+        return null;
+      }
+
+      Element element;
+
+      if (artifactList.size() == 1) {
+        element = artifactList.get(0);
+      }
+      else {
+        // TODO handle
+        return null;
+      }
+
+      String groupId = element.getValue();
+
+      String downloadUrl = "http://search.maven.org/remotecontent?filepath=" + groupId.replace('.', '/') + '/' + artifactId + '/' + version + '/' + artifactId + '-' + version + "-sources.jar";
+
+      return downloadUrl;
+    }
+    catch (JDOMException e) {
+      LOG.warn(e);
+      throw new SourceSearchException("Failed to parse response from server. See log for more details.");
+    }
+    catch (IOException e) {
+      indicator.checkCanceled(); // Cause of IOException may be canceling of operation.
+
+      LOG.warn(e);
+      throw new SourceSearchException("Connection problem. See log for more details.");
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java
new file mode 100644
index 0000000..2a942cc
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java
@@ -0,0 +1,87 @@
+package com.intellij.jarFinder;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.Pair;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.xpath.XPath;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class SonatypeSourceSearcher extends SourceSearcher {
+
+  private static final Logger LOG = Logger.getInstance(SonatypeSourceSearcher.class);
+
+  @Nullable
+  @Override
+  public String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version)
+    throws SourceSearchException {
+    try {
+      indicator.setIndeterminate(true);
+      indicator.setText("Connecting to https://oss.sonatype.org");
+
+      indicator.checkCanceled();
+
+      String url = "https://oss.sonatype.org/service/local/lucene/search?collapseresults=true&c=sources&a=" + artifactId + "&v=" + version;
+      Document document = readDocumentCancelable(indicator, url);
+
+      indicator.checkCanceled();
+
+      List<Element> artifactList = (List<Element>)XPath.newInstance("/searchNGResponse/data/artifact").selectNodes(document);
+      if (artifactList.isEmpty()) {
+        return null;
+      }
+
+      Element element;
+
+      if (artifactList.size() == 1) {
+        element = artifactList.get(0);
+      }
+      else {
+        // TODO handle
+        return null;
+      }
+
+      List<Element> artifactHintList =
+        (List<Element>)XPath.newInstance("artifactHits/artifactHit/artifactLinks/artifactLink/classifier[text()='sources']/../../..")
+          .selectNodes(element);
+      if (artifactHintList.isEmpty()) {
+        return null;
+      }
+
+      String groupId = element.getChildTextTrim("groupId");
+      String repositoryId = artifactHintList.get(0).getChildTextTrim("repositoryId");
+
+      String downloadUrl = "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=" +
+                           repositoryId +
+                           "&g=" +
+                           groupId +
+                           "&a=" +
+                           artifactId +
+                           "&v=" +
+                           version +
+                           "&e=jar&c=sources";
+
+      return downloadUrl;
+    }
+    catch (JDOMException e) {
+      LOG.warn(e);
+      throw new SourceSearchException("Failed to parse response from server. See log for more details.");
+    }
+    catch (IOException e) {
+      indicator.checkCanceled(); // Cause of IOException may be canceling of operation.
+
+      LOG.warn(e);
+      throw new SourceSearchException("Connection problem. See log for more details.");
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java
new file mode 100644
index 0000000..b1d635a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java
@@ -0,0 +1,77 @@
+package com.intellij.jarFinder;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.util.net.HttpConfigurable;
+import org.jdom.Document;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public abstract class SourceSearcher {
+
+  /**
+   * @param indicator
+   * @param artifactId
+   * @param version
+   * @return groupId of found artifact and url.
+   */
+  @Nullable
+  protected abstract String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) throws SourceSearchException;
+
+  protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws JDOMException, IOException {
+    final HttpURLConnection urlConnection = HttpConfigurable.getInstance().openHttpConnection(url);
+
+    Thread t = new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          //noinspection InfiniteLoopStatement
+          while (true) {
+            if (indicator.isCanceled()) {
+              urlConnection.disconnect();
+            }
+
+            //noinspection BusyWait
+            Thread.sleep(100);
+          }
+        }
+        catch (InterruptedException ignored) {
+
+        }
+      }
+    });
+
+    t.start();
+
+    try {
+      urlConnection.setRequestProperty("accept", "application/xml");
+
+      InputStream inputStream = urlConnection.getInputStream();
+      try {
+        return new SAXBuilder().build(inputStream);
+      }
+      finally {
+        inputStream.close();
+      }
+    }
+    finally {
+      t.interrupt();
+    }
+  }
+}
+
+class SourceSearchException extends Exception {
+
+  SourceSearchException(String message) {
+    super(message);
+  }
+
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
index 5b7c3ef..08ecb6a 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
@@ -21,8 +21,6 @@
 import com.intellij.execution.Executor;
 import com.intellij.execution.configurations.*;
 import com.intellij.execution.filters.RegexpFilter;
-import com.intellij.execution.filters.TextConsoleBuilder;
-import com.intellij.execution.filters.TextConsoleBuilderFactory;
 import com.intellij.execution.process.OSProcessHandler;
 import com.intellij.execution.process.ProcessAdapter;
 import com.intellij.execution.process.ProcessEvent;
@@ -138,10 +136,8 @@
       super(null);
       myGenerationOptions = generationOptions;
       myProject = project;
-      TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
-      builder.addFilter(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"));
-      builder.addFilter(new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$"));
-      setConsoleBuilder(builder);
+      addConsoleFilters(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"),
+                        new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$"));
     }
 
     protected GeneralCommandLine createCommandLine() throws ExecutionException {
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
index ecebc06..e34cafb 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
@@ -18,6 +18,7 @@
 import com.intellij.CommonBundle;
 import com.intellij.analysis.AnalysisScope;
 import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
 import com.intellij.execution.RunnerRegistry;
 import com.intellij.execution.executors.DefaultRunExecutor;
 import com.intellij.execution.runners.ExecutionEnvironment;
@@ -83,7 +84,8 @@
     try {
       final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration);
       assert runner != null;
-      runner.execute(DefaultRunExecutor.getRunExecutorInstance(), new ExecutionEnvironment(myConfiguration, myProject, null, null, null));
+      Executor executor = DefaultRunExecutor.getRunExecutorInstance();
+      runner.execute(new ExecutionEnvironment(myConfiguration ,executor, myProject, null));
     }
     catch (ExecutionException e) {
       ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java b/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java
deleted file mode 100644
index 4d3712d..0000000
--- a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.lang.java;
-
-import com.intellij.lang.LiteralEscaper;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiJavaToken;
-import com.intellij.psi.JavaTokenType;
-import com.intellij.openapi.util.text.StringUtil;
-
-/**
- * @author yole
- */
-public class JavaLiteralEscaper implements LiteralEscaper {
-  @Override
-  public String getEscapedText(final PsiElement context, final String originalText) {
-    if (context instanceof PsiJavaToken && ((PsiJavaToken)context).getTokenType() == JavaTokenType.STRING_LITERAL) {
-      return StringUtil.escapeStringCharacters(originalText);
-    }
-    return originalText;
-  }
-
-  @Override
-  public String escapeText(String originalText) {
-    return StringUtil.escapeStringCharacters(originalText);
-  }
-
-  @Override
-  public String unescapeText(String originalText) {
-    return StringUtil.unescapeStringCharacters(originalText);
-  }
-}
diff --git a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
index e8e6666..a86e3a6 100644
--- a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
+++ b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
@@ -28,6 +28,7 @@
 import com.intellij.psi.JavaPsiFacade;
 import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -41,7 +42,7 @@
 
   public static final String MODULE_NAME = ProjectBundle.message("module.type.java.name");
   public static final String JAVA_GROUP = "Java";
-  private static final String JAVA_MODULE = "JAVA_MODULE";
+  private static final String JAVA_MODULE = ModuleTypeId.JAVA_MODULE;
 
   public JavaModuleType() {
     this(JAVA_MODULE);
@@ -51,16 +52,19 @@
     super(id);
   }
 
+  @NotNull
   @Override
   public JavaModuleBuilder createModuleBuilder() {
     return new JavaModuleBuilder();
   }
 
+  @NotNull
   @Override
   public String getName() {
     return MODULE_NAME;
   }
 
+  @NotNull
   @Override
   public String getDescription() {
     return ProjectBundle.message("module.type.java.description");
@@ -76,9 +80,10 @@
     return getJavaModuleNodeIconClosed();
   }
 
+  @NotNull
   @Override
-  public ModuleWizardStep[] createWizardSteps(final WizardContext wizardContext, final JavaModuleBuilder moduleBuilder,
-                                              final ModulesProvider modulesProvider) {
+  public ModuleWizardStep[] createWizardSteps(@NotNull final WizardContext wizardContext, @NotNull final JavaModuleBuilder moduleBuilder,
+                                              @NotNull final ModulesProvider modulesProvider) {
     final ProjectWizardStepFactory wizardFactory = ProjectWizardStepFactory.getInstance();
     ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
     final ModuleWizardStep supportForFrameworksStep = wizardFactory.createSupportForFrameworksStep(wizardContext, moduleBuilder, modulesProvider);
@@ -91,7 +96,7 @@
 
   @Nullable
   @Override
-  public ModuleWizardStep modifySettingsStep(SettingsStep settingsStep, final ModuleBuilder moduleBuilder) {
+  public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep, @NotNull final ModuleBuilder moduleBuilder) {
     return ProjectWizardStepFactory.getInstance().createJavaSettingsStep(settingsStep, moduleBuilder, new Condition<SdkTypeId>() {
       @Override
       public boolean value(SdkTypeId sdkType) {
@@ -118,13 +123,13 @@
   }
 
   @Override
-  public boolean isValidSdk(final Module module, final Sdk projectSdk) {
+  public boolean isValidSdk(@NotNull final Module module, final Sdk projectSdk) {
     return isValidJavaSdk(module);
   }
 
-  public static boolean isValidJavaSdk(final Module module) {
+  public static boolean isValidJavaSdk(@NotNull Module module) {
     if (ModuleRootManager.getInstance(module).getSourceRoots().length == 0) return true;
-    return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, 
+    return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT,
                                                                     module.getModuleWithLibrariesScope()) != null;
   }
 }
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
index 016e9f7..76e9875 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
@@ -15,36 +15,16 @@
  */
 package com.intellij.openapi.projectRoots;
 
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Disposer;
 import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author anna
  * @since 3/28/12
  */
 public class JavaVersionServiceImpl extends JavaVersionService {
-  private JavaSdkVersion myTestVersion = JavaSdkVersion.JDK_1_7;
-
-  @TestOnly
-  public void setTestVersion(@Nullable JavaSdkVersion testVersion, Disposable parentDisposable) {
-    myTestVersion = testVersion;
-    Disposer.register(parentDisposable, new Disposable() {
-      @Override
-      public void dispose() {
-        myTestVersion = JavaSdkVersion.JDK_1_7;
-      }
-    });
-  }
-
   @Override
-  public boolean isAtLeast(PsiElement element, JavaSdkVersion version) {
-    if (ApplicationManager.getApplication().isUnitTestMode()) {
-      return myTestVersion != null && myTestVersion.isAtLeast(version);
-    }
+  public boolean isAtLeast(@NotNull PsiElement element, @NotNull JavaSdkVersion version) {
     return JavaSdkVersionUtil.isAtLeast(element, version);
   }
 }
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
index 248f5a7..ad59dda 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
@@ -314,7 +314,7 @@
 
   @Override
   @SuppressWarnings({"HardCodedStringLiteral"})
-  public void setupSdkPaths(Sdk sdk) {
+  public void setupSdkPaths(@NotNull Sdk sdk) {
     final File jdkHome = new File(sdk.getHomePath());
     List<VirtualFile> classes = findClasses(jdkHome, false);
     VirtualFile sources = findSources(jdkHome);
@@ -427,10 +427,6 @@
 
   @Override
   public JavaSdkVersion getVersion(@NotNull Sdk sdk) {
-    return getVersion1(sdk);
-  }
-
-  private static JavaSdkVersion getVersion1(Sdk sdk) {
     String version = sdk.getVersionString();
     if (version == null) return null;
     return JdkVersionUtil.getVersion(version);
diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java b/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
index 8a12fac..b177f9a 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
@@ -27,6 +27,7 @@
 import com.intellij.util.io.DataInputOutputUtil;
 import com.intellij.util.messages.MessageBus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -42,7 +43,7 @@
   }
 
   @Override
-  public void initExtra(Project project, MessageBus bus, Engine languageLevelUpdater) {
+  public void initExtra(@NotNull Project project, @NotNull MessageBus bus, @NotNull Engine languageLevelUpdater) {
     // nothing
   }
 
@@ -64,24 +65,24 @@
   }
 
   @Override
-  public LanguageLevel getImmediateValue(Project project, VirtualFile file) {
+  public LanguageLevel getImmediateValue(@NotNull Project project, @Nullable VirtualFile file) {
     return null;
   }
 
   @Override
-  public LanguageLevel getImmediateValue(Module module) {
+  public LanguageLevel getImmediateValue(@NotNull Module module) {
     return LanguageLevelUtil.getEffectiveLanguageLevel(module);
   }
 
   @Override
-  public boolean acceptsFile(VirtualFile file) {
+  public boolean acceptsFile(@NotNull VirtualFile file) {
     return false;
   }
 
   private static final FileAttribute PERSISTENCE = new FileAttribute("language_level_persistence", 2, true);
 
   @Override
-  public void persistAttribute(VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException {
+  public void persistAttribute(@NotNull VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException {
     final DataInputStream iStream = PERSISTENCE.readAttribute(fileOrDir);
     if (iStream != null) {
       try {
@@ -105,6 +106,6 @@
   }
 
   @Override
-  public void afterRootsChanged(Project project) {
+  public void afterRootsChanged(@NotNull Project project) {
   }
 }
diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
index 17d9376..af89062 100644
--- a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
+++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
@@ -178,7 +178,8 @@
   @Override
   public boolean processPackageDirectories(@NotNull PsiPackage psiPackage,
                                            @NotNull GlobalSearchScope scope,
-                                           @NotNull Processor<PsiDirectory> consumer) {
+                                           @NotNull Processor<PsiDirectory> consumer,
+                                           boolean includeLibrarySources) {
     final List<VirtualFile> classRoots = getClassRoots();
     if (classRoots.isEmpty()) {
       return true;
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
index d5b7e90..b65393f 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
@@ -18,9 +18,9 @@
 import com.intellij.formatting.*;
 import com.intellij.formatting.alignment.AlignmentStrategy;
 import com.intellij.lang.ASTNode;
+import com.intellij.psi.JavaDocTokenType;
 import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
 import com.intellij.psi.formatter.FormatterUtil;
-import com.intellij.psi.impl.source.tree.ElementType;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -37,7 +37,7 @@
 
     ASTNode child = myNode.getFirstChildNode();
     while (child != null) {
-      if (child.getElementType() == ElementType.DOC_COMMENT_START) {
+      if (child.getElementType() == JavaDocTokenType.DOC_COMMENT_START) {
         result.add(createJavaBlock(child, mySettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
       } else if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getText().trim().length() > 0){
         result.add(createJavaBlock(child, mySettings, Indent.getSpaceIndent(1), null, AlignmentStrategy.getNullStrategy()));
diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
index 1594b3b..0309800 100644
--- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
+++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
@@ -39,6 +39,7 @@
   AnchorElementInfo(@NotNull PsiElement anchor, @NotNull PsiFile containingFile) {
     super(containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), containingFile,
           containingFile.getLanguage());
+    assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor;
   }
   // will restore by stub index until file tree get loaded
   AnchorElementInfo(@NotNull PsiElement anchor,
@@ -50,18 +51,19 @@
     myStubElementType = stubElementType;
     IElementType contentElementType = ((PsiFileImpl)containingFile).getContentElementType();
     assert contentElementType instanceof IStubFileElementType : contentElementType;
+    assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor;
   }
 
   @Override
   @Nullable
   public PsiElement restoreElement() {
     if (stubId != -1) {
-      PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
+      PsiFile file = restoreFile();
       if (!(file instanceof PsiFileWithStubSupport)) return null;
       return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType, false);
     }
     if (!mySyncMarkerIsValid) return null;
-    PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
+    PsiFile file = restoreFile();
     if (file == null) return null;
     PsiElement anchor = file.findElementAt(getSyncStartOffset());
     if (anchor == null) return null;
diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
index 57f919f..a3ed29f 100644
--- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
+++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
@@ -15,7 +15,6 @@
  */
 package com.intellij.psi.impl.smartPointers;
 
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.PsiFileWithStubSupport;
 import com.intellij.psi.stubs.IStubElementType;
@@ -27,8 +26,6 @@
 import org.jetbrains.annotations.Nullable;
 
 public class AnchorElementInfoFactory implements SmartPointerElementInfoFactory {
-  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.AnchorElementInfoFactory");
-
   @Override
   @Nullable
   public SmartPointerElementInfo createElementInfo(@NotNull PsiElement element) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
index 5c80f43..841b8b5 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
@@ -16,9 +16,11 @@
 package com.intellij.psi.impl.source.codeStyle;
 
 import com.intellij.lang.ASTNode;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
 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.PsiField;
 import com.intellij.psi.PsiMethod;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -31,57 +33,65 @@
   @NotNull
   @Override
   public TextRange process(@NotNull final ASTNode element, @NotNull final TextRange range) {
-    final Project project = SourceTreeToPsiMap.treeElementToPsi(element).getProject();
+    PsiElement e = SourceTreeToPsiMap.treeElementToPsi(element);
+    assert e != null;
+    final Project project = e.getProject();
     if (!CodeStyleSettingsManager.getSettings(project).ENABLE_JAVADOC_FORMATTING ||
-        element.getPsi().getContainingFile().getLanguage() != StdLanguages.JAVA) {
+        element.getPsi().getContainingFile().getLanguage() != JavaLanguage.INSTANCE)
+    {
       return range;
     }
-
     return formatCommentsInner(project, element, range);
   }
 
-  private static TextRange formatCommentsInner(Project project, ASTNode element, final TextRange range) {
-    TextRange result = range;
+  /**
+   * Formats PsiDocComments of current ASTNode element and all his children PsiDocComments
+   */
+  @NotNull
+  private static TextRange formatCommentsInner(@NotNull Project project, @NotNull ASTNode element, @NotNull final TextRange markedRange) {
+    TextRange resultTextRange = markedRange;
+    final PsiElement elementPsi = element.getPsi();
+    boolean shouldFormat = markedRange.contains(element.getTextRange());
 
-
-    // check for RepositoryTreeElement is optimization
-    if (shouldProcess(element)) {
-      final TextRange elementRange = element.getTextRange();
-
-      if (range.contains(elementRange)) {
-        new CommentFormatter(project).process(element);
-        final TextRange newRange = element.getTextRange();
-        result = new TextRange(range.getStartOffset(), range.getEndOffset() + newRange.getLength() - elementRange.getLength());
+    if (shouldFormat) {
+      final ASTNode rangeAnchor;
+      // There are two possible cases:
+      //   1. Given element correspond to comment's owner (e.g. field or method);
+      //   2. Given element corresponds to comment itself;
+      // However, doc comment formatter replaces old comment with the new one, hence, old element becomes invalid. That's why we need
+      // to calculate text length delta not for the given comment element (it's invalid because removed from the AST tree) but for
+      // its parent.
+      if (elementPsi instanceof PsiDocComment) {
+        rangeAnchor = element.getTreeParent();
       }
-
-      // optimization, does not seek PsiDocComment inside fields / methods or out of range
-      if (element.getPsi() instanceof PsiField ||
-          element.getPsi() instanceof PsiMethod ||
-          element instanceof PsiDocComment ||
-          range.getEndOffset() < elementRange.getStartOffset()
-         ) {
-        return result;
+      else {
+        rangeAnchor = element;
       }
+      TextRange before = rangeAnchor.getTextRange();
+      new CommentFormatter(project).processComment(element);
+      int deltaRange = rangeAnchor.getTextRange().getLength() - before.getLength();
+      resultTextRange = new TextRange(markedRange.getStartOffset(), markedRange.getEndOffset() + deltaRange);
+    }
+
+    
+    // If element is Psi{Method, Field, DocComment} and was formatted there is no reason to continue - we formatted all possible javadocs.
+    // If element is out of range its children are also out of range. So in both cases formatting is finished. It's just for optimization.
+    if ((shouldFormat && (elementPsi instanceof  PsiMethod || elementPsi instanceof PsiField || elementPsi instanceof PsiDocComment))
+        || markedRange.getEndOffset() < element.getStartOffset())
+    {
+      return resultTextRange;
     }
 
     ASTNode current = element.getFirstChildNode();
     while (current != null) {
-      // we expand the chameleons here for effectiveness
-      current.getFirstChildNode();
-      result = formatCommentsInner(project, current, result);
+      // When element is PsiClass its PsiDocComment is formatted up to this moment, so we didn't need to format it again.
+      if (!(shouldFormat && current.getPsi() instanceof PsiDocComment && elementPsi instanceof PsiClass)) {
+        resultTextRange = formatCommentsInner(project, current, resultTextRange);
+      }
       current = current.getTreeNext();
     }
-    return result;
-  }
 
-  private static boolean shouldProcess(final ASTNode element) {
-    if (element instanceof PsiDocComment) {
-      return true;
-    }
-    else {
-      return true;//element.getElementType() instanceof JavaStubElementType &&
-          //(element.getPsi()) instanceof PsiDocCommentOwner;
-    }
+    return resultTextRange;
   }
 
 }
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
index 8beff5d..0fe403b 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
@@ -748,8 +748,11 @@
     String suffix = getSuffixByVariableKind(variableKind);
     boolean doDecapitalize = false;
 
-    if (name.startsWith(prefix) && name.length() > prefix.length()) {
-      name = name.substring(prefix.length());
+    int pLength = prefix.length();
+    if (pLength > 0 && name.startsWith(prefix) && name.length() > pLength &&
+        // check it's not just a long camel word that happens to begin with the specified prefix
+        (!Character.isJavaIdentifierPart(prefix.charAt(pLength - 1)) || Character.isUpperCase(name.charAt(pLength)))) {
+      name = name.substring(pLength);
       doDecapitalize = true;
     }
 
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
index 9f900c0..624c537 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
@@ -15,16 +15,21 @@
  */
 package com.intellij.psi.impl.source.codeStyle.javadoc;
 
+import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.lang.ASTNode;
+import com.intellij.lang.java.JavaLanguage;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.LineTokenizer;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
 import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -38,7 +43,7 @@
   private final JDParser myParser;
   private final Project myProject;
 
-  public CommentFormatter(Project project) {
+  public CommentFormatter(@NotNull Project project) {
     mySettings = CodeStyleSettingsManager.getSettings(project);
     myParser = new JDParser(mySettings);
     myProject = project;
@@ -52,14 +57,14 @@
     return myParser;
   }
 
-  public void process(ASTNode element) {
+  public void processComment(@Nullable ASTNode element) {
     if (!getSettings().ENABLE_JAVADOC_FORMATTING) return;
 
     PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(element);
     processElementComment(psiElement);
   }
 
-  private void processElementComment(PsiElement psiElement) {
+  private void processElementComment(@Nullable PsiElement psiElement) {
     if (psiElement instanceof PsiClass) {
       String newCommentText = formatClassComment((PsiClass)psiElement);
       replaceDocComment(newCommentText, (PsiDocCommentOwner)psiElement);
@@ -77,7 +82,7 @@
     }
   }
 
-  private void replaceDocComment(String newCommentText, final PsiDocCommentOwner psiDocCommentOwner) {
+  private void replaceDocComment(@Nullable String newCommentText, @NotNull final PsiDocCommentOwner psiDocCommentOwner) {
     final PsiDocComment oldComment = psiDocCommentOwner.getDocComment();
     if (newCommentText != null) newCommentText = stripSpaces(newCommentText);
     if (newCommentText == null || oldComment == null || newCommentText.equals(oldComment.getText())) {
@@ -99,7 +104,7 @@
 
   private static String stripSpaces(String text) {
     String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
-    StringBuffer buf = new StringBuffer(text.length());
+    StringBuilder buf = new StringBuilder(text.length());
     for (int i = 0; i < lines.length; i++) {
       if (i > 0) buf.append('\n');
       buf.append(rTrim(lines[i]));
@@ -117,7 +122,7 @@
   }
 
   @Nullable
-  private String formatClassComment(PsiClass psiClass) {
+  private String formatClassComment(@NotNull PsiClass psiClass) {
     final String info = getOrigCommentInfo(psiClass);
     if (info == null) return null;
 
@@ -126,7 +131,7 @@
   }
 
   @Nullable
-  private String formatMethodComment(PsiMethod psiMethod) {
+  private String formatMethodComment(@NotNull PsiMethod psiMethod) {
     final String info = getOrigCommentInfo(psiMethod);
     if (info == null) return null;
 
@@ -135,7 +140,7 @@
   }
 
   @Nullable
-  private String formatFieldComment(PsiField psiField) {
+  private String formatFieldComment(@NotNull PsiField psiField) {
     final String info = getOrigCommentInfo(psiField);
     if (info == null) return null;
 
@@ -149,8 +154,9 @@
    * @param element the specified element
    * @return text chunk
    */
+  @Nullable
   private static String getOrigCommentInfo(PsiDocCommentOwner element) {
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     PsiElement e = element.getFirstChild();
     if (!(e instanceof PsiComment)) {
       // no comments for this element
@@ -188,39 +194,38 @@
   }
 
   /**
-   * For the specified element returns its indentation
-   * 
-   * @param element the specified element
-   * @return indentation as string
+   * Computes indentation of PsiClass, PsiMethod and PsiField elements after formatting
+   * @param element PsiClass or PsiMethod or PsiField
+   * @return indentation size
    */
-  private static String getIndent(PsiElement element) {
-    PsiElement e = element.getFirstChild();
-    PsiWhiteSpace lastWS = null;
-    for (; ; e = e.getNextSibling()) {
-      if (e instanceof PsiWhiteSpace) {
-        lastWS = (PsiWhiteSpace)e;
-      }
-      else if (e instanceof PsiComment) {
-        lastWS = null;
-      }
-      else {
+  private int getIndentSpecial(@NotNull PsiElement element) {
+    assert(element instanceof PsiClass ||
+           element instanceof PsiField ||
+           element instanceof PsiMethod);
+
+    int indentSize = mySettings.getIndentSize(JavaFileType.INSTANCE);
+    boolean doNotIndentTopLevelClassMembers = mySettings.getCommonSettings(JavaLanguage.INSTANCE).DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS;
+
+    int indent = 0;
+    PsiClass top = PsiUtil.getTopLevelClass(element);
+    while (top != null && !element.isEquivalentTo(top)) {
+      if (doNotIndentTopLevelClassMembers && element.getParent().isEquivalentTo(top)) {
         break;
       }
+      element = element.getParent();
+      indent += indentSize;
     }
 
-    e = lastWS == null ? element.getPrevSibling() : lastWS;
-    if (!(e instanceof PsiWhiteSpace)) return "";
-    PsiWhiteSpace ws = (PsiWhiteSpace)e;
-    String t = ws.getText();
-    int l = t.length();
-    int i = l;
-    while (--i >= 0) {
-      char ch = t.charAt(i);
-      if (ch == '\n' || ch == '\r') break;
-    }
-    if (i < 0) return t;
-    i++;
-    if (i == l) return "";
-    return t.substring(i);
+    return indent;
+  }
+
+  /**
+   * Used while formatting javadocs. We need precise element indentation after formatting to wrap comments correctly.
+   * Used only for PsiClass, PsiMethod and PsiFields.
+   * @return indent which would be used for the given element when it's formatted according to the current code style settings
+   */
+  @NotNull
+  private String getIndent(@NotNull PsiElement element) {
+    return StringUtil.repeatSymbol(' ', getIndentSpecial(element));
   }
 }
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
index 28dc6a3..740b77c 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
@@ -36,6 +36,7 @@
   private List<String> mySeeAlsoList;
   private String mySince;
   private String myDeprecated;
+  private boolean myMultiLineComment;
 
   public JDComment(@NotNull CommentFormatter formatter) {
     myFormatter = formatter;
@@ -49,6 +50,10 @@
     return l == null || l.size() == 0;
   }
 
+  public void setMultiLine(boolean value) {
+    myMultiLineComment = value;
+  }
+
   @Nullable
   public String generate(@NotNull String indent) {
     final String prefix;
@@ -118,12 +123,14 @@
       sb.delete(nlen, sb.length());
     }
 
-    if( !myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS ||
-        sb.indexOf("\n") != sb.length()-1 ) {
+    if (myMultiLineComment && myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS
+        || !myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS
+        || sb.indexOf("\n") != sb.length() - 1) // If comment has become multiline after formatting - it must be shown as multiline.
+                                                // Last symbol is always '\n', so we need to check if there is one more LF symbol before it.
+    {
       sb.insert(0, "/**\n");
       sb.append(indent);
-    }
-    else {
+    } else {
       sb.replace(0, prefix.length(), "/** ");
       sb.deleteCharAt(sb.length()-1);
     }
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
index 859e848..f4ba000 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
@@ -47,14 +47,24 @@
   private static final char lineSeparator = '\n';
 
   @NotNull
-  public JDComment parse(@Nullable String text, @NotNull JDComment c) {
-    if (text == null) return c;
+  public JDComment parse(@Nullable String text, @NotNull JDComment comment) {
+    if (text == null) return comment;
 
     List<Boolean> markers = new ArrayList<Boolean>();
     List<String> l = toArray(text, "\n", markers);
-    if (l == null) return c;
+
+    //if it is - we are dealing with multiline comment:
+    // /**
+    //  * comment
+    //  */
+    //which shouldn't be wrapped into one line comment like /** comment */
+    if (text.indexOf('\n') >= 0) {
+      comment.setMultiLine(true);
+    }
+
+    if (l == null) return comment;
     int size = l.size();
-    if (size == 0) return c;
+    if (size == 0) return comment;
 
     // preprocess strings - removes first '*'
     for (int i = 0; i < size; i++) {
@@ -85,17 +95,17 @@
       if (i == size || line.length() > 0) {
         if (i == size || line.charAt(0) == '@') {
           if (tag == null) {
-            c.setDescription(sb.toString());
+            comment.setDescription(sb.toString());
           }
           else {
             int j = 0;
             String myline = sb.toString();
             for (; j < tagParsers.length; j++) {
               TagParser parser = tagParsers[j];
-              if (parser.parse(tag, myline, c)) break;
+              if (parser.parse(tag, myline, comment)) break;
             }
             if (j == tagParsers.length) {
-              c.addUnknownTag("@" + tag + " " + myline);
+              comment.addUnknownTag("@" + tag + " " + myline);
             }
           }
 
@@ -127,7 +137,7 @@
       }
     }
 
-    return c;
+    return comment;
   }
 
   /**
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
index 83e623b..ca65db6 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi.impl.source.resolve.reference.impl;
 
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
 import com.intellij.psi.*;
 import com.intellij.psi.PsiReferenceProvider;
 import com.intellij.psi.impl.source.resolve.reference.impl.providers.GenericReferenceProvider;
@@ -29,7 +30,7 @@
  * Time: 17:33:24
  * To change this template use Options | File Templates.
  */
-public abstract class GenericReference extends CachingReference {
+public abstract class GenericReference extends CachingReference implements EmptyResolveMessageProvider {
   public static final GenericReference[] EMPTY_ARRAY = new GenericReference[0];
 
   @Nullable
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
index d146982..604b90e 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
@@ -23,10 +23,8 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.util.ProcessingContext;
-import com.intellij.util.containers.*;
 import com.intellij.util.containers.HashSet;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
 
@@ -166,7 +164,7 @@
         final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
         if (aPackage != null && aPackage.getName() != null) {
           // package prefix
-          result.add(PackagePrefixFileSystemItem.create(directory));
+          result.add(PackagePrefixFileSystemItemImpl.create(directory));
         }
         else {
           result.add(directory);
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 4a379e0..5e4f279 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
@@ -17,7 +17,6 @@
 
 import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
 import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
-import com.intellij.codeInsight.daemon.QuickFixProvider;
 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
 import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
 import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
@@ -68,7 +67,7 @@
 /**
  * @author peter
  */
-public class JavaClassReference extends GenericReference implements PsiJavaReference, QuickFixProvider, LocalQuickFixProvider {
+public class JavaClassReference extends GenericReference implements PsiJavaReference, LocalQuickFixProvider {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReference");
   protected final int myIndex;
   private TextRange myRange;
@@ -94,7 +93,7 @@
   }
 
   @Override
-  public void processVariants(final PsiScopeProcessor processor) {
+  public void processVariants(@NotNull final PsiScopeProcessor processor) {
     if (processor instanceof JavaCompletionProcessor) {
       final Map<CustomizableReferenceProvider.CustomizationKey, Object> options = getOptions();
       if (options != null &&
@@ -472,11 +471,6 @@
     return new JavaResolveResult[]{javaResolveResult};
   }
 
-  @Override
-  public void registerQuickfix(HighlightInfo info, PsiReference reference) {
-    registerFixes(info);
-  }
-
   @Nullable
   private List<? extends LocalQuickFix> registerFixes(final HighlightInfo info) {
 
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java
similarity index 87%
rename from java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java
rename to java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java
index 022f69a..7b85d17 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java
@@ -36,20 +36,20 @@
 /**
  * @author Gregory.Shrago
 */
-class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSystemItem {
+class PackagePrefixFileSystemItemImpl extends PsiElementBase implements PsiFileSystemItem, PackagePrefixFileSystemItem {
   private final PsiDirectory myDirectory;
   private final int myIndex;
   private final PsiPackage[] myPackages;
 
-  public static PackagePrefixFileSystemItem create(final PsiDirectory directory) {
+  public static PackagePrefixFileSystemItemImpl create(final PsiDirectory directory) {
     final ArrayList<PsiPackage> packages = new ArrayList<PsiPackage>();
     for (PsiPackage cur = JavaDirectoryService.getInstance().getPackage(directory); cur != null; cur = cur.getParentPackage()) {
       packages.add(0, cur);
     }
-    return new PackagePrefixFileSystemItem(directory, 0, packages.toArray(new PsiPackage[packages.size()]));
+    return new PackagePrefixFileSystemItemImpl(directory, 0, packages.toArray(new PsiPackage[packages.size()]));
   }
 
-  private PackagePrefixFileSystemItem(final PsiDirectory directory, int index, final PsiPackage[] packages) {
+  private PackagePrefixFileSystemItemImpl(final PsiDirectory directory, int index, final PsiPackage[] packages) {
     myDirectory = directory;
     myIndex = index;
     myPackages = packages;
@@ -78,7 +78,7 @@
 
   @Override
   public PsiFileSystemItem getParent() {
-    return myIndex > 0 ? new PackagePrefixFileSystemItem(myDirectory, myIndex - 1, myPackages) : myDirectory.getParent();
+    return myIndex > 0 ? new PackagePrefixFileSystemItemImpl(myDirectory, myIndex - 1, myPackages) : myDirectory.getParent();
   }
 
   @Override
@@ -207,7 +207,7 @@
       return myDirectory.processChildren(processor);
     }
     else {
-      return processor.execute(new PackagePrefixFileSystemItem(myDirectory, myIndex+1, myPackages));
+      return processor.execute(new PackagePrefixFileSystemItemImpl(myDirectory, myIndex+1, myPackages));
     }
   }
 
@@ -225,7 +225,7 @@
   @Override
   @NotNull
   public PsiElement[] getChildren() {
-    return myIndex == myPackages.length -1? myDirectory.getChildren() : new PsiElement[] {new PackagePrefixFileSystemItem(myDirectory, myIndex + 1, myPackages)};
+    return myIndex == myPackages.length -1? myDirectory.getChildren() : new PsiElement[] {new PackagePrefixFileSystemItemImpl(myDirectory, myIndex + 1, myPackages)};
   }
 
   @Override
@@ -248,4 +248,9 @@
   public Icon getIcon(final int flags) {
     return myDirectory.getIcon(flags);
   }
+
+  @Override
+  public PsiDirectory getDirectory() {
+    return myDirectory;
+  }
 }
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
index 537b321..8e287ac 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
@@ -40,7 +40,7 @@
   private Set<PsiPackage> getContext() {
     if (myIndex == 0) return myReferenceSet.getInitialContext();
     Set<PsiPackage> psiPackages = new HashSet<PsiPackage>();
-    for (ResolveResult resolveResult : myReferenceSet.getReference(myIndex - 1).multiResolve(false)) {
+    for (ResolveResult resolveResult : myReferenceSet.getReference(myIndex - 1).doMultiResolve()) {
       PsiElement psiElement = resolveResult.getElement();
       if (psiElement instanceof PsiPackage) {
         psiPackages.add((PsiPackage)psiElement);
@@ -69,6 +69,11 @@
   @Override
   @NotNull
   public ResolveResult[] multiResolve(final boolean incompleteCode) {
+    return doMultiResolve();
+  }
+
+  @NotNull
+  protected ResolveResult[] doMultiResolve() {
     final Collection<PsiPackage> packages = new HashSet<PsiPackage>();
     for (PsiPackage parentPackage : getContext()) {
       packages.addAll(myReferenceSet.resolvePackageName(parentPackage, getValue()));
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
index 5b4dd7a..7d70ee9 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
@@ -72,7 +72,7 @@
     return myModificationCounter;
   }
 
-  private static Pair<PsiElement,PsiElement[]> computeAnchorAndOperandsImpl(PsiElement context) {
+  private static Pair<PsiElement,PsiElement[]> computeAnchorAndOperandsImpl(@NotNull PsiElement context) {
     PsiElement element = context;
     PsiElement parent = context.getParent();
     while (parent instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)parent).getOperationTokenType() == JavaTokenType.PLUS
@@ -102,8 +102,12 @@
 
     return Pair.create(anchor, operands);
   }
-  private static MultiHostRegistrarImpl doCompute(PsiElement context, Project project, PsiElement anchor, PsiElement[] operands) {
-    MultiHostRegistrarImpl registrar = new MultiHostRegistrarImpl(project, context.getContainingFile(), anchor);
+
+  private static MultiHostRegistrarImpl doCompute(@NotNull PsiFile containingFile,
+                                                  @NotNull Project project,
+                                                  @NotNull PsiElement anchor,
+                                                  @NotNull PsiElement[] operands) {
+    MultiHostRegistrarImpl registrar = new MultiHostRegistrarImpl(project, containingFile, anchor);
     JavaConcatenationInjectorManager concatenationInjectorManager = getInstance(project);
     for (ConcatenationAwareInjector concatenationInjector : concatenationInjectorManager.myConcatenationInjectors) {
       concatenationInjector.getLanguagesToInject(registrar, operands);
@@ -119,7 +123,7 @@
   private static final Key<ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>> INJECTED_PSI_IN_CONCATENATION = Key.create("INJECTED_PSI_IN_CONCATENATION");
   private static final Key<Integer> NO_CONCAT_INJECTION_TIMESTAMP = Key.create("NO_CONCAT_INJECTION_TIMESTAMP");
 
-  public static abstract class BaseConcatenation2InjectorAdapter implements MultiHostInjector {
+  public abstract static class BaseConcatenation2InjectorAdapter implements MultiHostInjector {
     private final JavaConcatenationInjectorManager myManager;
 
     public BaseConcatenation2InjectorAdapter(Project project) {
@@ -130,7 +134,8 @@
     public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
       if (myManager.myConcatenationInjectors.isEmpty()) return;
 
-      Project project = context.getProject();
+      final PsiFile containingFile = ((MultiHostRegistrarImpl)registrar).getHostPsiFile();
+      Project project = containingFile.getProject();
       long modificationCount = PsiManager.getInstance(project).getModificationTracker().getModificationCount();
       Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context);
       PsiElement anchor = pair.first;
@@ -146,7 +151,7 @@
         data = anchor.getUserData(INJECTED_PSI_IN_CONCATENATION);
 
         if (data == null) {
-          result = doCompute(context, project, anchor, operands);
+          result = doCompute(containingFile, project, anchor, operands);
         }
         else {
           result = data.getValue(context);
@@ -164,10 +169,11 @@
             new ParameterizedCachedValueProvider<MultiHostRegistrarImpl, PsiElement>() {
               @Override
               public CachedValueProvider.Result<MultiHostRegistrarImpl> compute(PsiElement context) {
-                Project project = context.getProject();
+                PsiFile containingFile1 = context.getContainingFile();
+                Project project1 = containingFile1.getProject();
                 Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context);
-                MultiHostRegistrarImpl registrar = doCompute(context, project, pair.first, pair.second);
-                return registrar == null ? null : CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, getInstance(project));
+                MultiHostRegistrarImpl registrar = doCompute(containingFile1, project1, pair.first, pair.second);
+                return registrar == null ? null : CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, getInstance(project1));
               }
             }, false);
           ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)data).setValue(cachedResult);
@@ -187,7 +193,7 @@
       }
     }
 
-    protected abstract Pair<PsiElement, PsiElement[]>  computeAnchorAndOperands(PsiElement context);
+    protected abstract Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(@NotNull PsiElement context);
   }
 
   public static class Concatenation2InjectorAdapter extends BaseConcatenation2InjectorAdapter implements MultiHostInjector {
@@ -197,7 +203,7 @@
     }
 
     @Override
-    public Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(PsiElement context) {
+    public Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(@NotNull PsiElement context) {
       return computeAnchorAndOperandsImpl(context);
     }
 
diff --git a/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java b/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
index 3db0c30..2a17536 100644
--- a/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
+++ b/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
@@ -21,8 +21,8 @@
 import com.intellij.psi.infos.MethodCandidateInfo;
 import com.intellij.psi.scope.PsiConflictResolver;
 import com.intellij.psi.scope.PsiScopeProcessor;
-import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
 import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver;
+import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
 import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
 import com.intellij.psi.scope.processor.MethodResolverProcessor;
 import com.intellij.psi.util.MethodSignature;
@@ -33,7 +33,9 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -45,11 +47,12 @@
   private final MethodCandidatesProcessor myProcessor;
   @Nullable private final PsiType[] myArgumentTypes;
 
-  public JavaMethodResolveHelper(final PsiElement argumentList, @Nullable final PsiType[] argumentTypes) {
+  public JavaMethodResolveHelper(@NotNull final PsiElement argumentList, PsiFile containingFile, @Nullable final PsiType[] argumentTypes) {
     myArgumentTypes = argumentTypes;
     final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(argumentList);
-    final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes);
-    myProcessor = new MethodResolverProcessor(argumentList, new PsiConflictResolver[]{resolver}) {
+    final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes,
+                                                                                                                                      languageLevel);
+    myProcessor = new MethodResolverProcessor(argumentList, containingFile, new PsiConflictResolver[]{resolver}) {
       @Override
       protected MethodCandidateInfo createCandidateInfo(final PsiMethod method, final PsiSubstitutor substitutor,
                                                         final boolean staticProblem,
@@ -72,7 +75,8 @@
                                                     PsiElement currentFileContext,
                                                     boolean accessProblem,
                                                     PsiElement argumentList,
-                                                    PsiType[] argumentTypes, LanguageLevel languageLevel) {
+                                                    PsiType[] argumentTypes,
+                                                    @NotNull LanguageLevel languageLevel) {
     return new MethodCandidateInfo(method, substitutor, accessProblem, staticProblem, argumentList, currentFileContext, argumentTypes,
                                    PsiType.EMPTY_ARRAY, languageLevel);
   }
@@ -85,12 +89,16 @@
 
   @NotNull
   public ErrorType getResolveError() {
-    final CandidateInfo[] candidates = myProcessor.getCandidates();
-    if (candidates.length != 1) return ErrorType.RESOLVE;
+    final List<CandidateInfo> candidates = getCandidates();
+    if (candidates.size() != 1) return ErrorType.RESOLVE;
 
-    if (!candidates[0].isStaticsScopeCorrect()) return ErrorType.STATIC;
+    if (!candidates.get(0).isStaticsScopeCorrect()) return ErrorType.STATIC;
 
-    return getResolveError((MethodCandidateInfo)candidates[0]);
+    return getResolveError((MethodCandidateInfo)candidates.get(0));
+  }
+
+  protected List<CandidateInfo> getCandidates() {
+    return Arrays.asList(myProcessor.getCandidates());
   }
 
   protected ErrorType getResolveError(MethodCandidateInfo info) {
@@ -125,7 +133,7 @@
   }
 
   public Collection<JavaMethodCandidateInfo> getMethods() {
-    return ContainerUtil.mapNotNull(myProcessor.getResult(), new Function<JavaResolveResult, JavaMethodCandidateInfo>() {
+    return ContainerUtil.mapNotNull(getCandidates(), new Function<JavaResolveResult, JavaMethodCandidateInfo>() {
       @Override
       public JavaMethodCandidateInfo fun(final JavaResolveResult javaResolveResult) {
         return new JavaMethodCandidateInfo((PsiMethod)javaResolveResult.getElement(), javaResolveResult.getSubstitutor());
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
index b5d0e09..8b721b6 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
@@ -258,10 +258,11 @@
   }
 
   protected void setupPropagationEnabled(final PsiParameter[] parameters, final ParameterInfoImpl[] newParms) {
-    if (parameters.length != newParms.length) {
+    if (parameters.length >= newParms.length) {
       isPropagationEnabled = false;
     }
     else {
+      isPropagationEnabled = !propagateParametersMethods.isEmpty();
       for (int i = 0; i < parameters.length; i++) {
         final ParameterInfoImpl newParm = newParms[i];
         if (newParm.oldParameterIndex != i) {
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
index d46fa20..bfbe8b2 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.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.
@@ -192,7 +192,7 @@
     myPropExceptionsButton.setShortcut(CustomShortcutSet.fromString("alt X"));
 
     final JPanel panel = ToolbarDecorator.createDecorator(table).addExtraAction(myPropExceptionsButton).createPanel();
-    panel.setBorder(IdeBorderFactory.createEmptyBorder(0));
+    panel.setBorder(IdeBorderFactory.createEmptyBorder());
 
     myExceptionsModel.addTableModelListener(mySignatureUpdater);
 
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
index cc4d0cd..e8bb45c 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
@@ -380,7 +380,7 @@
           else {
             newArg = factory.createExpressionFromText(info.getName(), list);
           }
-          JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list.add(newArg));
+          if (newArg != null) JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list.add(newArg));
         }
       }
       else {
diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
index 9943d48..e8d41e0 100644
--- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.refactoring.encapsulateFields;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.help.HelpManager;
@@ -509,8 +510,8 @@
 
   private PsiMethod generateMethodPrototype(PsiField field, String methodName, boolean isGetter) {
     PsiMethod prototype = isGetter
-                          ? PropertyUtil.generateGetterPrototype(field)
-                          : PropertyUtil.generateSetterPrototype(field);
+                          ? GenerateMembersUtil.generateGetterPrototype(field)
+                          : GenerateMembersUtil.generateSetterPrototype(field);
     try {
       PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
       PsiIdentifier identifier = factory.createIdentifier(methodName);
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
index 284433f..9013129 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
@@ -21,6 +21,7 @@
 package com.intellij.refactoring.extractMethodObject;
 
 import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
@@ -255,7 +256,7 @@
         field = PropertyUtil.findPropertyField(myProject, myInnerClass, name, false);
       }
       LOG.assertTrue(field != null, "i:" + i + "; output variables: " + Arrays.toString(outputVariables) + "; parameters: " + Arrays.toString(getMethod().getParameterList().getParameters()) + "; output field: " + outputField );
-      myInnerClass.add(PropertyUtil.generateGetterPrototype(field));
+      myInnerClass.add(GenerateMembersUtil.generateGetterPrototype(field));
     }
 
     PsiParameter[] params = getMethod().getParameterList().getParameters();
diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
index d096db5..3969ae5 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.refactoring.extractclass;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.ide.util.PackageUtil;
 import com.intellij.openapi.application.ApplicationManager;
@@ -311,11 +312,11 @@
     if (myGenerateAccessors) {
       final NecessaryAccessorsVisitor visitor = checkNecessaryGettersSetters4SourceClass();
       for (PsiField field : visitor.getFieldsNeedingGetter()) {
-        sourceClass.add(PropertyUtil.generateGetterPrototype(field));
+        sourceClass.add(GenerateMembersUtil.generateGetterPrototype(field));
       }
 
       for (PsiField field : visitor.getFieldsNeedingSetter()) {
-        sourceClass.add(PropertyUtil.generateSetterPrototype(field));
+        sourceClass.add(GenerateMembersUtil.generateSetterPrototype(field));
       }
     }
     super.performRefactoring(usageInfos);
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
index 0ef27c9..a94f411 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
@@ -15,11 +15,11 @@
  */
 package com.intellij.refactoring.introduceParameter;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.util.PropertyUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.IntroduceParameterRefactoring;
 import com.intellij.refactoring.util.RefactoringUtil;
@@ -217,7 +217,7 @@
     }
     PsiElement newExpr = expr;
 
-    PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(psiField);
+    PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(psiField);
 
     PsiMethod getter = psiField.getContainingClass().findMethodBySignature(getterPrototype, true);
 
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
index 59ec81a..e862915 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
@@ -20,12 +20,12 @@
  */
 package com.intellij.refactoring.introduceparameterobject.usageInfo;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiField;
 import com.intellij.psi.PsiParameter;
-import com.intellij.psi.util.PropertyUtil;
 import com.intellij.refactoring.RefactorJBundle;
 import com.intellij.refactoring.introduceparameterobject.IntroduceParameterObjectProcessor;
 import com.intellij.refactoring.util.FixableUsageInfo;
@@ -70,8 +70,8 @@
         final PsiField field = parameterChunk.getField();
         if (field != null) {
           element.add(isGetter
-                      ? PropertyUtil.generateGetterPrototype(field)
-                      : PropertyUtil.generateSetterPrototype(field));
+                      ? GenerateMembersUtil.generateGetterPrototype(field)
+                      : GenerateMembersUtil.generateSetterPrototype(field));
         }
 
       }
diff --git a/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java b/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
index ab14d4f..091e6f7 100644
--- a/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
@@ -15,6 +15,7 @@
  */
 package com.intellij.refactoring.removemiddleman;
 
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
@@ -99,7 +100,7 @@
       } else {
         access = getterName + "()";
         if (getter == null) {
-          getter = PropertyUtil.generateGetterPrototype(field);
+          getter = GenerateMembersUtil.generateGetterPrototype(field);
         }
       }
       usages.add(new InlineDelegatingCall(call, paramPermutation, access, delegatedMethod.getName()));
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
index 6c29623..5045c2b 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
@@ -15,16 +15,20 @@
  */
 package com.intellij.refactoring.rename.naming;
 
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.JavaPsiFacade;
+import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiShortNamesCache;
 import com.intellij.refactoring.JavaRefactoringSettings;
 import com.intellij.refactoring.RefactoringBundle;
 import com.intellij.usageView.UsageInfo;
+import com.intellij.util.containers.HashSet;
 
 import java.util.Collection;
+import java.util.regex.Pattern;
 
 /**
  * @author yole
@@ -59,18 +63,33 @@
   private static class TestsRenamer extends AutomaticRenamer {
     public TestsRenamer(PsiClass aClass, String newClassName) {
 
-      appendTestClass(aClass, "Test");
-      appendTestClass(aClass, "TestCase");
+      final Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
+      if (module != null) {
+        final GlobalSearchScope moduleScope = GlobalSearchScope.moduleWithDependentsScope(module);
 
-      suggestAllNames(aClass.getName(), newClassName);
+        appendTestClass(aClass, "Test", moduleScope);
+        appendTestClass(aClass, "TestCase", moduleScope);
+
+        suggestAllNames(aClass.getName(), newClassName);
+      }
     }
 
-    private void appendTestClass(PsiClass aClass, String testSuffix) {
-      final Project project = aClass.getProject();
-      final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
-      final PsiClass psiClassTest = facade.findClass(aClass.getQualifiedName() + testSuffix, GlobalSearchScope.projectScope(project));
-      if (psiClassTest != null) {
-        myElements.add(psiClassTest);
+    private void appendTestClass(PsiClass aClass, String testSuffix, final GlobalSearchScope moduleScope) {
+      PsiShortNamesCache cache = PsiShortNamesCache.getInstance(aClass.getProject());
+
+      String klassName = aClass.getName();
+      Pattern pattern = Pattern.compile(".*" + klassName + ".*" + testSuffix);
+
+      HashSet<String> names = new HashSet<String>();
+      cache.getAllClassNames(names);
+      for (String eachName : names) {
+        if (pattern.matcher(eachName).matches()) {
+          for (PsiClass eachClass : cache.getClassesByName(eachName, moduleScope)) {
+            if (TestFrameworks.getInstance().isTestClass(eachClass)) {
+              myElements.add(eachClass);
+            }
+          }
+        }
       }
     }
 
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
index ac7a6d9..46b604e 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
@@ -457,13 +457,6 @@
             removeDeletedMethods(OverridingMethodsSearch.search(psiMethod, true).toArray(PsiMethod.EMPTY_ARRAY),
                                  allElementsToDelete);
 
-    for (PsiReference reference : references) {
-      final PsiElement element = reference.getElement();
-      if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) {
-        usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiMethod, PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) != null));
-      }
-    }
-
     final HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>();
     for (PsiMethod overridingMethod : overridingMethods) {
       final Collection<PsiReference> overridingReferences = ReferencesSearch.search(overridingMethod).findAll();
@@ -472,6 +465,12 @@
     final Set<PsiMethod> validOverriding =
       validateOverridingMethods(psiMethod, references, Arrays.asList(overridingMethods), methodToReferences, usages,
                                 allElementsToDelete);
+    for (PsiReference reference : references) {
+      final PsiElement element = reference.getElement();
+      if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) {
+        usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiMethod, PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) != null));
+      }
+    }
     return new Condition<PsiElement>() {
       public boolean value(PsiElement usage) {
         if(usage instanceof PsiFile) return false;
@@ -594,12 +593,12 @@
     }
 
     for (PsiMethod method : overridingMethods) {
-      if (!validOverriding.contains(method) && !multipleInterfaceImplementations.contains(method)) {
-        final boolean methodCanBePrivate =
-          canBePrivate(method, methodToReferences.get(method), validOverriding, allElementsToDelete);
-        if (methodCanBePrivate) {
-          usages.add(new SafeDeletePrivatizeMethod(method, originalMethod));
-        }
+      if (!validOverriding.contains(method) &&
+          !multipleInterfaceImplementations.contains(method) &&
+          canBePrivate(method, methodToReferences.get(method), validOverriding, allElementsToDelete)) {
+        usages.add(new SafeDeletePrivatizeMethod(method, originalMethod));
+      } else {
+        usages.add(new SafeDeleteOverrideAnnotation(method, originalMethod));
       }
     }
     return validOverriding;
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java
new file mode 100644
index 0000000..9a31595
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java
@@ -0,0 +1,43 @@
+/*
+ * 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.refactoring.safeDelete.usageInfo;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * User: anna
+ * Date: 7/22/13
+ */
+public class SafeDeleteOverrideAnnotation extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
+  public SafeDeleteOverrideAnnotation(PsiElement element, PsiElement referencedElement) {
+    super(element, referencedElement);
+  }
+
+  public PsiMethod getMethod() {
+    return (PsiMethod)getElement();
+  }
+
+  public void performRefactoring() throws IncorrectOperationException {
+    final PsiAnnotation annotation = AnnotationUtil.findAnnotation(getMethod(), true, Override.class.getName());
+    if (annotation != null) {
+      annotation.delete();
+    }
+  }
+}
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
index 0e0e70f..70a6b44 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
@@ -15,8 +15,6 @@
  */
 package com.intellij.refactoring.safeDelete.usageInfo;
 
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.psi.PsiAnnotation;
 import com.intellij.psi.PsiMethod;
 import com.intellij.psi.PsiModifier;
 import com.intellij.psi.util.PsiUtil;
@@ -25,20 +23,13 @@
 /**
  * @author dsl
  */
-public class SafeDeletePrivatizeMethod extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
+public class SafeDeletePrivatizeMethod extends SafeDeleteOverrideAnnotation {
   public SafeDeletePrivatizeMethod(PsiMethod method, PsiMethod overridenMethod) {
     super(method, overridenMethod);
   }
 
-  public PsiMethod getMethod() {
-    return (PsiMethod) getElement();
-  }
-
   public void performRefactoring() throws IncorrectOperationException {
     PsiUtil.setModifierProperty(getMethod(), PsiModifier.PRIVATE, true);
-    final PsiAnnotation annotation = AnnotationUtil.findAnnotation(getMethod(), true, Override.class.getName());
-    if (annotation != null) {
-      annotation.delete();
-    }
+    super.performRefactoring();
   }
 }
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index ca905b0..abf333c 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -1137,7 +1137,7 @@
       paramTag.delete();
     }
     for (PsiDocTag psiDocTag : newTags) {
-      anchor = docComment.addAfter(psiDocTag, anchor);
+      anchor = anchor != null && anchor.isValid() ? docComment.addAfter(psiDocTag, anchor) : docComment.add(psiDocTag);
     }
   }
 
diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java
new file mode 100644
index 0000000..94fa4f2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.unscramble;
+
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.project.Project;
+
+import javax.swing.*;
+import java.util.List;
+
+/**
+* Created by Irina.Chernushina on 7/13/13.
+*/
+public class ThreadDumpConsoleFactory implements AnalyzeStacktraceUtil.ConsoleFactory {
+  private final Project myProject;
+  private final List<ThreadState> myThreadDump;
+
+  public ThreadDumpConsoleFactory(Project project, List<ThreadState> threadDump) {
+    myProject = project;
+    myThreadDump = threadDump;
+  }
+
+  public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
+    return new ThreadDumpPanel(myProject, consoleView, toolbarActions, myThreadDump);
+  }
+}
diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
index 2627fd2..3731125 100644
--- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
+++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
@@ -15,12 +15,10 @@
  */
 package com.intellij.unscramble;
 
-import com.intellij.execution.ui.ConsoleView;
 import com.intellij.execution.ui.RunContentDescriptor;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.IdeBundle;
 import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileChooser.FileChooser;
 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -410,11 +408,7 @@
       message = IdeBundle.message("unscramble.unscrambled.deadlock.tab");
       icon = AllIcons.Debugger.KillProcess;
     }
-    return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new AnalyzeStacktraceUtil.ConsoleFactory() {
-      public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
-        return new ThreadDumpPanel(project, consoleView, toolbarActions, threadDump);
-      }
-    } : null, message, unscrambledTrace, icon);
+    return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new ThreadDumpConsoleFactory(project, threadDump) : null, message, unscrambledTrace, icon);
   }
 
   protected String getDimensionServiceKey(){
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 3878aaa..8cd8471 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
@@ -48,6 +48,8 @@
     }
     final PsiElement psiElement = ((PsiElementUsage)usage).getElement();
     final PsiFile containingFile = psiElement.getContainingFile();
+    if (containingFile == null) return null;
+
     PsiFile topLevelFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
 
     if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof JspFile) {
diff --git a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
index 152e51a..88ccc0a 100644
--- a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
+++ b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
@@ -91,7 +91,7 @@
             return super.advancedResolve(incompleteCode);
           }
 
-          public void processVariants(final PsiScopeProcessor processor) {
+          public void processVariants(@NotNull final PsiScopeProcessor processor) {
             if (processor instanceof JavaCompletionProcessor) {
               ((JavaCompletionProcessor)processor).setCompletionElements(getVariants());
             } else {