/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.codeInsight.daemon.impl;

import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
import com.intellij.codeInsight.daemon.impl.analysis.*;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.EmptyIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
import com.intellij.lang.Language;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.PomNamedTarget;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Processor;
import com.intellij.util.containers.Predicate;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;

import java.util.*;

public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
  private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
  private final LanguageLevel myLanguageLevel;
  private RefCountHolder myRefCountHolder;
  private final PsiFile myFile;
  @Nullable private final Editor myEditor;
  @NotNull private final Predicate<PsiElement> myIsEntryPointPredicate;
  private final int myStartOffset;
  private final int myEndOffset;

  private Collection<HighlightInfo> myHighlights;
  private boolean myHasRedundantImports;
  private int myCurrentEntryIndex;
  private boolean myHasMissortedImports;
  private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
  private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection;
  private HighlightDisplayKey myUnusedSymbolKey;
  private boolean myInLibrary;
  private HighlightDisplayKey myDeadCodeKey;
  private HighlightInfoType myDeadCodeInfoType;

  public PostHighlightingPass(@NotNull Project project,
                              @NotNull PsiFile file,
                              @Nullable Editor editor,
                              @NotNull Document document,
                              @NotNull HighlightInfoProcessor highlightInfoProcessor,
                              @NotNull Predicate<PsiElement> isEntryPoint) {
    super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor);
    myFile = file;
    myEditor = editor;
    myIsEntryPointPredicate = isEntryPoint;
    myStartOffset = 0;
    myEndOffset = file.getTextLength();

    myCurrentEntryIndex = -1;
    myLanguageLevel = PsiUtil.getLanguageLevel(file);
  }

  static boolean isUpToDate(@NotNull PsiFile file) {
    Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
    long currentStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
    return lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file);
  }

  private static void markFileUpToDate(@NotNull PsiFile file) {
    long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
    file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
  }

  private static boolean isInjected(@NotNull Project project, @NotNull PsiModifierListOwner modifierListOwner) {
    return EntryPointsManagerBase.getInstance(project).isEntryPoint(modifierListOwner);
  }

  @Override
  protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
    DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
    final FileStatusMap fileStatusMap = daemonCodeAnalyzer.getFileStatusMap();
    final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>();
    final FileViewProvider viewProvider = myFile.getViewProvider();
    final Set<Language> relevantLanguages = viewProvider.getLanguages();
    final Set<PsiElement> elementSet = new THashSet<PsiElement>();
    for (Language language : relevantLanguages) {
      PsiElement psiRoot = viewProvider.getPsi(language);
      if (!HighlightingLevelManager.getInstance(myProject).shouldHighlight(psiRoot)) continue;
      List<PsiElement> elements = CollectHighlightsUtil.getElementsInRange(psiRoot, myStartOffset, myEndOffset);
      elementSet.addAll(elements);
    }

    ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
    VirtualFile virtualFile = viewProvider.getVirtualFile();
    myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);

    myRefCountHolder = RefCountHolder.endUsing(myFile, progress);
    if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(progress, new Runnable() {
      @Override
      public void run() {
        boolean errorFound = collectHighlights(elementSet, highlights, progress);
        myHighlights = highlights;
        if (errorFound) {
          fileStatusMap.setErrorFoundFlag(myDocument, true);
        }
      }
    })) {
      // we must be sure GHP will restart
      fileStatusMap.markFileScopeDirty(getDocument(), Pass.UPDATE_ALL);
      GeneralHighlightingPass.cancelAndRestartDaemonLater(progress, myProject, this);
    }
  }

  @NotNull
  @Override
  public List<HighlightInfo> getInfos() {
    Collection<HighlightInfo> infos = myHighlights;
    return infos == null ? Collections.<HighlightInfo>emptyList() : new ArrayList<HighlightInfo>(infos);
  }

  @Override
  protected void applyInformationWithProgress() {
    if (myHighlights == null) return;
    UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL);
    markFileUpToDate(myFile);

    Editor editor = myEditor;
    if (editor != null) {
      optimizeImportsOnTheFly(editor);
    }
  }

  private void optimizeImportsOnTheFly(@NotNull final Editor editor) {
    if (myHasRedundantImports || myHasMissortedImports) {
      IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix(true);
      if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) {
        optimizeImportsFix.invoke(myProject, editor, myFile);
      }
    }
  }

  // returns true if error highlight was created
  private boolean collectHighlights(@NotNull Collection<PsiElement> elements,
                                    @NotNull final List<HighlightInfo> result,
                                    @NotNull ProgressIndicator progress) throws ProcessCanceledException {
    ApplicationManager.getApplication().assertReadAccessAllowed();

    InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
    myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspectionBase.SHORT_NAME);
    boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile);
    myUnusedSymbolInspection = (UnusedSymbolLocalInspectionBase)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.SHORT_NAME, myFile);
    LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null);

    myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);

    HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);

    myDeadCodeInfoType = myDeadCodeKey == null
                         ? HighlightInfoType.UNUSED_SYMBOL
                         : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(),
                                                                       HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());

    GlobalUsageHelper helper = new GlobalUsageHelper() {
      @Override
      public boolean shouldCheckUsages(@NotNull PsiMember member) {
        return !myInLibrary && !myIsEntryPointPredicate.apply(member);
      }

      @Override
      public boolean isCurrentFileAlreadyChecked() {
        return true;
      }

      @Override
      public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
        return myRefCountHolder.isReferenced(member);
      }
    };

    boolean errorFound = false;
    if (unusedSymbolEnabled) {
      for (PsiElement element : elements) {
        progress.checkCanceled();
        if (element instanceof PsiIdentifier) {
          PsiIdentifier identifier = (PsiIdentifier)element;
          HighlightInfo info = processIdentifier(identifier, progress, helper);
          if (info != null) {
            errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
            result.add(info);
          }
        }
      }
    }
    if (isUnusedImportEnabled(unusedImportKey)) {
      PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
      if (importList != null) {
        final PsiImportStatementBase[] imports = importList.getAllImportStatements();
        for (PsiImportStatementBase statement : imports) {
          progress.checkCanceled();
          final HighlightInfo info = processImport(statement, unusedImportKey);
          if (info != null) {
            errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
            result.add(info);
          }
        }
      }
    }

    return errorFound;
  }

  protected boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey) {
    InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
    if (!profile.isToolEnabled(unusedImportKey, myFile)) return false;
    return myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile);
  }

  @Nullable
  private HighlightInfo processIdentifier(@NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) {
    if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
    PsiElement parent = identifier.getParent();
    if (PsiUtilCore.hasErrorElementChild(parent)) return null;

    if (parent instanceof PsiLocalVariable && myUnusedSymbolInspection.LOCAL_VARIABLE) {
      return processLocalVariable((PsiLocalVariable)parent, identifier, progress);
    }
    if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
      return processField(myProject, (PsiField)parent, identifier, progress, helper);
    }
    if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
      if (SuppressionUtil.isSuppressed(identifier, UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME)) return null;
      return processParameter(myProject, (PsiParameter)parent, identifier, progress);
    }
    if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
      return processMethod(myProject, (PsiMethod)parent, identifier, progress, helper);
    }
    if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
      return processClass(myProject, (PsiClass)parent, identifier, progress, helper);
    }
    return null;
  }

  @Nullable
  private HighlightInfo processLocalVariable(@NotNull PsiLocalVariable variable,
                                             @NotNull PsiIdentifier identifier,
                                             @NotNull ProgressIndicator progress) {
    if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null;
    if (isImplicitUsage(myProject, variable, progress)) return null;

    if (!myRefCountHolder.isReferenced(variable)) {
      String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText());
      HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
      IntentionAction fix = variable instanceof PsiResourceVariable ? QuickFixFactory.getInstance().createRenameToIgnoredFix(variable) : QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable);
      QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey);
      return highlightInfo;
    }

    boolean referenced = myRefCountHolder.isReferencedForRead(variable);
    if (!referenced && !isImplicitRead(myProject, variable, progress)) {
      String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText());
      HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
      QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable), myUnusedSymbolKey);
      return highlightInfo;
    }

    if (!variable.hasInitializer()) {
      referenced = myRefCountHolder.isReferencedForWrite(variable);
      if (!referenced && !isImplicitWrite(myProject, variable, progress)) {
        String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText());
        final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
        QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspectionBase.DISPLAY_NAME), myUnusedSymbolKey);
        return unusedSymbolInfo;
      }
    }

    return null;
  }

  public static boolean isImplicitUsage(@NotNull Project project,
                                        @NotNull PsiModifierListOwner element,
                                        @NotNull ProgressIndicator progress) {
    if (isInjected(project, element)) return true;
    for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
      progress.checkCanceled();
      if (provider.isImplicitUsage(element)) {
        return true;
      }
    }

    return false;
  }

  private static boolean isImplicitRead(@NotNull Project project, @NotNull PsiVariable element, @NotNull ProgressIndicator progress) {
    for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
      progress.checkCanceled();
      if (provider.isImplicitRead(element)) {
        return true;
      }
    }
    return isInjected(project, element);
  }

  private static boolean isImplicitWrite(@NotNull Project project,
                                         @NotNull PsiVariable element,
                                         @NotNull ProgressIndicator progress) {
    for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
      progress.checkCanceled();
      if (provider.isImplicitWrite(element)) {
        return true;
      }
    }
    return isInjected(project, element);
  }

  @Nullable
  public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element,
                                                     @NotNull String message,
                                                     @NotNull final HighlightInfoType highlightInfoType) {
    HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create();
    if (info == null) {
      return null; //filtered out
    }
    
    UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME);
    for (UnusedDeclarationFixProvider provider : fixProviders) {
      IntentionAction[] fixes = provider.getQuickFixes(element);
      for (IntentionAction fix : fixes) {
        QuickFixAction.registerQuickFixAction(info, fix);
      }
    }
    return info;
  }

  @Nullable
  private HighlightInfo processField(@NotNull final Project project,
                                     @NotNull final PsiField field,
                                     @NotNull PsiIdentifier identifier,
                                     @NotNull ProgressIndicator progress,
                                     @NotNull GlobalUsageHelper helper) {
    if (HighlightUtil.isSerializationImplicitlyUsedField(field)) {
      return null;
    }
    if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
      if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(myProject, field, progress)) {
        String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText());

        HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message);
        if (!field.hasInitializer()) {
          QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(field));
        }
        return highlightInfo;
      }

      final boolean readReferenced = myRefCountHolder.isReferencedForRead(field);
      if (!readReferenced && !isImplicitRead(project, field, progress)) {
        String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText());
        return suggestionsToMakeFieldUsed(field, identifier, message);
      }

      if (field.hasInitializer()) {
        return null;
      }
      final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field);
      if (!writeReferenced && !isImplicitWrite(project, field, progress)) {
        String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText());
        final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);

        QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
        QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(
          field));
        SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
          @Override
          public boolean process(final String annoName) {
            QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance()
              .createAddToDependencyInjectionAnnotationsFix(project, annoName, "fields"));
            return true;
          }
        });
        return info;
      }
    }
    else if (isImplicitUsage(myProject, field, progress)) {
      return null;
    }
    else if (isFieldUnused(myProject, myFile, field, progress, helper)) {
      return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
    }
    return null;
  }

  public static boolean isFieldUnused(@NotNull Project project,
                                      @NotNull PsiFile containingFile,
                                      @NotNull PsiField field,
                                      @NotNull ProgressIndicator progress,
                                      @NotNull GlobalUsageHelper helper) {
    if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) {
      return false;
    }
    return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper);
  }

  private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) {
    HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(field), myUnusedSymbolKey);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
    return highlightInfo;
  }

  private static boolean isOverriddenOrOverrides(PsiMethod method) {
    boolean overrides = SuperMethodsSearch.search(method, null, true, false).findFirst() != null;
    return overrides || OverridingMethodsSearch.search(method).findFirst() != null;
  }

  @Nullable
  private HighlightInfo processParameter(@NotNull Project project,
                                         @NotNull PsiParameter parameter,
                                         @NotNull PsiIdentifier identifier,
                                         @NotNull ProgressIndicator progress) {
    PsiElement declarationScope = parameter.getDeclarationScope();
    if (declarationScope instanceof PsiMethod) {
      PsiMethod method = (PsiMethod)declarationScope;
      if (PsiUtilCore.hasErrorElementChild(method)) return null;
      if ((method.isConstructor() ||
           method.hasModifierProperty(PsiModifier.PRIVATE) ||
           method.hasModifierProperty(PsiModifier.STATIC) ||
           !method.hasModifierProperty(PsiModifier.ABSTRACT) &&
           myUnusedSymbolInspection.REPORT_PARAMETER_FOR_PUBLIC_METHODS &&
           !isOverriddenOrOverrides(method)) &&
          !method.hasModifierProperty(PsiModifier.NATIVE) &&
          !JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
          !PsiClassImplUtil.isMainOrPremainMethod(method)) {
        if (isInjected(project, method)) return null;
        HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
        if (highlightInfo != null) {
          QuickFixFactory.getInstance().registerFixesForUnusedParameter(parameter, highlightInfo);
          return highlightInfo;
        }
      }
    }
    else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) {
      HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
      if (highlightInfo != null) {
        QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRenameToIgnoredFix(parameter), myUnusedSymbolKey);
        return highlightInfo;
      }
    }

    return null;
  }

  @Nullable
  private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter,
                                             @NotNull PsiIdentifier identifier,
                                             @NotNull ProgressIndicator progress) {
    if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(myProject, parameter, progress)) {
      //parameter is defined by functional interface
      final PsiElement declarationScope = parameter.getDeclarationScope();
      if (declarationScope instanceof PsiMethod && 
          myRefCountHolder.isReferencedByMethodReference((PsiMethod)declarationScope, myLanguageLevel)) {
        return null;
      }
      String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
      return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
    }
    return null;
  }

  @Nullable
  private HighlightInfo processMethod(@NotNull final Project project,
                                      @NotNull final PsiMethod method,
                                      @NotNull PsiIdentifier identifier,
                                      @NotNull ProgressIndicator progress,
                                      @NotNull GlobalUsageHelper helper) {
    if (isMethodReferenced(myProject, myFile, method, progress, helper)) return null;
    HighlightInfoType highlightInfoType;
    HighlightDisplayKey highlightDisplayKey;
    String key;
    if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
      highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
      highlightDisplayKey = myUnusedSymbolKey;
      key = method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used";
    }
    else {
      highlightInfoType = myDeadCodeInfoType;
      highlightDisplayKey = myDeadCodeKey;
      key = method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used";
    }
    String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY);
    String message = JavaErrorMessages.message(key, symbolName);
    final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), highlightDisplayKey);
    SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor<String>() {
      @Override
      public boolean process(final String annoName) {
        IntentionAction fix = QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, "methods");
        QuickFixAction.registerQuickFixAction(highlightInfo, fix);
        return true;
      }
    });
    return highlightInfo;
  }

  public static boolean isMethodReferenced(@NotNull Project project,
                                           @NotNull PsiFile containingFile,
                                           @NotNull PsiMethod method,
                                           @NotNull ProgressIndicator progress,
                                           @NotNull GlobalUsageHelper helper) {
    if (helper.isLocallyUsed(method)) return true;

    boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
    PsiClass containingClass = method.getContainingClass();
    if (JavaHighlightUtil.isSerializationRelatedMethod(method, containingClass)) return true;
    if (aPrivate) {
      if (isIntentionalPrivateConstructor(method, containingClass)) {
        return true;
      }
      if (isImplicitUsage(project, method, progress)) {
        return true;
      }
      if (!helper.isCurrentFileAlreadyChecked()) {
        return !weAreSureThereAreNoUsages(project, containingFile, method, progress, helper);
      }
    }
    else {
      //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
      if (containingClass != null && method.isConstructor()
          && containingClass.getConstructors().length == 1
          && isClassUsed(project, containingFile, containingClass, progress, helper)) {
        return true;
      }
      if (isImplicitUsage(project, method, progress)) return true;

      if (method.findSuperMethods().length != 0) {
        return true;
      }
      if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) {
        return true;
      }
    }
    return false;
  }

  private static boolean weAreSureThereAreNoUsages(@NotNull Project project,
                                                   @NotNull PsiFile containingFile,
                                                   @NotNull PsiMember member,
                                                   @NotNull ProgressIndicator progress,
                                                   @NotNull GlobalUsageHelper helper) {
    if (!helper.shouldCheckUsages(member)) return false;

    String name = member.getName();
    if (name == null) return false;
    SearchScope useScope = member.getUseScope();
    PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
    PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null;
    if (useScope instanceof GlobalSearchScope) {
      // some classes may have references from within XML outside dependent modules, e.g. our actions
      if (member instanceof PsiClass) {
        useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
      }

      PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
      if (cheapEnough == PsiSearchHelper.SearchCostResult.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 && !canBeReferencedViaWeirdNames(member, containingFile)) {
        return true;
      }

      if (member instanceof PsiMethod) {
        String propertyName = PropertyUtil.getPropertyName(member);
        if (propertyName != null) {
          SearchScope fileScope = containingFile.getUseScope();
          if (fileScope instanceof GlobalSearchScope &&
              searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) ==
              PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) {
            return false;
          }
        }
      }
    }
    if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false;
    return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope, searchHelper, ignoreFile);
  }

  private static boolean foundUsageInText(@NotNull PsiMember member,
                                          @NotNull GlobalSearchScope scope,
                                          @NotNull PsiSearchHelper searchHelper,
                                          final PsiFile ignoreFile) {
    return !searchHelper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() {
      @Override
      public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
        if (psiFile == ignoreFile) return true; // ignore usages in containingFile because isLocallyUsed() method would have caught that
        PsiElement element = psiFile.findElementAt(startOffset);
        return element instanceof PsiComment; // ignore comments
      }
    }, scope);
  }

  private static boolean isEnumValuesMethodUsed(@NotNull Project project,
                                                @NotNull PsiFile containingFile,
                                                @NotNull PsiMember member,
                                                @NotNull ProgressIndicator progress,
                                                @NotNull GlobalUsageHelper helper) {
    final PsiClass containingClass = member.getContainingClass();
    if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
    final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
    return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper);
  }

  private static boolean canBeReferencedViaWeirdNames(@NotNull PsiMember member, @NotNull PsiFile containingFile) {
    if (member instanceof PsiClass) return false;
    if (!(containingFile instanceof PsiJavaFile)) return true;  // Groovy field can be referenced from Java by getter
    if (member instanceof PsiField) return false;  //Java field cannot be referenced by anything but its name
    if (member instanceof PsiMethod) {
      return PropertyUtil.isSimplePropertyAccessor((PsiMethod)member);  //Java accessors can be referenced by field name from Groovy
    }
    return false;
  }

  @Nullable
  private HighlightInfo processClass(@NotNull Project project,
                                     @NotNull PsiClass aClass,
                                     @NotNull PsiIdentifier identifier,
                                     @NotNull ProgressIndicator progress,
                                     @NotNull GlobalUsageHelper helper) {
    if (isClassUsed(project, myFile, aClass, progress, helper)) return null;

    String pattern;
    HighlightDisplayKey highlightDisplayKey;
    HighlightInfoType highlightInfoType;
    if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE)) {
      pattern = aClass.isInterface()
                       ? "private.inner.interface.is.not.used"
                       : "private.inner.class.is.not.used";
      highlightDisplayKey = myUnusedSymbolKey;
      highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
    }
    else if (aClass.getParent() instanceof PsiDeclarationStatement) { // local class
      pattern = "local.class.is.not.used";
      highlightDisplayKey = myUnusedSymbolKey;
      highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
    }
    else if (aClass instanceof PsiTypeParameter) {
      pattern = "type.parameter.is.not.used";
      highlightDisplayKey = myUnusedSymbolKey;
      highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
    }
    else {
      pattern = "class.is.not.used";
      highlightDisplayKey = myDeadCodeKey;
      highlightInfoType = myDeadCodeInfoType;
    }
    return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
  }

  public static boolean isClassUsed(@NotNull Project project,
                                    @NotNull PsiFile containingFile,
                                    @NotNull PsiClass aClass,
                                    @NotNull ProgressIndicator progress,
                                    @NotNull GlobalUsageHelper helper) {
    Boolean result = helper.unusedClassCache.get(aClass);
    if (result == null) {
      result = isReallyUsed(project, containingFile, aClass, progress, helper);
      helper.unusedClassCache.put(aClass, result);
    }
    return result;
  }

  private static boolean isReallyUsed(@NotNull Project project,
                                      @NotNull PsiFile containingFile,
                                      @NotNull PsiClass aClass,
                                      @NotNull ProgressIndicator progress,
                                      @NotNull GlobalUsageHelper helper) {
    if (isImplicitUsage(project, aClass, progress) || helper.isLocallyUsed(aClass)) return true;
    if (helper.isCurrentFileAlreadyChecked()) {
      if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
             aClass.getParent() instanceof PsiDeclarationStatement ||
             aClass instanceof PsiTypeParameter) return false;
    }
    return !weAreSureThereAreNoUsages(project, containingFile, aClass, progress, helper);
  }

  private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull final Project project,
                                                               @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
                                                               @NotNull final PsiNameIdentifierOwner aClass,
                                                               @NotNull final String element,
                                                               HighlightDisplayKey highlightDisplayKey,
                                                               @NotNull HighlightInfoType highlightInfoType,
                                                               @NotNull PsiElement identifier) {
    String symbolName = aClass.getName();
    String message = JavaErrorMessages.message(pattern, symbolName);
    final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
    QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(aClass), highlightDisplayKey);
    SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor<String>() {
      @Override
      public boolean process(final String annoName) {
        QuickFixAction
          .registerQuickFixAction(highlightInfo,
                                  QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, element));
        return true;
      }
    });
    return highlightInfo;
  }

  @Nullable
  private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
    // jsp include directive hack
    if (importStatement.isForeignFileImport()) return null;

    if (PsiUtilCore.hasErrorElementChild(importStatement)) return null;

    boolean isRedundant = myRefCountHolder.isRedundant(importStatement);
    if (!isRedundant && !(importStatement instanceof PsiImportStaticStatement)) {
      //check import from same package
      String packageName = ((PsiClassOwner)importStatement.getContainingFile()).getPackageName();
      PsiJavaCodeReferenceElement reference = importStatement.getImportReference();
      PsiElement resolved = reference == null ? null : reference.resolve();
      if (resolved instanceof PsiPackage) {
        isRedundant = packageName.equals(((PsiQualifiedNamedElement)resolved).getQualifiedName());
      }
      else if (resolved instanceof PsiClass && !importStatement.isOnDemand()) {
        String qName = ((PsiClass)resolved).getQualifiedName();
        if (qName != null) {
          String name = ((PomNamedTarget)resolved).getName();
          isRedundant = qName.equals(packageName + '.' + name);
        }
      }
    }

    if (isRedundant) {
      return registerRedundantImport(importStatement, unusedImportKey);
    }

    int entryIndex = JavaCodeStyleManager.getInstance(myProject).findEntryIndex(importStatement);
    if (entryIndex < myCurrentEntryIndex) {
      myHasMissortedImports = true;
    }
    myCurrentEntryIndex = entryIndex;

    return null;
  }

  private HighlightInfo registerRedundantImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
    String description = InspectionsBundle.message("unused.import.statement");
    HighlightInfo info =
      HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description)
        .create();

    QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(false), unusedImportKey);
    QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
    myHasRedundantImports = true;
    return info;
  }


  private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) {
    return method.isConstructor() &&
           method.getParameterList().getParametersCount() == 0 &&
           containingClass != null &&
           containingClass.getConstructors().length == 1;
  }
}
