package com.intellij.lang.javascript.flex; import com.intellij.codeHighlighting.Pass; import com.intellij.codeHighlighting.TextEditorHighlightingPass; import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory; import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.lang.ImportOptimizer; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.AnnotationSession; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.lang.javascript.JSBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.inspections.JSUnusedLocalSymbolsInspection; import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSExpressionCodeFragment; import com.intellij.lang.javascript.psi.JSFile; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.psi.ecmal4.JSImportStatement; import com.intellij.lang.javascript.validation.ActionScriptUnusedImportsHelper; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.PsiCompiledElement; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlFile; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * @author Maxim.Mossienko * Date: Jul 29, 2008 * Time: 10:23:03 PM */ public class ActionScriptUnusedImportsPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory { public ActionScriptUnusedImportsPassFactory(Project project, TextEditorHighlightingPassRegistrar registrar) { super(project); registrar.registerTextEditorHighlightingPass( this, new int[]{Pass.UPDATE_ALL}, null, true, -1 ); } public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) { if (file instanceof XmlFile && JavaScriptSupportLoader.isFlexMxmFile(file) || file instanceof JSFile && !(file instanceof PsiCompiledElement) && file.getLanguage().is(JavaScriptSupportLoader.ECMA_SCRIPT_L4) ) { final HighlightDisplayKey key = HighlightDisplayKey.find(JSUnusedLocalSymbolsInspection.SHORT_NAME); if (InspectionProjectProfileManager.getInstance(file.getProject()).getCurrentProfile().isToolEnabled(key, file)) { return new ActionScriptUnusedImportsHighlightingPass(file, editor); } } return null; } private static IntentionAction createOptimizeImportsIntention() { return new IntentionAction() { @NotNull public String getText() { return JSBundle.message("javascript.fix.optimize.imports"); } @NotNull public String getFamilyName() { return getText(); } public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return true; } public void invoke(@NotNull final Project project, Editor editor, PsiFile file) { ImportOptimizer optimizer = new ECMAScriptImportOptimizer(); final Runnable runnable = optimizer.processFile(file); ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { CommandProcessor.getInstance().executeCommand(project, runnable, getFamilyName(), this); } }); } public boolean startInWriteAction() { return true; } }; } @NotNull public String getComponentName() { return "ActionScript.UnusedImportReporter"; } public static class ActionScriptUnusedImportsHighlightingPass extends TextEditorHighlightingPass { private Collection<JSImportStatement> importStatements; private Collection<JSReferenceExpression> fqnsToReplaceWithShortName; private final PsiFile myFile; public ActionScriptUnusedImportsHighlightingPass(final PsiFile file, final Editor editor) { super(file.getProject(), editor.getDocument(), true); myFile = file; } public void doCollectInformation(@NotNull final ProgressIndicator progress) { if (myFile instanceof JSExpressionCodeFragment) { importStatements = Collections.emptyList(); fqnsToReplaceWithShortName = Collections.emptyList(); } else { final ActionScriptUnusedImportsHelper.Results results = ActionScriptUnusedImportsHelper.getUnusedImports(myFile); importStatements = results.unusedImports; fqnsToReplaceWithShortName = results.fqnsToReplaceWithShortName; } } public void doApplyInformationToEditor() { UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), getHighlights(), getColorsScheme(), getId()); } private List<HighlightInfo> getHighlights() { final AnnotationHolder annotationHolder = new AnnotationHolderImpl(new AnnotationSession(myFile)); final List<HighlightInfo> infos = new ArrayList<>(importStatements.size() + fqnsToReplaceWithShortName.size()); IntentionAction action = createOptimizeImportsIntention(); createHighlights(importStatements, annotationHolder, action, JSBundle.message("javascript.validation.unused.import"), infos, ProblemHighlightType.LIKE_UNUSED_SYMBOL); createHighlights(fqnsToReplaceWithShortName, annotationHolder, action, JSBundle.message("javascript.validation.fqn.to.replace.with.import"), infos, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); return infos; } private static void createHighlights(Collection<? extends JSElement> elements, AnnotationHolder annotationHolder, IntentionAction action, String message, List<HighlightInfo> result, @NotNull ProblemHighlightType type) { for (JSElement unusedImport : elements) { TextRange range = InjectedLanguageManager.getInstance(unusedImport.getProject()).injectedToHost(unusedImport, unusedImport.getTextRange()); if (range.isEmpty()) continue; final Annotation annotation = annotationHolder.createWarningAnnotation(range, message); annotation.setHighlightType(type); annotation.registerFix(action); result.add(HighlightInfo.fromAnnotation(annotation)); } } } }