/* * SonarQube IntelliJ * Copyright (C) 2013-2014 SonarSource * dev@sonar.codehaus.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ package org.intellij.sonar.analysis; import java.util.List; import java.util.Optional; import java.util.Set; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import com.intellij.analysis.AnalysisScope; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInspection.GlobalInspectionContext; import com.intellij.codeInspection.ex.GlobalInspectionContextBase; import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.codeInspection.ex.Tools; import com.intellij.codeInspection.lang.GlobalInspectionContextExtension; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.TransactionGuard; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import org.intellij.sonar.DocumentChangeListener; import org.intellij.sonar.console.SonarConsole; import org.intellij.sonar.console.SonarToolWindowFactory; import org.intellij.sonar.index.IssuesByFileIndex; import org.intellij.sonar.persistence.ModuleSettings; import org.intellij.sonar.persistence.ProjectSettings; import org.intellij.sonar.persistence.Settings; import org.intellij.sonar.persistence.SonarConsoleSettings; import org.jetbrains.annotations.NotNull; public class SonarQubeInspectionContext implements GlobalInspectionContextExtension<SonarQubeInspectionContext> { private static final Key<SonarQubeInspectionContext> KEY = Key.create("SonarQubeInspectionContext"); @NotNull @Override public Key<SonarQubeInspectionContext> getID() { return KEY; } public static class EnrichedSettings { public Settings settings; public Project project; public Module module; public EnrichedSettings(Settings settings,Project project,Module module) { this.settings = settings; this.project = project; this.module = module; } } private boolean isInspectionToolEnabled(final String toolName,final GlobalInspectionContext context) { final InspectionProfileImpl currentProfile = ((GlobalInspectionContextBase) context).getCurrentProfile(); final Project project = context.getProject(); return currentProfile.getAllEnabledInspectionTools(project).stream() .map(Tools::getShortName) .anyMatch(toolName::equals); } @Override public void performPreRunActivities( @NotNull List<Tools> globalTools, @NotNull List<Tools> localTools, @NotNull final GlobalInspectionContext context ) { final boolean newIssuesGlobalInspectionToolEnabled = isInspectionToolEnabled( NewIssuesGlobalInspectionTool.class.getSimpleName(), context ); final boolean oldIssuesGlobalInspectionToolEnabled = isInspectionToolEnabled( OldIssuesGlobalInspectionTool.class.getSimpleName(), context ); if (!newIssuesGlobalInspectionToolEnabled && !oldIssuesGlobalInspectionToolEnabled) return; saveAllDocuments(); final Project project = context.getProject(); showSonarQubeToolWindowIfNeeded(project); SonarConsole.get(project).clear(); final Set<Module> modules = Sets.newHashSet(); final ImmutableList.Builder<PsiFile> filesBuilder = ImmutableList.builder(); context.getRefManager().getScope().accept( new PsiElementVisitor() { @Override public void visitFile(PsiFile psiFile) { filesBuilder.add(psiFile); final Module module = ModuleUtil.findModuleForPsiElement(psiFile); if (module != null) modules.add(module); } } ); final ImmutableList<PsiFile> psiFiles = filesBuilder.build(); IssuesByFileIndex.clearIndexFor(psiFiles); Set<EnrichedSettings> enrichedSettingsFromScope = Sets.newHashSet(); if (modules.isEmpty() || AnalysisScope.PROJECT == context.getRefManager().getScope().getScopeType()) { final Settings settings = ProjectSettings.getInstance(project).getState(); enrichedSettingsFromScope.add(new EnrichedSettings(settings,project,null)); } else { for (Module module : modules) { final Settings settings = ModuleSettings.getInstance(module).getState(); enrichedSettingsFromScope.add(new EnrichedSettings(settings,project,module)); } } if (oldIssuesGlobalInspectionToolEnabled) { for (final EnrichedSettings enrichedSettings : enrichedSettingsFromScope) { final Optional<DownloadIssuesTask> downloadTask = DownloadIssuesTask.from(enrichedSettings,psiFiles); downloadTask.ifPresent(DownloadIssuesTask::run); } } if (newIssuesGlobalInspectionToolEnabled) { for (final EnrichedSettings enrichedSettings : enrichedSettingsFromScope) { final Optional<RunLocalAnalysisScriptTask> scriptTask = RunLocalAnalysisScriptTask.from( enrichedSettings, psiFiles ); scriptTask.ifPresent(RunLocalAnalysisScriptTask::run); } } } private void saveAllDocuments() { TransactionGuard.getInstance().submitTransactionAndWait( () -> FileDocumentManager.getInstance().saveAllDocuments() ); } private void showSonarQubeToolWindowIfNeeded(final Project project) { if (SonarConsoleSettings.getInstance().isShowSonarConsoleOnAnalysis()) { ApplicationManager.getApplication().invokeLater( () -> { final ToolWindow toolWindow = ToolWindowManager.getInstance(project) .getToolWindow(SonarToolWindowFactory.TOOL_WINDOW_ID); toolWindow.show(null); } ); } } @Override public void performPostRunActivities( @NotNull List<InspectionToolWrapper> inspections, @NotNull GlobalInspectionContext context ) { DocumentChangeListener.CHANGED_FILES.clear(); final Project project = context.getProject(); // rerun external annotator and refresh highlighters in editor removeAllHighlighters(); DaemonCodeAnalyzer.getInstance(project).restart(); } private static void removeAllHighlighters() { ApplicationManager.getApplication().invokeLater( () -> { Editor[] allEditors = EditorFactory.getInstance().getAllEditors(); for (Editor editor : allEditors) { editor.getMarkupModel().removeAllHighlighters(); } } ); } @Override public void cleanup() { } }