From 35df08dd30251c730da039405c76ba85d9115582 Mon Sep 17 00:00:00 2001 From: Fuyao Zhao Date: Mon, 27 Jul 2015 13:48:13 -0700 Subject: Implement Gradle aware add jetBrains annotation fix. Change-Id: Ib72f605a6b5c07f9717bfa3abe1fb636a423fdef --- .../tests/gui/gradle/AddGradleDependencyTest.java | 11 +++ .../quickfix/AddGradleJetbrainsAnnotationFix.java | 102 +++++++++++++++++++++ ...AndroidUnresolvedReferenceQuickFixProvider.java | 12 +++ 3 files changed, 125 insertions(+) create mode 100644 android/src/com/android/tools/idea/quickfix/AddGradleJetbrainsAnnotationFix.java (limited to 'android') diff --git a/android/guiTestSrc/com/android/tools/idea/tests/gui/gradle/AddGradleDependencyTest.java b/android/guiTestSrc/com/android/tools/idea/tests/gui/gradle/AddGradleDependencyTest.java index 1a372e1ad80..1d786a5af81 100644 --- a/android/guiTestSrc/com/android/tools/idea/tests/gui/gradle/AddGradleDependencyTest.java +++ b/android/guiTestSrc/com/android/tools/idea/tests/gui/gradle/AddGradleDependencyTest.java @@ -150,6 +150,17 @@ public class AddGradleDependencyTest extends GuiTestCase { assertBuildFileContains(projectFrame, "app/build.gradle", "testCompile 'junit:junit:4.12'"); } + @Test @IdeGuiTest + public void testAddJetbrainsAnnotationDependency() throws IOException { + IdeFrameFixture projectFrame = importSimpleApplication(); + EditorFixture editor = projectFrame.getEditor(); + editor.open("app/src/main/java/google/simpleapplication/MyActivity.java"); + + typeImportAndInvokeAction(projectFrame, "onCreate(^Bundle savedInstanceState) {", "@Not^Null ", "Add 'annotations.jar' to classpath"); + + assertBuildFileContains(projectFrame, "app/build.gradle", "compile 'org.jetbrains:annotations:13.0'"); + } + private static void typeImportAndInvokeAction(@NotNull IdeFrameFixture projectFrame, @NotNull String lineToType, @NotNull String testImportStatement, @NotNull String intention) { EditorFixture editor = projectFrame.getEditor(); diff --git a/android/src/com/android/tools/idea/quickfix/AddGradleJetbrainsAnnotationFix.java b/android/src/com/android/tools/idea/quickfix/AddGradleJetbrainsAnnotationFix.java new file mode 100644 index 00000000000..877e4c56a65 --- /dev/null +++ b/android/src/com/android/tools/idea/quickfix/AddGradleJetbrainsAnnotationFix.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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.android.tools.idea.quickfix; + +import com.android.tools.idea.gradle.parser.Dependency; +import com.android.tools.idea.gradle.project.GradleProjectImporter; +import com.android.tools.idea.gradle.project.GradleSyncListener; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.actions.AddImportAction; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class AddGradleJetbrainsAnnotationFix extends GradleDependencyFix { + private final Module myCurrentModule; + private final PsiReference myReference; + private final String myClassName; + + public AddGradleJetbrainsAnnotationFix(@NotNull Module currentModule, @NotNull PsiReference reference, @NotNull String className) { + myCurrentModule = currentModule; + myReference = reference; + myClassName = className; + } + + @NotNull + @Override + public String getText() { + return QuickFixBundle.message("orderEntry.fix.add.annotations.jar.to.classpath"); + } + + @NotNull + @Override + public String getFamilyName() { + return getText(); + } + + @Override + public boolean isAvailable(@NotNull Project project, @Nullable Editor editor, @Nullable PsiFile file) { + return !project.isDisposed() && !myCurrentModule.isDisposed(); + } + + @Override + public void invoke(@NotNull final Project project, @Nullable final Editor editor, @Nullable PsiFile file) + throws IncorrectOperationException { + VirtualFile location = PsiUtilCore.getVirtualFile(myReference.getElement()); + boolean inTests = location != null && ModuleRootManager.getInstance(myCurrentModule).getFileIndex().isInTestSourceContent(location); + final Dependency dependency = new Dependency(getDependencyScope(myCurrentModule, inTests), Dependency.Type.EXTERNAL, + "org.jetbrains:annotations:13.0"); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new WriteCommandAction(project) { + @Override + protected void run(@NotNull final Result result) throws Throwable { + addDependency(myCurrentModule, dependency); + gradleSyncAndImportClass(myCurrentModule, editor, myReference, new Function>() { + @Override + public List apply(@Nullable Void input) { + PsiClass aClass = + JavaPsiFacade.getInstance(project).findClass(myClassName, GlobalSearchScope.moduleWithLibrariesScope(myCurrentModule)); + return aClass != null ? ImmutableList.of(aClass) : null; + } + }); + } + }.execute(); + } + }); + } +} diff --git a/android/src/com/android/tools/idea/quickfix/AndroidUnresolvedReferenceQuickFixProvider.java b/android/src/com/android/tools/idea/quickfix/AndroidUnresolvedReferenceQuickFixProvider.java index fdf50cea8ab..9c1f93547b1 100644 --- a/android/src/com/android/tools/idea/quickfix/AndroidUnresolvedReferenceQuickFixProvider.java +++ b/android/src/com/android/tools/idea/quickfix/AndroidUnresolvedReferenceQuickFixProvider.java @@ -18,6 +18,7 @@ package com.android.tools.idea.quickfix; import com.android.tools.idea.gradle.facet.AndroidGradleFacet; import com.android.tools.idea.gradle.parser.GradleBuildFile; import com.google.common.collect.Sets; +import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix; import com.intellij.codeInsight.intention.IntentionAction; @@ -105,6 +106,16 @@ public class AndroidUnresolvedReferenceQuickFixProvider extends UnresolvedRefere } } + // Check if it is a JetBrains annotation class reference. + if (isAnnotation(psiElement) && AnnotationUtil.isJetbrainsAnnotation(referenceName)) { + String className = "org.jetbrains.annotations." + referenceName; + PsiClass found = + JavaPsiFacade.getInstance(project).findClass(className, contextModule.getModuleWithDependenciesAndLibrariesScope(true)); + if (found == null) { + registrar.register(new AddGradleJetbrainsAnnotationFix(contextModule, reference, className)); + } + } + // Check if we could fix it by introduce gradle dependency. PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(referenceName, GlobalSearchScope.allScope(project)); List allowedDependencies = filterAllowedDependencies(psiElement, classes); @@ -114,6 +125,7 @@ public class AndroidUnresolvedReferenceQuickFixProvider extends UnresolvedRefere registrar.register(new AddGradleProjectDependencyFix(contextModule, classVFile, classes, reference)); } + // Check if we could fix it by introduce other library dependency. JavaPsiFacade facade = JavaPsiFacade.getInstance(psiElement.getProject()); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); -- cgit v1.2.3