diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index c192d4b1b266..ec7a2b492954 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -150,7 +150,7 @@ factoryClass="org.jetbrains.plugins.gradle.ui.GradleToolWindowFactory" conditionClass="org.jetbrains.plugins.gradle.ui.GradleToolWindowFactoryCondition"/> + implementationClass="org.jetbrains.plugins.gradle.documentation.GradleDocumentationProvider" order="first"/> () + val variable = object : GrLightVariable(place.manager, name, gradleProp.typeFqn, place) { + override fun getNavigationElement(): PsiElement { + val navigationElement = super.getNavigationElement() + navigationElement.putUserData(DOCUMENTATION, docRef.get()) + return navigationElement + } + } + val doc = getDocumentation(gradleProp, variable) + docRef.set(doc) + place.putUserData(DOCUMENTATION, doc) + if (!processor.execute(variable, state)) return false + } + } + } + } + for (extension in extensionsData.extensions) { if (!shouldProcessMethods && shouldProcessProperties && name == extension.name) { val variable = GrLightVariable(place.manager, name, extension.rootTypeFqn, place) @@ -129,6 +153,23 @@ class GradleExtensionsContributor : GradleMethodContextContributor { return true } + private fun getDocumentation(gradleProp: GradleExtensionsSettings.GradleProp, + lightVariable: GrLightVariable): String { + val buffer = StringBuilder() + buffer.append("
")
+    JavaDocInfoGenerator.generateType(buffer, lightVariable.type, lightVariable, true)
+    buffer.append(" " + gradleProp.name)
+    val hasInitializer = !gradleProp.value.isNullOrBlank()
+    if (hasInitializer) {
+      buffer.append(" = " + gradleProp.value)
+    }
+    buffer.append("
") + if (hasInitializer) { + buffer.append("Initial value has been got during last import") + } + return buffer.toString() + } + companion object { fun getExtensionsFor(psiElement: PsiElement): GradleExtensionsSettings.GradleExtensionsData? { val project = psiElement.project diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java index 850af275868a..72770173c7ad 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java @@ -29,8 +29,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter; import org.jetbrains.plugins.gradle.model.GradleExtensions; +import org.jetbrains.plugins.gradle.model.GradleProperty; import org.jetbrains.plugins.gradle.util.GradleConstants; +import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -79,13 +81,24 @@ public class GradleExtensionsSettings implements PersistentStateComponent entry : extensions.entrySet()) { GradleExtensionsData extensionsData = new GradleExtensionsData(); - for (org.jetbrains.plugins.gradle.model.GradleExtension extension : entry.getValue().list()) { + GradleExtensions gradleExtensions = entry.getValue(); + for (org.jetbrains.plugins.gradle.model.GradleExtension extension : gradleExtensions.getExtensions()) { GradleExtension gradleExtension = new GradleExtension(); gradleExtension.name = extension.getName(); - gradleExtension.rootTypeFqn = extension.getRootTypeFqn(); + gradleExtension.rootTypeFqn = extension.getTypeFqn(); gradleExtension.namedObjectTypeFqn = extension.getNamedObjectTypeFqn(); extensionsData.extensions.add(gradleExtension); } + for (GradleProperty property : gradleExtensions.getGradleProperties()) { + GradleProp gradleProp = new GradleProp(); + gradleProp.name = property.getName(); + gradleProp.typeFqn = property.getTypeFqn(); + Serializable value = property.getValue(); + if(value != null) { + gradleProp.value = value.toString(); + } + extensionsData.properties.add(gradleProp); + } gradleProject.extensions.put(entry.getKey(), extensionsData); } @@ -129,6 +142,9 @@ public class GradleExtensionsSettings implements PersistentStateComponent extensions = new SmartList<>(); + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public List properties = new SmartList<>(); } @Tag("ext") @@ -140,4 +156,14 @@ public class GradleExtensionsSettings implements PersistentStateComponent list(); + @NotNull + List getExtensions(); + + @NotNull + List getGradleProperties(); } diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java new file mode 100644 index 000000000000..d4ab863c664b --- /dev/null +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2016 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.model; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +/** + * @author Vladislav.Soroka + * @since 11/16/2016 + */ +public interface GradleProperty extends Serializable { + @NotNull + String getName(); + + @NotNull + String getTypeFqn(); + + @Nullable + Serializable getValue(); +} diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java index 0458595bb722..ff7c4964ea0f 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java @@ -22,37 +22,19 @@ import org.jetbrains.annotations.Nullable; * @author Vladislav.Soroka * @since 11/16/2016 */ -public class DefaultGradleExtension implements GradleExtension { +public class DefaultGradleExtension extends DefaultGradleProperty implements GradleExtension { private static final long serialVersionUID = 1L; - @NotNull - private final String myName; - @NotNull - private final String myRootTypeFqn; @Nullable private final String myNamedObjectTypeFqn; - public DefaultGradleExtension(@NotNull String name, @NotNull String rootTypeFqn, @Nullable String namedObjectTypeFqn) { - myName = name; - myRootTypeFqn = rootTypeFqn; + public DefaultGradleExtension(@NotNull String name, @NotNull String typeFqn, @Nullable String namedObjectTypeFqn) { + super(name, typeFqn, null); myNamedObjectTypeFqn = namedObjectTypeFqn; } public DefaultGradleExtension(GradleExtension extension) { - this(extension.getName(), extension.getRootTypeFqn(), extension.getNamedObjectTypeFqn()); + this(extension.getName(), extension.getTypeFqn(), extension.getNamedObjectTypeFqn()); } - - @NotNull - @Override - public String getName() { - return myName; - } - - @NotNull - @Override - public String getRootTypeFqn() { - return myRootTypeFqn; - } - @Nullable @Override public String getNamedObjectTypeFqn() { diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java index b75679b4da59..8be65ca0860b 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java @@ -15,6 +15,8 @@ */ package org.jetbrains.plugins.gradle.model; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.List; @@ -22,20 +24,34 @@ import java.util.List; * @author Vladislav.Soroka * @since 11/16/2016 */ -public class DefaultGradleExtensions extends ArrayList implements GradleExtensions { +public class DefaultGradleExtensions implements GradleExtensions { private static final long serialVersionUID = 1L; + @NotNull + private final List myExtensions = new ArrayList(); + @NotNull + private final List myGradleProperties = new ArrayList(); public DefaultGradleExtensions() { } public DefaultGradleExtensions(GradleExtensions extensions) { - for (GradleExtension extension : extensions.list()) { - add(new DefaultGradleExtension(extension)); + for (GradleExtension extension : extensions.getExtensions()) { + myExtensions.add(new DefaultGradleExtension(extension)); } + for (GradleProperty property : extensions.getGradleProperties()) { + myGradleProperties.add(new DefaultGradleProperty(property)); + } } + @NotNull @Override - public List list() { - return this; + public List getExtensions() { + return myExtensions; + } + + @NotNull + @Override + public List getGradleProperties() { + return myGradleProperties; } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java new file mode 100644 index 000000000000..c4ad996df746 --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2016 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.model; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +/** + * @author Vladislav.Soroka + * @since 11/16/2016 + */ +public class DefaultGradleProperty implements GradleProperty { + private static final long serialVersionUID = 1L; + @NotNull + private final String myName; + @NotNull + private final String myRootTypeFqn; + @Nullable + private final Serializable myValue; + + public DefaultGradleProperty(@NotNull String name, @NotNull String typeFqn, @Nullable Serializable value) { + myName = name; + myRootTypeFqn = typeFqn; + myValue = value; + } + + public DefaultGradleProperty(GradleProperty property) { + this(property.getName(), property.getTypeFqn(), property.getValue()); + } + + @NotNull + @Override + public String getName() { + return myName; + } + + @NotNull + @Override + public String getTypeFqn() { + return myRootTypeFqn; + } + + @Nullable + @Override + public Serializable getValue() { + return myValue; + } +} diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy index 8165b4343e69..f6293adad1e5 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy @@ -138,10 +138,7 @@ class ExternalProjectBuilderImpl implements ModelBuilderService { externalTask.QName = task.name externalTask.description = task.description externalTask.group = task.group ?: "other" - - def clazzName = task.class.canonicalName - def prefixIndex = clazzName.lastIndexOf('_Decorated') - externalTask.type = prefixIndex == -1 ? clazzName : clazzName.substring(0, prefixIndex) + externalTask.type = ProjectExtensionsDataBuilderImpl.getType(task) result.put(externalTask.name, externalTask) } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy index 61928914517d..e40df8a23421 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy @@ -22,6 +22,7 @@ import org.gradle.api.internal.plugins.DefaultConvention import org.jetbrains.annotations.NotNull import org.jetbrains.plugins.gradle.model.DefaultGradleExtension import org.jetbrains.plugins.gradle.model.DefaultGradleExtensions +import org.jetbrains.plugins.gradle.model.DefaultGradleProperty import org.jetbrains.plugins.gradle.model.GradleExtensions import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder import org.jetbrains.plugins.gradle.tooling.ModelBuilderService @@ -41,27 +42,28 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { Object buildAll(String modelName, Project project) { DefaultGradleExtensions result = new DefaultGradleExtensions() def conventions = project.extensions as DefaultConvention + conventions.extraProperties.properties.each { name, value -> + String typeFqn = getType(value) + result.gradleProperties.add(new DefaultGradleProperty( + name, typeFqn, value.toString())) + } + for (it in conventions.findAll()) { def convention = it as DefaultConvention convention.asMap.each { name, value -> if(name == 'idea') return - def rootClazz = value.getClass()?.canonicalName - def rootDecorIndex = rootClazz?.lastIndexOf('_Decorated') - def rootTypeFqn = !rootDecorIndex || rootDecorIndex == -1 ? rootClazz : rootClazz.substring(0, rootDecorIndex) + def rootTypeFqn = getType(value) def namedObjectTypeFqn = null as String if (value instanceof NamedDomainObjectCollection) { - NamedDomainObjectCollection objectCollection = (NamedDomainObjectCollection)value + def objectCollection = (NamedDomainObjectCollection)value if(!objectCollection.isEmpty()) { - def namedObjectClazz = objectCollection.first().getClass()?.canonicalName - def namedObjectDecorIndex = namedObjectClazz?.lastIndexOf('_Decorated') - namedObjectTypeFqn = !namedObjectDecorIndex || namedObjectDecorIndex == -1 ? namedObjectClazz : - namedObjectClazz.substring(0, namedObjectDecorIndex) + namedObjectTypeFqn = getType(objectCollection.first()) } } - result.add(new DefaultGradleExtension(name, rootTypeFqn, namedObjectTypeFqn)) + result.extensions.add(new DefaultGradleExtension(name, rootTypeFqn, namedObjectTypeFqn)) } } - return result.isEmpty() ? null : result + return result.extensions.isEmpty() && result.gradleProperties.isEmpty() ? null : result } @Override @@ -71,4 +73,10 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { ).withDescription( "Unable to resolve some context data of gradle scripts. Some codeInsight features inside *.gradle files can be unavailable.") } + + static String getType(object) { + def clazz = object.getClass()?.canonicalName + def decorIndex = clazz?.lastIndexOf('_Decorated') + !decorIndex || decorIndex == -1 ? clazz : clazz.substring(0, decorIndex) + } }