From 7639ed2a75107b0a5bdb9616942107e960abfcd5 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Thu, 24 Nov 2016 15:24:05 +0300 Subject: [PATCH] gradle: tasks resolve updated --- plugins/gradle/src/META-INF/plugin.xml | 1 - .../BaseGradleProjectResolverExtension.java | 7 +- .../resolve/GradleExtensionsContributor.kt | 199 ++++++++++---- .../resolve/GradleImplicitContributor.java | 242 ------------------ .../resolve/GradleTaskContributor.java | 143 ----------- .../plugins/gradle/service/resolve/util.kt | 13 +- .../settings/GradleExtensionsSettings.java | 53 +++- .../gradle/model/GradleExtensions.java | 3 + .../gradle/model/DefaultGradleExtension.java | 3 +- .../gradle/model/DefaultGradleExtensions.java | 11 + .../gradle/model/DefaultGradleProperty.java | 4 +- .../ProjectExtensionsDataBuilderImpl.groovy | 4 +- 12 files changed, 235 insertions(+), 448 deletions(-) delete mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java delete mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index ec7a2b492954..929aac917e50 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -59,7 +59,6 @@ - diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index 4668251c40a0..95d5abda4db3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -286,7 +286,12 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver GradleExtensions gradleExtensions = resolverCtx.getExtraProject(gradleModule, GradleExtensions.class); if (gradleExtensions != null) { - ideModule.createChild(GradleExtensionsDataService.KEY, new DefaultGradleExtensions(gradleExtensions)); + DefaultGradleExtensions extensions = new DefaultGradleExtensions(gradleExtensions); + ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class); + if (externalProject != null) { + extensions.getTasks().addAll(externalProject.getTasks().values()); + } + ideModule.createChild(GradleExtensionsDataService.KEY, extensions); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleExtensionsContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleExtensionsContributor.kt index ada9ba68fdd8..24e8983e0632 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleExtensionsContributor.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleExtensionsContributor.kt @@ -19,7 +19,10 @@ import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.util.Ref import com.intellij.patterns.ElementPattern +import com.intellij.patterns.PatternCondition import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.psi.CommonClassNames.JAVA_LANG_STRING +import com.intellij.psi.CommonClassNames.JAVA_UTIL_MAP import com.intellij.psi.PsiElement import com.intellij.psi.ResolveState import com.intellij.psi.scope.ElementClassHint @@ -27,17 +30,19 @@ import com.intellij.psi.scope.NameHint import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.util.ProcessingContext import groovy.lang.Closure -import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* import org.jetbrains.plugins.gradle.settings.GradleExtensionsSettings import org.jetbrains.plugins.groovy.dsl.holders.NonCodeMembersHolder.DOCUMENTATION +import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.COMPOSITE_LSHIFT_SIGN import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.* import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrMethodCallExpressionImpl import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable +import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.groovyBinaryExpression import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE @@ -82,7 +87,7 @@ class GradleExtensionsContributor : GradleMethodContextContributor { processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { - val extensionsData = Companion.getExtensionsFor(place) ?: return true + val extensionsData = getExtensionsFor(place) ?: return true val classHint = processor.getHint(ElementClassHint.KEY) val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint) val shouldProcessProperties = ResolveUtil.shouldProcessProperties(classHint) @@ -90,8 +95,136 @@ class GradleExtensionsContributor : GradleMethodContextContributor { val resolveScope = place.resolveScope val projectClass = psiManager.findClassWithCache(GRADLE_API_PROJECT, resolveScope) ?: return true val name = processor.getHint(NameHint.KEY)?.getName(state) - if (!shouldProcessMethods && shouldProcessProperties && place is GrReferenceExpression) { - if (!place.isQualified) { + + if (psiElement().inside(closureInLeftShiftMethod).accepts(place)) { + if (!GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_DEFAULT_TASK)) { + return false + } + } + + if (place.text == "task" && place is GrReferenceExpression && place.parent is GrApplicationStatement) { + if (GradleResolverUtil.isLShiftElement(place.parent?.children?.getOrNull(1)?.firstChild)) { + val taskContainerClass = psiManager.findClassWithCache(GRADLE_API_TASK_CONTAINER, resolveScope) ?: return true + val returnClass = psiManager.createTypeByFQClassName(GRADLE_API_TASK, resolveScope) ?: return true + val methodBuilder = GrLightMethodBuilder(place.manager, "create").apply { + containingClass = taskContainerClass + returnType = returnClass + } + methodBuilder.addParameter("task", GRADLE_API_TASK, true) + place.putUserData(RESOLVED_CODE, true) + if (!processor.execute(methodBuilder, state)) return false + } + } + + for (extension in extensionsData.extensions) { + if (!shouldProcessMethods && shouldProcessProperties && name == extension.name) { + val variable = GrLightVariable(place.manager, name, extension.rootTypeFqn, place) + place.putUserData(RESOLVED_CODE, true) + if (!processor.execute(variable, state)) return false + } + + if (shouldProcessMethods && name == extension.name) { + val returnClass = psiManager.createTypeByFQClassName(extension.rootTypeFqn, resolveScope) ?: continue + val methodBuilder = GrLightMethodBuilder(place.manager, extension.name).apply { + containingClass = projectClass + returnType = returnClass + } + methodBuilder.addParameter("configuration", GROOVY_LANG_CLOSURE, true) + place.putUserData(RESOLVED_CODE, true) + if (!processor.execute(methodBuilder, state)) return false + } + + val objectTypeFqn = extension.namedObjectTypeFqn?.let { if (it.isNotBlank()) it else null } + val extensionClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, extension.name)) + val placeText = place.text + val psiElement = psiElement() + if (psiElement.inside(extensionClosure).accepts(place)) { + if (shouldProcessMethods && !GradleResolverUtil.processDeclarations(psiManager, processor, state, place, extension.rootTypeFqn)) { + return false + } + + if (objectTypeFqn == null) break + if (place.parent is GrMethodCallExpression) { + val methodBuilder = GradleResolverUtil.createMethodWithClosure(placeText, objectTypeFqn, null, place, psiManager) + if (methodBuilder != null) { + place.putUserData(RESOLVED_CODE, true) + if (!processor.execute(methodBuilder, state)) return false + } + } + if (place.parent is GrReferenceExpression || psiElement.withTreeParent(extensionClosure).accepts(place)) { + val variable = GrLightVariable(place.manager, placeText, objectTypeFqn, place) + place.putUserData(RESOLVED_CODE, true) + if (!processor.execute(variable, state)) return false + } + } + + if (name == extension.name) break + } + + if (place.getUserData(RESOLVED_CODE).let { it == null || !it }) { + if (psiElement().withAncestor(2, groovyClosure().with(object : PatternCondition("withDelegatesToInfo") { + override fun accepts(t: GrClosableBlock, context: ProcessingContext?): Boolean { + return getDelegatesToInfo(t) != null + } + })).accepts(place)) { + return true + } + + var isTaskDeclaration = false + val parent = place.parent + val superParent = parent?.parent + if (superParent is GrCommandArgumentList && superParent.parent?.firstChild?.text == "task") { + isTaskDeclaration = true + } + + for (gradleTask in extensionsData.tasks) { + if (shouldProcessMethods && name == gradleTask.name) { + val returnClass = psiManager.createTypeByFQClassName( + if (isTaskDeclaration) JAVA_LANG_STRING else gradleTask.typeFqn, resolveScope) ?: continue + + val methodBuilder = GrLightMethodBuilder(place.manager, gradleTask.name).apply { + containingClass = projectClass + returnType = returnClass + if (parent is GrMethodCallExpressionImpl && parent.argumentList.namedArguments.isNotEmpty()) { + addParameter("args", JAVA_UTIL_MAP, true) + } + addParameter("configuration", GROOVY_LANG_CLOSURE, true) + } + if (!processor.execute(methodBuilder, state)) return false + break + } + + val taskClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, gradleTask.name)) + val psiElement = psiElement() + if (psiElement.inside(taskClosure).accepts(place)) { + if (shouldProcessMethods && !GradleResolverUtil.processDeclarations(psiManager, processor, state, place, gradleTask.typeFqn)) { + place.putUserData(RESOLVED_CODE, null) + return false + } + else { + place.putUserData(RESOLVED_CODE, null) + } + } + } + + if (!shouldProcessMethods && shouldProcessProperties && place is GrReferenceExpression && !place.isQualified) { + for (gradleTask in extensionsData.tasks) { + if (name == gradleTask.name) { + val docRef = Ref.create() + val variable = object : GrLightVariable(place.manager, name, gradleTask.typeFqn, place) { + override fun getNavigationElement(): PsiElement { + val navigationElement = super.getNavigationElement() + navigationElement.putUserData(DOCUMENTATION, docRef.get()) + return navigationElement + } + } + val doc = getDocumentation(gradleTask, variable) + docRef.set(doc) + place.putUserData(DOCUMENTATION, doc) + if (!processor.execute(variable, state)) return false + break + } + } for (gradleProp in extensionsData.properties) { if (name == gradleProp.name) { val docRef = Ref.create() @@ -106,50 +239,12 @@ class GradleExtensionsContributor : GradleMethodContextContributor { docRef.set(doc) place.putUserData(DOCUMENTATION, doc) if (!processor.execute(variable, state)) return false + break } } } } - for (extension in extensionsData.extensions) { - if (!shouldProcessMethods && shouldProcessProperties && name == extension.name) { - val variable = GrLightVariable(place.manager, name, extension.rootTypeFqn, place) - if (!processor.execute(variable, state)) return false - } - - if (shouldProcessMethods && name == extension.name) { - val returnClass = psiManager.createTypeByFQClassName(extension.rootTypeFqn, resolveScope) ?: continue - val methodBuilder = GrLightMethodBuilder(place.manager, extension.name).apply { - containingClass = projectClass - returnType = returnClass - } - methodBuilder.addParameter("configuration", GROOVY_LANG_CLOSURE, true) - if (!processor.execute(methodBuilder, state)) return false - } - - val objectTypeFqn = extension.namedObjectTypeFqn?.let { if (it.isNotBlank()) it else null } - val extensionClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, extension.name)) - val placeText = place.text - val psiElement = psiElement() - if (psiElement.inside(extensionClosure).accepts(place)) { - if (shouldProcessMethods && !GradleResolverUtil.processDeclarations(psiManager, processor, state, place, extension.rootTypeFqn)) { - return false - } - - if(objectTypeFqn == null) continue - if (place.parent is GrMethodCallExpression) { - val methodBuilder = GradleResolverUtil.createMethodWithClosure(placeText, objectTypeFqn, null, place, psiManager) - if (methodBuilder != null) { - if (!processor.execute(methodBuilder, state)) return false - } - } - if (place.parent is GrReferenceExpression || psiElement.withTreeParent(extensionClosure).accepts(place)) { - val variable = GrLightVariable(place.manager, placeText, objectTypeFqn, place) - if (!processor.execute(variable, state)) return false - } - - } - } return true } @@ -164,6 +259,13 @@ class GradleExtensionsContributor : GradleMethodContextContributor { buffer.append(" = " + gradleProp.value) } buffer.append("") + + if (gradleProp is GradleExtensionsSettings.GradleTask) { + if (!gradleProp.description.isNullOrBlank()) { + buffer.append(gradleProp.description) + } + } + if (hasInitializer) { buffer.append("Initial value has been got during last import") } @@ -171,6 +273,13 @@ class GradleExtensionsContributor : GradleMethodContextContributor { } companion object { + val closureInLeftShiftMethod = groovyClosure().withTreeParent( + groovyBinaryExpression().with(object : PatternCondition("leftShiftCondition") { + override fun accepts(t: GrBinaryExpression, context: ProcessingContext?): Boolean { + return t.operationTokenType == COMPOSITE_LSHIFT_SIGN + } + })) + fun getExtensionsFor(psiElement: PsiElement): GradleExtensionsSettings.GradleExtensionsData? { val project = psiElement.project val virtualFile = psiElement.containingFile?.originalFile?.virtualFile ?: return null diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java deleted file mode 100644 index e33cb63319fc..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * 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 org.jetbrains.plugins.gradle.service.resolve; - -import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; -import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.util.Couple; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiType; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.settings.GradleLocalSettings; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static com.intellij.util.containers.ContainerUtil.*; -import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.*; -import static org.jetbrains.plugins.gradle.service.resolve.GradleResolverUtil.canBeMethodOf; - -/** - * @author Vladislav.Soroka - * @since 9/24/13 - */ -public class GradleImplicitContributor implements GradleMethodContextContributor { - private final static Map BUILT_IN_TASKS = newHashMap( - Couple.of("assemble", GRADLE_API_DEFAULT_TASK), - Couple.of("build", GRADLE_API_DEFAULT_TASK), - Couple.of("buildDependents", GRADLE_API_DEFAULT_TASK), - Couple.of("buildNeeded", GRADLE_API_DEFAULT_TASK), - Couple.of("clean", GRADLE_API_TASKS_DELETE), - Couple.of("jar", GRADLE_API_TASKS_BUNDLING_JAR), - Couple.of("war", GRADLE_API_TASKS_BUNDLING_WAR), - Couple.of("classes", GRADLE_API_DEFAULT_TASK), - Couple.of("compileJava", GRADLE_API_TASKS_COMPILE_JAVA_COMPILE), - Couple.of("compileTestJava", GRADLE_API_DEFAULT_TASK), - Couple.of("processTestResources", GRADLE_API_DEFAULT_TASK), - Couple.of("testClasses", GRADLE_API_DEFAULT_TASK), - Couple.of("processResources", GRADLE_LANGUAGE_JVM_TASKS_PROCESS_RESOURCES), - Couple.of("setupBuild", GRADLE_BUILDSETUP_TASKS_SETUP_BUILD), - Couple.of("wrapper", GRADLE_API_TASKS_WRAPPER_WRAPPER), - Couple.of("javadoc", GRADLE_API_TASKS_JAVADOC_JAVADOC), - Couple.of("dependencies", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_REPORT_TASK), - Couple.of("dependencyInsight", GRADLE_API_TASKS_DIAGNOSTICS_DEPENDENCY_INSIGHT_REPORT_TASK), - Couple.of("projects", GRADLE_API_TASKS_DIAGNOSTICS_PROJECT_REPORT_TASK), - Couple.of("properties", GRADLE_API_TASKS_DIAGNOSTICS_PROPERTY_REPORT_TASK), - Couple.of("tasks", GRADLE_API_TASKS_DIAGNOSTICS_TASK_REPORT_TASK), - Couple.of("check", GRADLE_API_DEFAULT_TASK), - Couple.of("test", GRADLE_API_TASKS_TESTING_TEST), - Couple.of("uploadArchives", GRADLE_API_TASKS_UPLOAD) - ); - - @Override - public boolean process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - - //Module module = ProjectFileIndex.SERVICE.getInstance(place.getProject()).getModuleForFile(place.getContainingFile().getVirtualFile()); - //String rootProjectPath = ExternalSystemApiUtil.getExternalRootProjectPath(module); - //if (rootProjectPath != null) { - // ExternalProject externalProject = ExternalProjectDataCache.getInstance(place.getProject()) - // .getRootExternalProject(GradleConstants.SYSTEM_ID, new File(rootProjectPath)); - // if (externalProject != null) { - // Map properties = externalProject.getProperties(); - // - // if (true || ResolveUtil.shouldProcessProperties(processor.getHint(ElementClassHint.KEY))) { - // String placeText = place.getText(); - // ExternalProperty externalProperty = properties.get(placeText); - // if (externalProperty != null) { - // String type = externalProperty.getType() == null ? CommonClassNames.JAVA_LANG_OBJECT : externalProperty.getType(); - // //String name = processor.getHint(NameHint.KEY).getName(state); - // LightVariableBuilder variable = - // new LightVariableBuilder(place.getManager(), placeText, TypesUtil.createType(type, place), - // GroovyLanguage.INSTANCE); - // if (!processor.execute(variable, state)) return; - // //if (((String)name).let {it == null || it == "hostname" }) { - // //val variable = LightVariableBuilder>( - // // place.manager, "hostname", TypesUtil.createType(JAVA_LANG_STRING, place), GroovyLanguage) - // //if (!processor.execute(variable, state)) return - // //} - // } - // } - // } - //} - if (true) return true; - - - if (methodCallInfo.isEmpty()) { - checkForAvailableTasks(0, place.getText(), processor, state, place); - return true; - } - - final String methodCall = getLastItem(methodCallInfo); - if (methodCall == null) return true; - - if (!methodCall.equals("task")) { - if (methodCallInfo.size() == 1) { - checkForAvailableTasks(1, place.getText(), processor, state, place); - } - if (methodCallInfo.size() == 2) { - processAvailableTasks(methodCallInfo, methodCall, processor, state, place); - } - } - - if (methodCallInfo.size() >= 3 && Arrays.equals( - ar("dirs", "flatDir", "repositories"), methodCallInfo.subList(0, 3).toArray())) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, GRADLE_API_ARTIFACTS_REPOSITORIES_FLAT_DIRECTORY_ARTIFACT_REPOSITORY); - } - - if (methodCallInfo.size() == 3) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - if ("manifest".equals(methodCallInfo.get(1)) && "jar".equals(methodCallInfo.get(2))) { - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, GRADLE_API_JAVA_ARCHIVES_MANIFEST); - } - } - - if (place instanceof GrExpression && GradleResolverUtil.getTypeOf((GrExpression)place) == null) { - GrClosableBlock closableBlock = GradleResolverUtil.findParent(place, GrClosableBlock.class); - if (closableBlock != null && closableBlock.getParent() instanceof GrMethodCallExpression) { - PsiType psiType = GradleResolverUtil.getTypeOf(((GrExpression)closableBlock.getParent())); - if (psiType != null) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, TypesUtil.getQualifiedName(psiType)); - } - } - } - return true; - } - - public static void processImplicitDeclarations(@NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (!place.getText().equals("resources")) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_PROJECT); - } - } - - private static void checkForAvailableTasks(int level, - @Nullable String taskName, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (taskName == null) return; - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - PsiClass gradleApiProjectClass = psiManager.findClassWithCache(GRADLE_API_PROJECT, place.getResolveScope()); - if (canBeMethodOf(taskName, gradleApiProjectClass)) return; - if (canBeMethodOf(GroovyPropertyUtils.getGetterNameNonBoolean(taskName), gradleApiProjectClass)) return; - - final String className = BUILT_IN_TASKS.get(taskName); - if (className != null) { - if (level <= 1) { - GradleResolverUtil.addImplicitVariable(processor, state, place, className); - } - processTask(taskName, className, psiManager, processor, state, place); - return; - } - - Module module = ModuleUtilCore.findModuleForPsiElement(place); - if (module == null) return; - String path = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY); - GradleLocalSettings localSettings = GradleLocalSettings.getInstance(place.getProject()); - Collection taskPojos = localSettings.getAvailableTasks().get(path); - if (taskPojos == null) return; - - for (ExternalTaskPojo taskPojo : taskPojos) { - if (taskName.equals(taskPojo.getName())) { - processTask(taskName, GRADLE_API_TASK, psiManager, processor, state, place); - return; - } - } - } - - private static void processTask(@NotNull String taskName, - @NotNull String fqName, - @NotNull GroovyPsiManager psiManager, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (taskName.equals(place.getText())) { - if (!(place instanceof GrClosableBlock)) { - GrLightMethodBuilder methodBuilder = GradleResolverUtil.createMethodWithClosure(taskName, fqName, null, place, psiManager); - if (methodBuilder == null) return; - processor.execute(methodBuilder, state); - PsiClass contributorClass = - psiManager.findClassWithCache(fqName, place.getResolveScope()); - if (contributorClass == null) return; - //GradleResolverUtil.processMethod(taskName, contributorClass, processor, state, place); - } - } - else { - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, fqName); - } - } - - private static void processAvailableTasks(List methodCallInfo, @NotNull String taskName, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - PsiClass gradleApiProjectClass = psiManager.findClassWithCache(GRADLE_API_PROJECT, place.getResolveScope()); - if (canBeMethodOf(taskName, gradleApiProjectClass)) return; - if (canBeMethodOf(GroovyPropertyUtils.getGetterNameNonBoolean(taskName), gradleApiProjectClass)) return; - final String className = BUILT_IN_TASKS.get(taskName); - if (className != null) { - //GradleResolverUtil.processDeclarations( - // methodCallInfo.size() > 0 ? methodCallInfo.get(0) : null, psiManager, processor, state, place, className); - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java deleted file mode 100644 index 2121b4a55b4c..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; -import com.intellij.psi.impl.source.PsiImmediateClassType; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; - -import java.util.List; - -/** - * @author Vladislav.Soroka - * @since 9/9/13 - */ -public class GradleTaskContributor implements GradleMethodContextContributor { - - @Override - public boolean process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) return true; - - if (methodCallInfo.size() == 1) { - if(GradleResolverUtil.isLShiftElement(place.getParent())) { - GradleResolverUtil.addImplicitVariable(processor, state, place, GradleCommonClassNames.GRADLE_API_TASK); - } - } - else if (methodCallInfo.size() == 2) { - if (place.getParent().getParent() instanceof GrCommandArgumentList) { - // Assuming that the method call is addition of new task into the project. - processTaskAddition(methodCallInfo.get(0), GradleCommonClassNames.GRADLE_API_TASK_CONTAINER, processor, state, place); - } - else { - processTaskTypeParameter(processor, state, place); - } - - GradleImplicitContributor.processImplicitDeclarations(processor, state, place); - } - else if (methodCallInfo.size() >= 3) { - processTaskTypeParameter(processor, state, place); - GradleImplicitContributor.processImplicitDeclarations(processor, state, place); - } - return true; - } - - private static void processTaskTypeParameter(@NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - final int taskTypeParameterLevel = 3; - PsiElement psiElement = GradleResolverUtil.findParent(place, taskTypeParameterLevel); - - if (psiElement instanceof GrMethodCallExpression) { - GrMethodCallExpression callExpression = (GrMethodCallExpression)psiElement; - GrArgumentList argumentList = callExpression.getArgumentList(); - if (argumentList.getAllArguments().length > 0) { - for (GroovyPsiElement argument : argumentList.getAllArguments()) { - if (argument instanceof GrNamedArgument) { - GrNamedArgument namedArgument = (GrNamedArgument)argument; - GrExpression grExpression = namedArgument.getExpression(); - PsiType psiType = null; - if (grExpression != null) { - psiType = GradleResolverUtil.getTypeOf(grExpression); - } - if (psiType instanceof PsiImmediateClassType) { - PsiImmediateClassType immediateClassType = (PsiImmediateClassType)psiType; - for (PsiType type : immediateClassType.getParameters()) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, TypesUtil.getQualifiedName(type)); - } - } - } - } - } - else { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GradleCommonClassNames.GRADLE_API_TASK); - } - } - } - - private static void processTaskAddition(@NotNull String name, - @NotNull String handlerClass, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - PsiClass psiClass = psiManager.findClassWithCache(handlerClass, place.getResolveScope()); - if (psiClass == null) { - return; - } - - GrLightMethodBuilder builder = new GrLightMethodBuilder(place.getManager(), name); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getManager().getProject()); - PsiType type = new PsiArrayType(factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, place.getResolveScope())); - builder.addParameter(new GrLightParameter("taskInfo", type, builder)); - PsiClassType retType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, place.getResolveScope()); - builder.setReturnType(retType); - processor.execute(builder, state); - - GrMethodCall call = PsiTreeUtil.getParentOfType(place, GrMethodCall.class); - if (call == null) { - return; - } - GrArgumentList args = call.getArgumentList(); - - int argsCount = GradleResolverUtil.getGrMethodArumentsCount(args); - argsCount++; // Configuration name is delivered as an argument. - - for (PsiMethod method : psiClass.findMethodsByName("create", false)) { - if (method.getParameterList().getParametersCount() == argsCount) { - builder.setNavigationElement(method); - } - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt index 219caddcc565..d7bdcf02e099 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt @@ -16,21 +16,21 @@ package org.jetbrains.plugins.gradle.service.resolve import com.intellij.openapi.util.Key -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.ResolveState +import com.intellij.psi.* import com.intellij.psi.scope.BaseScopeProcessor import com.intellij.psi.scope.ElementClassHint import com.intellij.psi.scope.NameHint.KEY import com.intellij.psi.scope.PsiScopeProcessor import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns +import java.util.* /** * @author Vladislav.Soroka * @since 11/11/2016 */ +@JvmField val RESOLVED_CODE = Key.create("gradle.resolved") + fun processDeclarations(handlerClass: PsiClass, processor: PsiScopeProcessor, state: ResolveState, @@ -42,11 +42,16 @@ fun processDeclarations(handlerClass: PsiClass, if (!componentClass.processDeclarations(componentProcessor, state, null, place)) return false } else { + val processedSignatures = HashSet>() for (method in componentClass.findMethodsByName(name, true)) { + processedSignatures.add(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText })) + place.putUserData(RESOLVED_CODE, true) if (!componentProcessor.execute(method, state)) return false } for (prefix in arrayOf("add", "set")) { for (method in componentClass.findMethodsByName(prefix + name.capitalize(), true)) { + if (processedSignatures.contains(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))) continue + place.putUserData(RESOLVED_CODE, true) if (!componentProcessor.execute(method, state)) return false } } 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 72770173c7ad..d2b463e3f5fc 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java @@ -22,14 +22,18 @@ import com.intellij.openapi.components.Storage; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.CommonClassNames; import com.intellij.util.SmartList; import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.annotations.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter; +import org.jetbrains.plugins.gradle.model.ExternalTask; import org.jetbrains.plugins.gradle.model.GradleExtensions; import org.jetbrains.plugins.gradle.model.GradleProperty; +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames; import org.jetbrains.plugins.gradle.util.GradleConstants; import java.io.Serializable; @@ -99,6 +103,28 @@ public class GradleExtensionsSettings implements PersistentStateComponent"); + } + } + if(task.getGroup() != null) { + description.append("Task group: ").append(task.getGroup()).append(""); + } + + gradleTask.description = description.toString(); + extensionsData.tasks.add(gradleTask); + } gradleProject.extensions.put(entry.getKey(), extensionsData); } @@ -145,25 +171,38 @@ public class GradleExtensionsSettings implements PersistentStateComponent properties = new SmartList<>(); + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public List tasks = new SmartList<>(); } @Tag("ext") public static class GradleExtension { @Attribute("name") public String name; - @Attribute("rootTypeFqn") - public String rootTypeFqn; - @Attribute("namedObjectTypeFqn") + @Attribute("type") + public String rootTypeFqn = CommonClassNames.JAVA_LANG_OBJECT_SHORT; + @Attribute("objectType") public String namedObjectTypeFqn; } - @Tag("p") + + @Tag("prop") public static class GradleProp { @Attribute("name") public String name; - @Attribute("typeFqn") - public String typeFqn; + @Attribute("type") + public String typeFqn = CommonClassNames.JAVA_LANG_STRING; @Nullable - @Attribute("val") + @Text public String value; } + + @Tag("task") + public static class GradleTask extends GradleProp { + @Nullable + @Text + public String description; + @Attribute("type") + public String typeFqn = GradleCommonClassNames.GRADLE_API_DEFAULT_TASK; + } } diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleExtensions.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleExtensions.java index ab333756fb54..d67a26934a28 100644 --- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleExtensions.java +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleExtensions.java @@ -30,4 +30,7 @@ public interface GradleExtensions extends Serializable { @NotNull List getGradleProperties(); + + @NotNull + List getTasks(); } 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 ff7c4964ea0f..253ec29b6b77 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 @@ -27,7 +27,7 @@ public class DefaultGradleExtension extends DefaultGradleProperty implements Gra @Nullable private final String myNamedObjectTypeFqn; - public DefaultGradleExtension(@NotNull String name, @NotNull String typeFqn, @Nullable String namedObjectTypeFqn) { + public DefaultGradleExtension(@NotNull String name, @Nullable String typeFqn, @Nullable String namedObjectTypeFqn) { super(name, typeFqn, null); myNamedObjectTypeFqn = namedObjectTypeFqn; } @@ -35,6 +35,7 @@ public class DefaultGradleExtension extends DefaultGradleProperty implements Gra public DefaultGradleExtension(GradleExtension extension) { this(extension.getName(), extension.getTypeFqn(), extension.getNamedObjectTypeFqn()); } + @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 8be65ca0860b..6cf8f89d0030 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 @@ -30,6 +30,8 @@ public class DefaultGradleExtensions implements GradleExtensions { private final List myExtensions = new ArrayList(); @NotNull private final List myGradleProperties = new ArrayList(); + @NotNull + private List myTasks = new ArrayList(); public DefaultGradleExtensions() { } @@ -41,6 +43,9 @@ public class DefaultGradleExtensions implements GradleExtensions { for (GradleProperty property : extensions.getGradleProperties()) { myGradleProperties.add(new DefaultGradleProperty(property)); } + for (ExternalTask entry : extensions.getTasks()) { + myTasks.add(new DefaultExternalTask(entry)); + } } @NotNull @@ -54,4 +59,10 @@ public class DefaultGradleExtensions implements GradleExtensions { public List getGradleProperties() { return myGradleProperties; } + + @NotNull + @Override + public List getTasks() { + return myTasks; + } } 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 index c4ad996df746..4f31ab54d879 100644 --- 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 @@ -33,9 +33,9 @@ public class DefaultGradleProperty implements GradleProperty { @Nullable private final Serializable myValue; - public DefaultGradleProperty(@NotNull String name, @NotNull String typeFqn, @Nullable Serializable value) { + public DefaultGradleProperty(@NotNull String name, @Nullable String typeFqn, @Nullable Serializable value) { myName = name; - myRootTypeFqn = typeFqn; + myRootTypeFqn = typeFqn == null ? "Object" : typeFqn; myValue = value; } 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 e40df8a23421..bcb35277d41b 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 @@ -63,7 +63,7 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { result.extensions.add(new DefaultGradleExtension(name, rootTypeFqn, namedObjectTypeFqn)) } } - return result.extensions.isEmpty() && result.gradleProperties.isEmpty() ? null : result + return result } @Override @@ -75,7 +75,7 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { } static String getType(object) { - def clazz = object.getClass()?.canonicalName + def clazz = object?.getClass()?.canonicalName def decorIndex = clazz?.lastIndexOf('_Decorated') !decorIndex || decorIndex == -1 ? clazz : clazz.substring(0, decorIndex) }