package org.intellij.sonar.analysis;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import com.intellij.codeInsight.highlighting.TooltipLinkHandler;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import org.intellij.sonar.index.SonarIssue;
import org.intellij.sonar.persistence.IssuesByFileIndexProjectComponent;
import org.intellij.sonar.persistence.ModuleSettings;
import org.intellij.sonar.persistence.ProjectSettings;
import org.intellij.sonar.persistence.Settings;
import org.intellij.sonar.persistence.SonarRules;
import org.intellij.sonar.persistence.SonarServerConfig;
import org.intellij.sonar.persistence.SonarServers;
import org.intellij.sonar.sonarserver.Rule;
import org.intellij.sonar.sonarserver.SonarServer;
import org.intellij.sonar.util.SettingsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class IssueDescriptionLinkHandler extends TooltipLinkHandler {
@Nullable
@Override
public String getDescription(
@NotNull final String sonarIssueKey,
@NotNull final Editor editor
) {
// retrieve sonar issue data
final Project project = editor.getProject();
if (project == null || project.isDisposed()) return null;
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (psiFile == null) return null;
final Optional<IssuesByFileIndexProjectComponent> indexComponent =
IssuesByFileIndexProjectComponent.getInstance(project);
if (!indexComponent.isPresent()) return null;
final IssuesByFileIndexProjectComponent state = indexComponent.get().getState();
if (state == null) return null;
final Map<String,Set<SonarIssue>> index = state.getIndex();
final String path = psiFile.getVirtualFile().getPath();
final Set<SonarIssue> issues = index.get(path);
final Optional<SonarIssue> issue = issues.stream().filter(sonarIssue -> sonarIssueKey.equals(sonarIssue.getKey())).findFirst();
if (!issue.isPresent()) return null;
// try to get desc from already fetched rules
final Optional<SonarRules> sonarRules = SonarRules.getInstance(project);
if (sonarRules.isPresent()) {
final SonarRules sonarRulesState = sonarRules.get().getState();
if (sonarRulesState != null) {
final Rule rule = sonarRulesState.getSonarRulesByRuleKey().get(issue.get().getRuleKey());
if (rule != null && !rule.isEmpty())
return rule.getDesc();
}
}
// fetch and persist rule
Settings settings;
final Module moduleForFile = ModuleUtil.findModuleForFile(psiFile.getVirtualFile(),project);
if (moduleForFile != null) {
settings = ModuleSettings.getInstance(moduleForFile).getState();
settings = SettingsUtil.process(project,settings);
} else {
settings = ProjectSettings.getInstance(project).getState();
}
if (settings == null) return null;
final String serverName = settings.getServerName();
final Optional<SonarServerConfig> serverConfig = SonarServers.get(serverName);
if (!serverConfig.isPresent()) return null;
final SonarServer sonarServer = SonarServer.create(serverConfig.get());
final Rule rule = sonarServer.getRule(issue.get().getRuleKey());
// persist rule
if (sonarRules.isPresent()) {
final SonarRules sonarRulesState = sonarRules.get().getState();
if (sonarRulesState != null && !rule.isEmpty()) {
sonarRulesState.getSonarRulesByRuleKey().put(issue.get().getRuleKey(),rule);
}
}
return rule.getDesc();
}
}