| /* |
| * 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: 09-Jan-2007 |
| */ |
| package com.intellij.codeInspection.offlineViewer; |
| |
| import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; |
| import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager; |
| import com.intellij.codeInsight.intention.IntentionAction; |
| import com.intellij.codeInspection.*; |
| import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; |
| import com.intellij.codeInspection.ex.QuickFixWrapper; |
| import com.intellij.codeInspection.offline.OfflineProblemDescriptor; |
| import com.intellij.codeInspection.reference.RefElement; |
| import com.intellij.codeInspection.reference.RefEntity; |
| import com.intellij.codeInspection.ui.InspectionToolPresentation; |
| import com.intellij.codeInspection.ui.ProblemDescriptionNode; |
| import com.intellij.lang.Language; |
| import com.intellij.openapi.vcs.FileStatus; |
| import com.intellij.psi.*; |
| import com.intellij.psi.util.PsiUtilCore; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| public class OfflineProblemDescriptorNode extends ProblemDescriptionNode { |
| public OfflineProblemDescriptorNode(@NotNull OfflineProblemDescriptor descriptor, |
| @NotNull LocalInspectionToolWrapper toolWrapper, |
| @NotNull InspectionToolPresentation presentation) { |
| super(descriptor, toolWrapper, presentation); |
| } |
| |
| private static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) { |
| final FileViewProvider viewProvider = file.getViewProvider(); |
| final Set<PsiElement> result = new LinkedHashSet<PsiElement>(); |
| for (Language language : viewProvider.getLanguages()) { |
| final PsiFile psiRoot = viewProvider.getPsi(language); |
| if (HighlightingLevelManager.getInstance(file.getProject()).shouldInspect(psiRoot)) { |
| result.addAll(CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true)); |
| } |
| } |
| return PsiUtilCore.toPsiElementArray(result); |
| } |
| |
| @Override |
| @Nullable |
| public RefEntity getElement() { |
| if (userObject instanceof CommonProblemDescriptor) { |
| return myElement; |
| } |
| if (userObject == null) { |
| return null; |
| } |
| myElement = ((OfflineProblemDescriptor)userObject).getRefElement(myPresentation.getContext().getRefManager()); |
| return myElement; |
| } |
| |
| @Override |
| @Nullable |
| public CommonProblemDescriptor getDescriptor() { |
| if (userObject == null) return null; |
| if (userObject instanceof CommonProblemDescriptor) { |
| return (CommonProblemDescriptor)userObject; |
| } |
| |
| final InspectionManager inspectionManager = InspectionManager.getInstance(myPresentation.getContext().getProject()); |
| final OfflineProblemDescriptor offlineProblemDescriptor = (OfflineProblemDescriptor)userObject; |
| final RefEntity element = getElement(); |
| if (myToolWrapper instanceof LocalInspectionToolWrapper) { |
| if (element instanceof RefElement) { |
| final PsiElement psiElement = ((RefElement)element).getElement(); |
| if (psiElement != null) { |
| PsiFile containingFile = psiElement.getContainingFile(); |
| final ProblemsHolder holder = new ProblemsHolder(inspectionManager, containingFile, false); |
| final LocalInspectionTool localTool = ((LocalInspectionToolWrapper)myToolWrapper).getTool(); |
| final int startOffset = psiElement.getTextRange().getStartOffset(); |
| final int endOffset = psiElement.getTextRange().getEndOffset(); |
| LocalInspectionToolSession session = new LocalInspectionToolSession(containingFile, startOffset, endOffset); |
| final PsiElementVisitor visitor = localTool.buildVisitor(holder, false, session); |
| localTool.inspectionStarted(session, false); |
| final PsiElement[] elementsInRange = getElementsIntersectingRange(containingFile, |
| startOffset, |
| endOffset); |
| for (PsiElement el : elementsInRange) { |
| el.accept(visitor); |
| } |
| localTool.inspectionFinished(session, holder); |
| if (holder.hasResults()) { |
| final List<ProblemDescriptor> list = holder.getResults(); |
| final int idx = offlineProblemDescriptor.getProblemIndex(); |
| int curIdx = 0; |
| for (ProblemDescriptor descriptor : list) { |
| final PsiNamedElement member = localTool.getProblemElement(descriptor.getPsiElement()); |
| if (psiElement instanceof PsiFile || member != null && member.equals(psiElement)) { |
| if (curIdx == idx) { |
| setUserObject(descriptor); |
| return descriptor; |
| } |
| curIdx++; |
| } |
| } |
| } |
| } |
| } |
| setUserObject(null); |
| return null; |
| } |
| final List<String> hints = offlineProblemDescriptor.getHints(); |
| if (element instanceof RefElement) { |
| final PsiElement psiElement = ((RefElement)element).getElement(); |
| if (psiElement == null) return null; |
| ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(psiElement, offlineProblemDescriptor.getDescription(), |
| (LocalQuickFix)null, |
| ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); |
| final LocalQuickFix[] quickFixes = getFixes(descriptor, hints); |
| if (quickFixes != null) { |
| descriptor = inspectionManager.createProblemDescriptor(psiElement, offlineProblemDescriptor.getDescription(), false, quickFixes, |
| ProblemHighlightType.GENERIC_ERROR_OR_WARNING); |
| } |
| setUserObject(descriptor); |
| return descriptor; |
| } |
| CommonProblemDescriptor descriptor = |
| inspectionManager.createProblemDescriptor(offlineProblemDescriptor.getDescription(), (QuickFix)null); |
| final QuickFix[] quickFixes = getFixes(descriptor, hints); |
| if (quickFixes != null) { |
| descriptor = inspectionManager.createProblemDescriptor(offlineProblemDescriptor.getDescription(), quickFixes); |
| } |
| setUserObject(descriptor); |
| return descriptor; |
| } |
| |
| @Nullable |
| private LocalQuickFix[] getFixes(@NotNull CommonProblemDescriptor descriptor, List<String> hints) { |
| final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>(hints == null ? 1 : hints.size()); |
| if (hints == null) { |
| addFix(descriptor, fixes, null); |
| } |
| else { |
| for (String hint : hints) { |
| addFix(descriptor, fixes, hint); |
| } |
| } |
| return fixes.isEmpty() ? null : fixes.toArray(new LocalQuickFix[fixes.size()]); |
| } |
| |
| private void addFix(@NotNull CommonProblemDescriptor descriptor, final List<LocalQuickFix> fixes, String hint) { |
| final IntentionAction intentionAction = myPresentation.findQuickFixes(descriptor, hint); |
| if (intentionAction instanceof QuickFixWrapper) { |
| fixes.add(((QuickFixWrapper)intentionAction).getFix()); |
| } |
| } |
| |
| @Override |
| public boolean isValid() { |
| return getDescriptor() != null && super.isValid(); |
| } |
| |
| @Override |
| public FileStatus getNodeStatus() { |
| return FileStatus.NOT_CHANGED; |
| } |
| } |