--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+class AddExternalLibraryToDependenciesQuickFix extends OrderEntryFix {
+ private final Module myCurrentModule;
+ private final PsiReference myReference;
+ private final ExternalLibraryDescriptor myLibraryDescriptor;
+ private final String myQualifiedClassName;
+
+ public AddExternalLibraryToDependenciesQuickFix(@NotNull Module currentModule,
+ @NotNull ExternalLibraryDescriptor libraryDescriptor, @NotNull PsiReference reference,
+ @Nullable String qualifiedClassName) {
+ myCurrentModule = currentModule;
+ myReference = reference;
+ myLibraryDescriptor = libraryDescriptor;
+ myQualifiedClassName = qualifiedClassName;
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getText() {
+ return "Add '" + myLibraryDescriptor.getPresentableName() + "' to classpath";
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getText();
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return !project.isDisposed() && !myCurrentModule.isDisposed();
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ List<String> classesRoots = myLibraryDescriptor.locateLibraryClassesRoots(myCurrentModule);
+ if (!classesRoots.isEmpty()) {
+ String libraryName = classesRoots.size() > 1 ? myLibraryDescriptor.getPresentableName() : null;
+ addJarsToRootsAndImportClass(classesRoots, libraryName, myCurrentModule, editor, myReference,
+ myQualifiedClassName);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.openapi.module.Module;
+import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JetBrainsAnnotationsExternalLibraryResolver extends ExternalLibraryResolver {
+ private static final ExternalLibraryDescriptor ANNOTATIONS = new ExternalLibraryDescriptor("com.intellij", "annotations", null) {
+ @NotNull
+ @Override
+ public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+ return ContainerUtil.createMaybeSingletonList(OrderEntryFix.locateAnnotationsJar(contextModule));
+ }
+ };
+
+ @Nullable
+ @Override
+ public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+ if (AnnotationUtil.isJetbrainsAnnotation(shortClassName)) {
+ return new ExternalClassResolveResult("org.jetbrains.annotations." + shortClassName, ANNOTATIONS);
+ }
+ return null;
+ }
+}
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver.ExternalClassResolveResult;
import com.intellij.codeInsight.daemon.quickFix.MissingDependencyFixProvider;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@Nullable
public static List<LocalQuickFix> registerFixes(@NotNull final QuickFixActionRegistrar registrar, @NotNull final PsiReference reference) {
final PsiElement psiElement = reference.getElement();
- @NonNls final String referenceName = reference.getRangeInElement().substring(psiElement.getText());
+ @NonNls final String shortReferenceName = reference.getRangeInElement().substring(psiElement.getText());
Project project = psiElement.getProject();
PsiFile containingFile = psiElement.getContainingFile();
return providedFixes;
}
- if (isAnnotation(psiElement) && AnnotationUtil.isJetbrainsAnnotation(referenceName)) {
- @NonNls final String className = "org.jetbrains.annotations." + referenceName;
- PsiClass found =
- JavaPsiFacade.getInstance(project).findClass(className, currentModule.getModuleWithDependenciesAndLibrariesScope(true));
- if (found != null) return null; //no need to add junit to classpath
- final OrderEntryFix platformFix = new OrderEntryFix() {
- @Override
- @NotNull
- public String getText() {
- return QuickFixBundle.message("orderEntry.fix.add.annotations.jar.to.classpath");
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return !project.isDisposed() && !currentModule.isDisposed();
- }
-
- @Override
- public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- final String libraryPath = locateAnnotationsJar(currentModule);
- if (libraryPath != null) {
- new WriteCommandAction(project) {
- @Override
- protected void run(@NotNull final Result result) throws Throwable {
- addJarsToRootsAndImportClass(Collections.singletonList(libraryPath), null, currentModule, editor, reference,
- "org.jetbrains.annotations." + referenceName);
- }
- }.execute();
- }
- }
- });
- }
- };
-
- final OrderEntryFix providedFix = provideFix(new Function<MissingDependencyFixProvider, OrderEntryFix>() {
- @Override
- public OrderEntryFix fun(MissingDependencyFixProvider provider) {
- return provider.getJetbrainsAnnotationFix(reference, platformFix, currentModule);
+ List<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
+ JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ String fullReferenceText = reference.getCanonicalText();
+ for (ExternalLibraryResolver resolver : ExternalLibraryResolver.EP_NAME.getExtensions()) {
+ final ExternalClassResolveResult resolveResult = resolver.resolveClass(shortReferenceName, isReferenceToAnnotation(psiElement));
+ OrderEntryFix fix = null;
+ if (resolveResult != null && psiFacade.findClass(resolveResult.getQualifiedClassName(), currentModule.getModuleWithDependenciesAndLibrariesScope(true)) == null) {
+ fix = new AddExternalLibraryToDependenciesQuickFix(currentModule, resolveResult.getLibrary(), reference, resolveResult.getQualifiedClassName());
+ }
+ else if (!fullReferenceText.equals(shortReferenceName)) {
+ ExternalLibraryDescriptor descriptor = resolver.resolvePackage(fullReferenceText);
+ if (descriptor != null) {
+ fix = new AddExternalLibraryToDependenciesQuickFix(currentModule, descriptor, reference, null);
}
- });
- final OrderEntryFix fix = ObjectUtils.notNull(providedFix, platformFix);
-
- registrar.register(fix);
- return Collections.singletonList((LocalQuickFix)fix);
+ }
+ if (fix != null) {
+ registrar.register(fix);
+ result.add(fix);
+ }
+ }
+ if (!result.isEmpty()) {
+ return result;
}
- List<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
Set<Object> librariesToAdd = new THashSet<Object>();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(psiElement.getProject());
- PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(referenceName, GlobalSearchScope.allScope(project));
+ PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(shortReferenceName, GlobalSearchScope.allScope(project));
List<PsiClass> allowedDependencies = filterAllowedDependencies(psiElement, classes);
if (allowedDependencies.isEmpty()) {
return result;
return result;
}
- private static boolean isAnnotation(final PsiElement psiElement) {
- return PsiTreeUtil.getParentOfType(psiElement, PsiAnnotation.class) != null && PsiUtil.isLanguageLevel5OrHigher(psiElement);
+ private static ThreeState isReferenceToAnnotation(final PsiElement psiElement) {
+ if (!PsiUtil.isLanguageLevel5OrHigher(psiElement)) {
+ return ThreeState.NO;
+ }
+ if (PsiTreeUtil.getParentOfType(psiElement, PsiAnnotation.class) != null) {
+ return ThreeState.YES;
+ }
+ if (PsiTreeUtil.getParentOfType(psiElement, PsiImportStatement.class) != null) {
+ return ThreeState.UNSURE;
+ }
+ return ThreeState.NO;
}
/**
final String libraryName,
@NotNull final Module currentModule, @Nullable final Editor editor,
@Nullable final PsiReference reference,
- @NonNls final String className) {
+ @Nullable @NonNls final String className) {
addJarsToRoots(jarPaths, libraryName, currentModule, reference != null ? reference.getElement() : null);
final Project project = currentModule.getProject();
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.codeInsight.daemon.quickFix;
+
+import com.intellij.openapi.module.Module;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class ExternalLibraryDescriptor {
+ private final String myLibraryGroupId;
+ private final String myLibraryArtifactId;
+ private final String myMinVersion;
+
+ public ExternalLibraryDescriptor(@NotNull String libraryGroupId, @NotNull String libraryArtifactId, @Nullable String minVersion) {
+ myLibraryGroupId = libraryGroupId;
+ myLibraryArtifactId = libraryArtifactId;
+ myMinVersion = minVersion;
+ }
+
+ @NotNull
+ public String getLibraryGroupId() {
+ return myLibraryGroupId;
+ }
+
+ @NotNull
+ public String getLibraryArtifactId() {
+ return myLibraryArtifactId;
+ }
+
+ @Nullable
+ public String getMinVersion() {
+ return myMinVersion;
+ }
+
+ public String getPresentableName() {
+ return myLibraryArtifactId;
+ }
+
+ @NotNull
+ public abstract List<String> locateLibraryClassesRoots(@NotNull Module contextModule);
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.codeInsight.daemon.quickFix;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public abstract class ExternalLibraryResolver {
+ public static final ExtensionPointName<ExternalLibraryResolver> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.externalLibraryResolver");
+
+ @Nullable
+ public abstract ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation);
+
+ @Nullable
+ public ExternalLibraryDescriptor resolvePackage(@NotNull String packageName) {
+ return null;
+ }
+
+ public static class ExternalClassResolveResult {
+ private final String myQualifiedClassName;
+ private final ExternalLibraryDescriptor myLibrary;
+
+ public ExternalClassResolveResult(String qualifiedClassName,
+ ExternalLibraryDescriptor library) {
+ myQualifiedClassName = qualifiedClassName;
+ myLibrary = library;
+ }
+
+ public String getQualifiedClassName() {
+ return myQualifiedClassName;
+ }
+
+ public ExternalLibraryDescriptor getLibrary() {
+ return myLibrary;
+ }
+ }
+}
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
-import com.intellij.testIntegration.JavaTestFramework;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
return null;
}
- @Nullable
- public OrderEntryFix getJUnitFix(@NotNull PsiReference reference,
- @NotNull OrderEntryFix platformFix,
- @NotNull Module currentModule,
- @NotNull JavaTestFramework framework,
- @NotNull String className) {
- return null;
- }
-
- @Nullable
- public OrderEntryFix getJetbrainsAnnotationFix(@NotNull PsiReference reference,
- @NotNull OrderEntryFix platformFix,
- @NotNull Module currentModule) {
- return null;
- }
-
@Nullable
public OrderEntryFix getAddModuleDependencyFix(@NotNull PsiReference reference,
@NotNull OrderEntryFix platformFix,
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.codeInspection.concurrencyAnnotations;
+
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.openapi.module.Module;
+import com.intellij.util.PathUtil;
+import com.intellij.util.ThreeState;
+import net.jcip.annotations.GuardedBy;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JCiPExternalLibraryResolver extends ExternalLibraryResolver {
+ private static final ExternalLibraryDescriptor JDCIP_LIBRARY_DESCRIPTOR =
+ new ExternalLibraryDescriptor("net.jcip", "jcip-annotations", null) {
+ @NotNull
+ @Override
+ public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+ return Collections.singletonList(PathUtil.getJarPathForClass(GuardedBy.class));
+ }
+
+ @Override
+ public String getPresentableName() {
+ return "jcip-annotations.jar";
+ }
+ };
+
+ @Nullable
+ @Override
+ public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+ if (JCiPUtil.isJCiPAnnotation(shortClassName) && isAnnotation == ThreeState.YES) {
+ return new ExternalClassResolveResult("net.jcip.annotations." + shortClassName, JDCIP_LIBRARY_DESCRIPTOR);
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public ExternalLibraryDescriptor resolvePackage(@NotNull String packageName) {
+ if (packageName.equals("net.jcip.annotations")) {
+ return JDCIP_LIBRARY_DESCRIPTOR;
+ }
+ return null;
+ }
+}
+++ /dev/null
-/*
- * 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: 30-Jul-2007
- */
-package com.intellij.codeInspection.concurrencyAnnotations;
-
-import com.intellij.codeInsight.TargetElementUtil;
-import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.PathUtil;
-import net.jcip.annotations.GuardedBy;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collections;
-
-public class JCiPOrderEntryFix implements IntentionAction {
- private static final Logger LOG = Logger.getInstance("#" + JCiPOrderEntryFix.class.getName());
-
- @Override
- @NotNull
- public String getText() {
- return "Add jcip-annotations.jar to classpath";
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
- if (!(file instanceof PsiJavaFile)) return false;
-
- final PsiReference reference = TargetElementUtil.findReference(editor);
- if (!(reference instanceof PsiJavaCodeReferenceElement)) return false;
- if (reference.resolve() != null) return false;
- @NonNls final String referenceName = ((PsiJavaCodeReferenceElement)reference).getReferenceName();
- if (referenceName == null) return false;
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- final VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null) return false;
- if (fileIndex.getModuleForFile(virtualFile) == null) return false;
- if (!(((PsiJavaCodeReferenceElement)reference).getParent() instanceof PsiAnnotation &&
- PsiUtil.isLanguageLevel5OrHigher(((PsiJavaCodeReferenceElement)reference)))) return false;
- if (!JCiPUtil.isJCiPAnnotation(referenceName)) return false;
- return true;
- }
-
- @Override
- public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
- final PsiJavaCodeReferenceElement reference = (PsiJavaCodeReferenceElement)TargetElementUtil.findReference(editor);
- LOG.assertTrue(reference != null);
- String jarPath = PathUtil.getJarPathForClass(GuardedBy.class);
- final VirtualFile virtualFile = file.getVirtualFile();
- LOG.assertTrue(virtualFile != null);
- OrderEntryFix.addJarsToRootsAndImportClass(Collections.singletonList(jarPath), null, ModuleUtil.findModuleForFile(virtualFile, project), editor,
- reference, "net.jcip.annotations." + reference.getReferenceName());
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
-
-}
\ No newline at end of file
-// "Add JUnit to classpath" "true"
+// "Add 'JUnit3' to classpath" "true"
package x;
public class DoTest extends TestCase<caret>{
-// "Add JUnit to classpath" "true"
+// "Add 'JUnit4' to classpath" "true"
package x;
public class DoTest4 {
-// "Add JUnit to classpath" "true"
+// "Add 'JUnit4' to classpath" "true"
package x;
public class DoTest4junit {
<stacktrace.fold substring="at junit.framework.TestResult"/>
<programRunner implementation="com.intellij.execution.junit.JUnitDebuggerRunner"/>
- <codeInsight.unresolvedReferenceQuickFixProvider implementation="com.intellij.execution.junit.codeInsight.JUnitUnresolvedReferenceQuickFixProvider"/>
+ <codeInsight.externalLibraryResolver implementation="com.intellij.execution.junit.codeInsight.JUnitExternalLibraryResolver"/>
<junitListener implementation="com.intellij.junit4.JUnitTestDiscoveryListener"/>
<configurationType implementation="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationType"/>
<runConfigurationProducer implementation="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer"/>
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.intellij.execution.junit.codeInsight;
+
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.execution.junit.JUnit3Framework;
+import com.intellij.execution.junit.JUnit4Framework;
+import com.intellij.openapi.module.Module;
+import com.intellij.testIntegration.JavaTestFramework;
+import com.intellij.testIntegration.TestFramework;
+import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JUnitExternalLibraryResolver extends ExternalLibraryResolver {
+ public static final ExternalLibraryDescriptor JUNIT3 = createJUnitDescriptor("3", JUnit3Framework.class);
+ public static final ExternalLibraryDescriptor JUNIT4 = createJUnitDescriptor("4", JUnit4Framework.class);
+
+ @NotNull
+ private static ExternalLibraryDescriptor createJUnitDescriptor(final String version, final Class<? extends JavaTestFramework> frameworkClass) {
+ return new ExternalLibraryDescriptor("junit", "junit", version) {
+ @NotNull
+ @Override
+ public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+ return TestFramework.EXTENSION_NAME.findExtension(frameworkClass).getLibraryPaths();
+ }
+
+ @Override
+ public String getPresentableName() {
+ return "JUnit" + version;
+ }
+ };
+ }
+
+ private static Set<String> JUNIT4_ANNOTATIONS = ContainerUtil.set(
+ "Test", "Ignore", "RunWith", "Before", "BeforeClass", "After", "AfterClass"
+ );
+ @Nullable
+ @Override
+ public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+ if ("TestCase".equals(shortClassName)) {
+ return new ExternalClassResolveResult("junit.framework.TestCase", JUNIT3);
+ }
+ if (isAnnotation == ThreeState.YES && JUNIT4_ANNOTATIONS.contains(shortClassName)) {
+ return new ExternalClassResolveResult("org.junit." + shortClassName, JUNIT4);
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public ExternalLibraryDescriptor resolvePackage(@NotNull String packageName) {
+ if (packageName.equals("org.junit")) {
+ return JUNIT4;
+ }
+ if (packageName.equals("junit.framework")) {
+ return JUNIT3;
+ }
+ return null;
+ }
+}
+++ /dev/null
-/*
- * Copyright 2000-2015 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.
- */
-package com.intellij.execution.junit.codeInsight;
-
-import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
-import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInsight.daemon.impl.quickfix.MissingDependencyFixUtil;
-import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
-import com.intellij.codeInsight.daemon.quickFix.MissingDependencyFixProvider;
-import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
-import com.intellij.execution.junit.JUnit3Framework;
-import com.intellij.execution.junit.JUnit4Framework;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.testIntegration.JavaTestFramework;
-import com.intellij.testIntegration.TestFramework;
-import com.intellij.util.Function;
-import com.intellij.util.ObjectUtils;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-
-/**
- * @author nik
- */
-public class JUnitUnresolvedReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
- @Override
- public void registerFixes(@NotNull final PsiJavaCodeReferenceElement reference, @NotNull QuickFixActionRegistrar registrar) {
- final PsiElement psiElement = reference.getElement();
- @NonNls final String referenceName = reference.getRangeInElement().substring(psiElement.getText());
-
- Project project = psiElement.getProject();
- PsiFile containingFile = psiElement.getContainingFile();
- if (containingFile == null) return;
-
- final VirtualFile classVFile = containingFile.getVirtualFile();
- if (classVFile == null) return;
-
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- final Module currentModule = fileIndex.getModuleForFile(classVFile);
- if (currentModule == null) return;
-
- final JavaTestFramework framework;
- @NonNls final String className;
- if ("TestCase".equals(referenceName)) {
- framework = TestFramework.EXTENSION_NAME.findExtension(JUnit3Framework.class);
- className = "junit.framework.TestCase";
- }
- else if (PsiTreeUtil.getParentOfType(psiElement, PsiAnnotation.class) != null && isJunitAnnotationName(referenceName, psiElement)) {
- framework = TestFramework.EXTENSION_NAME.findExtension(JUnit4Framework.class);
- className = "org.junit." + referenceName;
- }
- else {
- return;
- }
-
- PsiClass found = JavaPsiFacade.getInstance(project).findClass(className, currentModule.getModuleWithDependenciesAndLibrariesScope(true));
- if (found != null) return;
-
- final OrderEntryFix platformFix = new OrderEntryFix() {
- @Override
- @NotNull
- public String getText() {
- return QuickFixBundle.message("orderEntry.fix.add.junit.jar.to.classpath");
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return !project.isDisposed() && !currentModule.isDisposed();
- }
-
- @Override
- public void invoke(@NotNull Project project, @Nullable Editor editor, PsiFile file) {
- List<String> jarPaths = framework.getLibraryPaths();
- String libraryName = jarPaths.size() == 1 ? null : framework.getName();
- addJarsToRootsAndImportClass(jarPaths, libraryName, currentModule, editor, reference, className);
- }
- };
-
- final OrderEntryFix providedFix = MissingDependencyFixUtil.provideFix(new Function<MissingDependencyFixProvider, OrderEntryFix>() {
- @Override
- public OrderEntryFix fun(MissingDependencyFixProvider provider) {
- return provider.getJUnitFix(reference, platformFix, currentModule, framework, className);
- }
- });
- final OrderEntryFix fix = ObjectUtils.notNull(providedFix, platformFix);
-
- registrar.register(fix);
- }
-
- private static boolean isJunitAnnotationName(@NonNls final String referenceName, @NotNull final PsiElement psiElement) {
- if ("Test".equals(referenceName) || "Ignore".equals(referenceName) || "RunWith".equals(referenceName) ||
- "Before".equals(referenceName) || "BeforeClass".equals(referenceName) ||
- "After".equals(referenceName) || "AfterClass".equals(referenceName)) {
- return true;
- }
- final PsiElement parent = psiElement.getParent();
- if (parent != null && !(parent instanceof PsiAnnotation)) {
- final PsiReference reference = parent.getReference();
- if (reference != null) {
- final String referenceText = parent.getText();
- if (isJunitAnnotationName(reference.getRangeInElement().substring(referenceText), parent)) {
- final int lastDot = referenceText.lastIndexOf('.');
- return lastDot > -1 && referenceText.substring(0, lastDot).equals("org.junit");
- }
- }
- }
- return false;
- }
-
- @NotNull
- @Override
- public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
- return PsiJavaCodeReferenceElement.class;
- }
-}
groupName="TestNG" enabledByDefault="true" level="ERROR"
implementationClass="com.theoryinpractice.testng.inspection.DataProviderReturnTypeInspection"/>
- <intentionAction>
- <className>com.theoryinpractice.testng.intention.TestNGOrderEntryFix</className>
- </intentionAction>
- <testFramework implementation="com.theoryinpractice.testng.TestNGFramework"/>
+ <testFramework implementation="com.theoryinpractice.testng.TestNGFramework"/>
+ <codeInsight.externalLibraryResolver implementation="com.theoryinpractice.testng.intention.TestNGExternalLibraryResolver"/>
<standardResource url="http://testng.org/testng-1.0.dtd" path="resources/standardSchemas/testng-1.0.dtd"/>
<overrideImplementsAnnotationsHandler implementation="com.theoryinpractice.testng.intention.OverrideImplementsTestNGAnnotationsHandler"/>
<forcedElementWeigher implementation="com.theoryinpractice.testng.TestNGForcedElementWeigher"/>
--- /dev/null
+/*
+ * Copyright 2000-2015 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.
+ */
+package com.theoryinpractice.testng.intention;
+
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
+import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.openapi.module.Module;
+import com.intellij.util.PathUtil;
+import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class TestNGExternalLibraryResolver extends ExternalLibraryResolver {
+ private static final Set<String> TEST_NG_ANNOTATIONS = ContainerUtil.set(
+ "Test", "BeforeClass", "BeforeGroups", "BeforeMethod", "BeforeSuite", "BeforeTest", "AfterClass", "AfterGroups", "AfterMethod",
+ "AfterSuite", "AfterTest", "Configuration"
+ );
+ private static final ExternalLibraryDescriptor TESTNG_DESCRIPTOR = new ExternalLibraryDescriptor("org.testng", "testng", null) {
+ @NotNull
+ @Override
+ public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+ return Collections.singletonList(PathUtil.getJarPathForClass(Test.class));
+ }
+ };
+
+ @Nullable
+ @Override
+ public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+ if (TEST_NG_ANNOTATIONS.contains(shortClassName)) {
+ return new ExternalClassResolveResult("org.testng.annotations." + shortClassName, TESTNG_DESCRIPTOR);
+ }
+ return null;
+ }
+}
+++ /dev/null
-/*
- * 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: 30-Jul-2007
- */
-package com.theoryinpractice.testng.intention;
-
-import com.intellij.codeInsight.TargetElementUtil;
-import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.lang.java.JavaLanguage;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.module.ModuleUtilCore;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.PathUtil;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.testng.annotations.Test;
-
-import java.util.Collections;
-
-public class TestNGOrderEntryFix implements IntentionAction {
- private static final Logger LOG = Logger.getInstance("#" + TestNGOrderEntryFix.class.getName());
-
- @NotNull
- public String getText() {
- return "Add testng.jar to classpath";
- }
-
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
- if (!(file instanceof PsiJavaFile)) return false;
- if (!file.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
-
- final PsiReference reference = TargetElementUtil.findReference(editor);
- if (!(reference instanceof PsiJavaCodeReferenceElement)) return false;
- if (reference.resolve() != null) return false;
- @NonNls final String referenceName = ((PsiJavaCodeReferenceElement)reference).getReferenceName();
- if (referenceName == null) return false;
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- final VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null) return false;
- if (fileIndex.getModuleForFile(virtualFile) == null) return false;
- if (!(((PsiJavaCodeReferenceElement)reference).getParent() instanceof PsiAnnotation &&
- PsiUtil.isLanguageLevel5OrHigher(((PsiJavaCodeReferenceElement)reference)))) return false;
- if (!isTestNGAnnotationName(referenceName)) return false;
- return true;
- }
-
- public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
- final PsiJavaCodeReferenceElement reference = (PsiJavaCodeReferenceElement)TargetElementUtil.findReference(editor);
- LOG.assertTrue(reference != null);
- String jarPath = PathUtil.getJarPathForClass(Test.class);
- final VirtualFile virtualFile = file.getVirtualFile();
- LOG.assertTrue(virtualFile != null);
- OrderEntryFix.addJarsToRootsAndImportClass(Collections.singletonList(jarPath), null, ModuleUtilCore.findModuleForFile(virtualFile, project),
- editor, reference, "org.testng.annotations." + reference.getReferenceName());
- }
-
- public boolean startInWriteAction() {
- return true;
- }
-
- private static boolean isTestNGAnnotationName(@NonNls final String referenceName) {
- return "Test".equals(referenceName) ||
- "BeforeClass".equals(referenceName) ||
- "BeforeGroups".equals(referenceName) ||
- "BeforeMethod".equals(referenceName) ||
- "BeforeSuite".equals(referenceName) ||
- "BeforeTest".equals(referenceName) ||
- "AfterClass".equals(referenceName) ||
- "AfterGroups".equals(referenceName) ||
- "AfterMethod".equals(referenceName) ||
- "AfterSuite".equals(referenceName) ||
- "AfterTest".equals(referenceName) ||
- "Configuration".equals(referenceName);
-
- }
-}
\ No newline at end of file
<!--suppress DeprecatedClassUsageInspection -->
<extensionPoint name="psi.clsCustomNavigationPolicy" interface="com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy"/>
+ <extensionPoint name="codeInsight.externalLibraryResolver" interface="com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver"/>
+
<extensionPoint name="vetoSPICondition" interface="com.intellij.openapi.util.Condition"/>
<extensionPoint name="hierarchy.referenceProcessor" interface="com.intellij.ide.hierarchy.call.CallReferenceProcessor"/>
</intentionAction>
- <intentionAction>
- <className>com.intellij.codeInspection.concurrencyAnnotations.JCiPOrderEntryFix</className>
- </intentionAction>
-
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.RemoveLiteralUnderscoresAction</className>
<category>Java/Numbers</category>
<generation.toStringClassFilter implementation="org.jetbrains.generate.tostring.GenerateToStringInterfaceFilter" order="last"/>
<codeInsight.unresolvedReferenceQuickFixProvider implementation="com.intellij.jarFinder.FindJarQuickFixProvider"/>
+ <codeInsight.externalLibraryResolver
+ implementation="com.intellij.codeInsight.daemon.impl.quickfix.JetBrainsAnnotationsExternalLibraryResolver"/>
+ <codeInsight.externalLibraryResolver implementation="com.intellij.codeInspection.concurrencyAnnotations.JCiPExternalLibraryResolver"/>
<refactoring.pullUpHelperFactory language="JAVA" implementationClass="com.intellij.refactoring.memberPullUp.JavaPullUpHelperFactory"/>
<hierarchy.referenceProcessor implementation="com.intellij.ide.hierarchy.call.JavaCallReferenceProcessor"/>