From 0fb461e0703f1caa1e4316fd38777c2fa607db75 Mon Sep 17 00:00:00 2001
From: "Vladislav.Soroka"
Date: Thu, 24 Oct 2013 12:30:26 +0400
Subject: [PATCH] IDEA-115359 Gradle: generate apply plugin dsl code with
alt-insert
---
plugins/gradle/gradle.iml | 2 +
.../resources/i18n/GradleBundle.properties | 6 +-
.../i18n/GradleDocumentationBundle.properties | 8 +-
.../gradle/resources/icons/gradlePlugin.png | Bin 0 -> 862 bytes
plugins/gradle/src/META-INF/plugin.xml | 7 +-
plugins/gradle/src/icons/GradleIcons.java | 1 +
.../actions/AddGradleDslPluginAction.java | 90 ++++++++++
.../AddGradleDslPluginActionHandler.java | 165 ++++++++++++++++++
.../actions/GradleGenerateActionGroup.java | 28 +++
.../gradle/testData/testApplyPlugin.gradle | 1 +
.../testApplyPluginInsideClosure.gradle | 6 +
.../testApplyPluginInsideClosure_after.gradle | 6 +
.../testData/testApplyPlugin_after.gradle | 2 +
.../actions/AddGradleDslPluginActionTest.java | 63 +++++++
14 files changed, 379 insertions(+), 6 deletions(-)
create mode 100644 plugins/gradle/resources/icons/gradlePlugin.png
create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginAction.java
create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginActionHandler.java
create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/GradleGenerateActionGroup.java
create mode 100644 plugins/gradle/testData/testApplyPlugin.gradle
create mode 100644 plugins/gradle/testData/testApplyPluginInsideClosure.gradle
create mode 100644 plugins/gradle/testData/testApplyPluginInsideClosure_after.gradle
create mode 100644 plugins/gradle/testData/testApplyPlugin_after.gradle
create mode 100644 plugins/gradle/testSources/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginActionTest.java
diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml
index 925c1ab193ac..4dbad25039f1 100644
--- a/plugins/gradle/gradle.iml
+++ b/plugins/gradle/gradle.iml
@@ -6,6 +6,7 @@
+
@@ -176,6 +177,7 @@
+
diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties
index 67e121dfebea..26ed2bc1f194 100644
--- a/plugins/gradle/resources/i18n/GradleBundle.properties
+++ b/plugins/gradle/resources/i18n/GradleBundle.properties
@@ -22,4 +22,8 @@ gradle.action.open.script.description=Allows to open project file of the linked
gradle.notifications.use.distribution.with.sources=You can configure Gradle wrapper to use distribution with sources. \
It will provide IDE with Gradle API/DSL documentation.
gradle.notifications.hide.tip=Hide the tip
-gradle.notifications.apply.suggestion=Ok, apply suggestion!
\ No newline at end of file
+gradle.notifications.apply.suggestion=Ok, apply suggestion!
+
+gradle.codeInsight.action.apply_plugin.text=Add Gradle plugin
+gradle.codeInsight.action.apply_plugin.description=Add selected gradle plugin to the project
+gradle.codeInsight.action.apply_plugin.popup.title=Choose plugin
\ No newline at end of file
diff --git a/plugins/gradle/resources/i18n/GradleDocumentationBundle.properties b/plugins/gradle/resources/i18n/GradleDocumentationBundle.properties
index 857b741c2b60..1c185408c4dc 100644
--- a/plugins/gradle/resources/i18n/GradleDocumentationBundle.properties
+++ b/plugins/gradle/resources/i18n/GradleDocumentationBundle.properties
@@ -42,13 +42,13 @@ gradle.documentation.org.gradle.api.Project.apply.plugin.announce=\
gradle.documentation.org.gradle.api.Project.apply.plugin.build-announcements=\
Sends local announcements to your desktop about interesting events in the build lifecycle.
gradle.documentation.org.gradle.api.Project.apply.plugin.checkstyle=\
- Performs quality checks on your project's Java source files using\
+
Performs quality checks on your project's Java source files using \
Checkstyle \
and generates reports from these checks.\
gradle.documentation.org.gradle.api.Project.apply.plugin.codenarc=\
Performs quality checks on your project's Groovy source files using \
- CodeNarc\
+ CodeNarc \
and generates reports from these checks.\
gradle.documentation.org.gradle.api.Project.apply.plugin.eclipse=\
@@ -62,7 +62,7 @@ gradle.documentation.org.gradle.api.Project.apply.plugin.eclipse-wtp=\
gradle.documentation.org.gradle.api.Project.apply.plugin.findbugs=\
Performs quality checks on your project's Java source files using \
- FindBugs\
+ FindBugs \
and generates reports from these checks.\
gradle.documentation.org.gradle.api.Project.apply.plugin.idea=\
@@ -76,7 +76,7 @@ gradle.documentation.org.gradle.api.Project.apply.plugin.jdepend=\
gradle.documentation.org.gradle.api.Project.apply.plugin.pmd=\
Performs quality checks on your project's Java source files using \
- PMD\
+ PMD \
and generates reports from these checks.\
gradle.documentation.org.gradle.api.Project.apply.plugin.project-report=\
diff --git a/plugins/gradle/resources/icons/gradlePlugin.png b/plugins/gradle/resources/icons/gradlePlugin.png
new file mode 100644
index 0000000000000000000000000000000000000000..a342f298cc99cddd8e4e8703e451295096d70734
GIT binary patch
literal 862
zcmV-k1EKthP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0`o~kK~y+TV;~09
z*Vi*eL`3KT@%+fh$Y`JtBSZ!Z_z#p^Qfw)|u*^<#)v8ctkmj(kFnyrLjX(o7#Kgpa
z*s1{m0m4u%s9=A+JxcZG+CyFs-e
z0LaD_6?UeZn%&cPbop#uTkm$FIn%QtDl&W$P@`c~R8%MsoB*=B6B83fq1qszzMg?;
zX@!mP@*2m(8=5>W@9y=h+0pI0bybba+37`&k#SMsot1I3`)5MXhEt>o$|
z$JIOAJ^t+L_xZb{!|UeGF5lYi9bTK()Ht4RNq29LiHa!1uo(tcR@g^wZuasFTAUz}TD8M3NAlntr{6>Mp8E!+*%bQEL&5Fefr
z_g_qZ4
z1bo}j=JWqRpV$9`{a*iret4+poUmXJd)nUE?bG(eLA+2^Rb^CGRyH#~KVLm9EsYE4A`Tdywll$L^6uE<
zllH_;o3uMNYs%iZ%<22%rcB)*b7b0{Xj`xW_`u9FX{^)t#amC?7d?H--k6h<_rxBb
oejt9@^nFp*AUUWqN&o``0OFBP)-li65C8xG07*qoM6N<$f==V6o&W#<
literal 0
HcmV?d00001
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index fd2e97e78fa4..9cb03439b612 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -93,5 +93,10 @@
-
+
+
+
+
+
+
diff --git a/plugins/gradle/src/icons/GradleIcons.java b/plugins/gradle/src/icons/GradleIcons.java
index e12bafb0d0c2..4283f7207364 100644
--- a/plugins/gradle/src/icons/GradleIcons.java
+++ b/plugins/gradle/src/icons/GradleIcons.java
@@ -31,6 +31,7 @@ public class GradleIcons {
public static final Icon Gradle = load("/icons/gradle.png"); // 16x16
public static final Icon GradleImport = load("/icons/gradleImport.png"); // 16x16
public static final Icon GradleNavigate = load("/icons/gradleNavigate.png"); // 16x16
+ public static final Icon GradlePlugin = load("/icons/gradlePlugin.png"); // 16x16
public static final Icon GradleSync = load("/icons/gradleSync.png"); // 16x16
public static final Icon ToolWindowGradle = load("/icons/toolWindowGradle.png"); // 13x13
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginAction.java
new file mode 100644
index 000000000000..fa9bcf7a9064
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginAction.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.plugins.gradle.codeInsight.actions;
+
+import com.intellij.codeInsight.CodeInsightActionHandler;
+import com.intellij.codeInsight.actions.CodeInsightAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.KeyValue;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiCompiledElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import icons.GradleIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+import org.jetbrains.plugins.gradle.util.GradleDocumentationBundle;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 10/22/13
+ */
+public class AddGradleDslPluginAction extends CodeInsightAction {
+ public static final ThreadLocal TEST_THREAD_LOCAL = new ThreadLocal();
+ private final KeyValue[] myPlugins;
+
+ public AddGradleDslPluginAction() {
+ getTemplatePresentation().setDescription(GradleBundle.message("gradle.codeInsight.action.apply_plugin.description"));
+ getTemplatePresentation().setText(GradleBundle.message("gradle.codeInsight.action.apply_plugin.text"));
+ getTemplatePresentation().setIcon(GradleIcons.GradlePlugin);
+
+ final List plugins = StringUtil.split(
+ "java,groovy,idea,eclipse,scala,antlr,application,ear,jetty,maven,osgi,war,announce," +
+ "build-announcements,checkstyle,codenarc,eclipse-wtp,findbugs,jdepend,pmd,project-report,signing,sonar", ",");
+
+ myPlugins = new KeyValue[plugins.size()];
+ ContainerUtil.map2Array(plugins, myPlugins, new Function() {
+ @Override
+ public KeyValue fun(String o) {
+ return createPluginKey(o);
+ }
+ });
+ Arrays.sort(myPlugins, new Comparator() {
+ @Override
+ public int compare(KeyValue o1, KeyValue o2) {
+ return String.valueOf(o1.getKey()).compareTo(String.valueOf(o2.getKey()));
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ protected CodeInsightActionHandler getHandler() {
+ return new AddGradleDslPluginActionHandler(myPlugins);
+ }
+
+ @Override
+ protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
+ if (file instanceof PsiCompiledElement) return false;
+ if (!GroovyFileType.GROOVY_FILE_TYPE.equals(file.getFileType())) return false;
+ return !GradleConstants.SETTINGS_FILE_NAME.equals(file.getName()) && file.getName().endsWith(GradleConstants.EXTENSION);
+ }
+
+ @NotNull
+ private static KeyValue createPluginKey(@NotNull String pluginName) {
+ String description =
+ GradleDocumentationBundle.messageOrDefault("gradle.documentation.org.gradle.api.Project.apply.plugin." + pluginName, "");
+ return KeyValue.create(pluginName, description);
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginActionHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginActionHandler.java
new file mode 100644
index 000000000000..540fdc9a878e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/actions/AddGradleDslPluginActionHandler.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.plugins.gradle.codeInsight.actions;
+
+import com.intellij.codeInsight.CodeInsightActionHandler;
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.lookup.impl.LookupCellRenderer;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.KeyValue;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+* @author Vladislav.Soroka
+* @since 10/24/13
+*/
+class AddGradleDslPluginActionHandler implements CodeInsightActionHandler {
+ private final KeyValue[] myPlugins;
+ public AddGradleDslPluginActionHandler(KeyValue[] plugins) {
+ myPlugins = plugins;
+ }
+
+ @Override
+ public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile file) {
+ if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
+
+ final JBList list = new JBList(myPlugins);
+ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ list.setCellRenderer(new MyListCellRenderer());
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ final KeyValue selected = (KeyValue)list.getSelectedValue();
+ new WriteCommandAction.Simple(project, GradleBundle.message("gradle.codeInsight.action.apply_plugin.text"), file) {
+ @Override
+ protected void run() {
+ if (selected == null) return;
+ GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
+ GrStatement grStatement = factory.createStatementFromText(
+ String.format("apply plugin: '%s'", selected.getKey()), null);
+
+ PsiElement anchor = file.findElementAt(editor.getCaretModel().getOffset());
+ PsiElement currentElement = PsiTreeUtil.getParentOfType(anchor, GrClosableBlock.class, GroovyFile.class);
+ if (currentElement != null) {
+ currentElement.addAfter(grStatement, anchor);
+ }
+ else {
+ file.addAfter(grStatement, file.findElementAt(editor.getCaretModel().getOffset() - 1));
+ }
+ PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+ Document document = documentManager.getDocument(file);
+ if (document != null) {
+ documentManager.commitDocument(document);
+ }
+ }
+ }.execute();
+ }
+ };
+
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ KeyValue descriptor = ContainerUtil.find(myPlugins, new Condition() {
+ @Override
+ public boolean value(KeyValue value) {
+ return value.getKey().equals(AddGradleDslPluginAction.TEST_THREAD_LOCAL.get());
+ }
+ });
+ list.setSelectedValue(descriptor, false);
+ runnable.run();
+ }
+ else {
+ JBPopupFactory.getInstance().createListPopupBuilder(list)
+ .setTitle(GradleBundle.message("gradle.codeInsight.action.apply_plugin.popup.title"))
+ .setItemChoosenCallback(runnable)
+ .setFilteringEnabled(new Function