// Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). // Licensed under the Apache License, Version 2.0 (see LICENSE). package com.twitter.intellij.pants.highlight; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightVisitor; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.twitter.intellij.pants.quickfix.PantsQuickFix; import com.twitter.intellij.pants.quickfix.PantsUnresolvedReferenceFixFinder; import com.twitter.intellij.pants.util.PantsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.scala.annotator.createFromUsage.CreateTypeDefinitionQuickFix; import org.jetbrains.plugins.scala.lang.psi.api.ScalaFile; import java.util.List; /** * A hack to extend fixes in Scala code. @fkorotkov asked JetBrains to add an extension point as we have for Java */ public class PantsScalaHighlightVisitor implements HighlightVisitor { private HighlightInfoHolder myHolder; @Override public boolean suitableForFile(@NotNull PsiFile file) { return PantsUtil.isPythonAvailable() && file instanceof ScalaFile; } @Override public void visit(@NotNull PsiElement element) { // FIXME: Re-enable quick fix for missing dependencies once it is functional again. // https://github.com/pantsbuild/intellij-pants-plugin/issues/280 if (!ApplicationManager.getApplication().isUnitTestMode()) { return; } final PsiFile containingFile = element.getContainingFile(); if (containingFile == null || DumbService.getInstance(myHolder.getProject()).isDumb()) { return; } int infoSize = myHolder.size(); for (int i = 0; i < infoSize; i++) { final HighlightInfo info = myHolder.get(i); tryToExtendInfo(info, containingFile); } } private void tryToExtendInfo(@NotNull HighlightInfo info, @NotNull PsiFile containingFile) { List<Pair<HighlightInfo.IntentionActionDescriptor, TextRange>> actionRanges = info.quickFixActionRanges; if (actionRanges == null) { return; } for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> actionAndRange : actionRanges) { final TextRange textRange = actionAndRange.getSecond(); final HighlightInfo.IntentionActionDescriptor actionDescriptor = actionAndRange.getFirst(); final IntentionAction action = actionDescriptor.getAction(); if (action instanceof CreateTypeDefinitionQuickFix) { final String className = textRange.substring(containingFile.getText()); final List<PantsQuickFix> missingDependencyFixes = PantsUnresolvedReferenceFixFinder.findMissingDependencies(className, containingFile); for (PantsQuickFix fix : missingDependencyFixes) { info.registerFix(fix, null, fix.getName(), textRange, null); } if (!missingDependencyFixes.isEmpty()) { // we should add only one fix per info return; } } } } @Override public boolean analyze( @NotNull PsiFile file, boolean updateWholeFile, @NotNull HighlightInfoHolder holder, @NotNull Runnable action ) { myHolder = holder; try { action.run(); } finally { myHolder = null; } return true; } @NotNull @Override public HighlightVisitor clone() { return new PantsScalaHighlightVisitor(); } }