diff --git a/plugins/gradle/src/META-INF/gradle-maven-integration.xml b/plugins/gradle/src/META-INF/gradle-maven-integration.xml index 2cd12be2fd38..ca045a5fa847 100644 --- a/plugins/gradle/src/META-INF/gradle-maven-integration.xml +++ b/plugins/gradle/src/META-INF/gradle-maven-integration.xml @@ -21,7 +21,7 @@ - + + diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index 93266441ebdc..c6c51716bb61 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -58,19 +58,16 @@ - - + + - - - - + @@ -153,6 +150,8 @@ implementationClass="org.jetbrains.plugins.gradle.documentation.GradleDocumentationProvider"/> + - + @@ -170,10 +169,7 @@ - - - - + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.java deleted file mode 100644 index 9c8eca1dac2f..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.java +++ /dev/null @@ -1,85 +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.psi.*; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; -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 8/30/13 - */ -public class GradleArtifactsContributor implements GradleMethodContextContributor { - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty() || methodCallInfo.size() < 2 || !"artifacts".equals(methodCallInfo.get(1))) { - return; - } - final String text = place.getText(); - if (!methodCallInfo.contains(text) && place instanceof GrReferenceExpressionImpl) { - GradleResolverUtil.addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, Object.class.getName()); - return; - } - - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GradleCommonClassNames.GRADLE_API_ARTIFACT_HANDLER); - PsiClass contributorClass = psiManager.findClassWithCache(GradleCommonClassNames.GRADLE_API_ARTIFACT_HANDLER, place.getResolveScope()); - if (contributorClass != null) { - // assuming that the method call is addition of an artifact to the given configuration. - processAtrifactAddition(methodCallInfo.get(0), contributorClass, processor, state, place); - } - } - - private static void processAtrifactAddition(@NotNull String gradleConfigurationName, - @NotNull PsiClass artifactHandlerClass, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - GrLightMethodBuilder builder = new GrLightMethodBuilder(place.getManager(), gradleConfigurationName); - PsiClassType type = PsiType.getJavaLangObject(place.getManager(), place.getResolveScope()); - builder.addParameter(new GrLightParameter("artifactInfo", type, builder)); - 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 : artifactHandlerClass.findMethodsByName("add", false)) { - if (method.getParameterList().getParametersCount() == argsCount) { - builder.setNavigationElement(method); - } - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt new file mode 100644 index 000000000000..a2dabe81ec5c --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt @@ -0,0 +1,103 @@ +/* + * 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.patterns.PsiJavaPatterns.psiElement +import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT +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 com.intellij.psi.util.PsiTreeUtil +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_ARTIFACT_HANDLER +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression +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 org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * @author Vladislav.Soroka + * * + * @since 8/30/13 + */ +class GradleArtifactsContributor : GradleMethodContextContributor { + + companion object { + val artifactsClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "artifacts")) + } + + override fun process(methodCallInfo: List, + processor: PsiScopeProcessor, + state: ResolveState, + place: PsiElement): Boolean { + val psiManager = GroovyPsiManager.getInstance(place.project) + val methodName = if (methodCallInfo.isNotEmpty()) methodCallInfo[0] else null + if (methodName != null && place is GrReferenceExpression && psiElement().inside(artifactsClosure).accepts(place)) { + val text = place.text + if (!methodCallInfo.contains(text) && place is GrReferenceExpression) { + GradleResolverUtil.addImplicitVariable(processor, state, place, JAVA_LANG_OBJECT) + return false + } + + if (!GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_ARTIFACT_HANDLER)) return false + val contributorClass = psiManager.findClassWithCache(GRADLE_API_ARTIFACT_HANDLER, place.resolveScope) + if (contributorClass != null) { + // assuming that the method call is addition of an artifact to the given configuration. + if (!processArtifactAddition(methodCallInfo[0], contributorClass, processor, state, place)) return false + } + } + return true + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (artifactsClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_ARTIFACT_HANDLER, closure), Closure.DELEGATE_FIRST) + } + return null + } + + private fun processArtifactAddition(gradleConfigurationName: String, + artifactHandlerClass: PsiClass, + processor: PsiScopeProcessor, + state: ResolveState, + place: PsiElement): Boolean { + val call = PsiTreeUtil.getParentOfType(place, GrMethodCall::class.java) ?: return true + val builder = GrLightMethodBuilder(place.manager, gradleConfigurationName) + val type = PsiType.getJavaLangObject(place.manager, place.resolveScope) + builder.addParameter(GrLightParameter("artifactInfo", type, builder)) + val args = call.argumentList + + var argsCount = GradleResolverUtil.getGrMethodArumentsCount(args) + argsCount++ // Configuration name is delivered as an argument. + + for (method in artifactHandlerClass.findMethodsByName("add", false)) { + if (method.parameterList.parametersCount == argsCount) { + builder.navigationElement = method + } + } + + return processor.execute(builder, state) + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.java deleted file mode 100644 index 735c92eac24c..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.service.resolve; - -/** - * @author Vladislav.Soroka - * @since 8/30/13 - */ -public class GradleBuildScriptContributor extends GradleSimpleContributor { - public GradleBuildScriptContributor() { - super("buildscript", GradleCommonClassNames.GRADLE_API_SCRIPT_HANDLER); - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.kt new file mode 100644 index 000000000000..3c211c8937b4 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleBuildScriptContributor.kt @@ -0,0 +1,41 @@ +/* + * 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.service.resolve + +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil +import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * @author Vladislav.Soroka + * @since 8/30/13 + */ +class GradleBuildScriptContributor : GradleMethodContextContributor { + companion object { + val buildscriptClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "buildscript")) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (buildscriptClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_SCRIPT_HANDLER, closure), Closure.DELEGATE_FIRST) + } + return null + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java index 0162e5451d51..55eed83302ca 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java @@ -24,11 +24,18 @@ import org.jetbrains.annotations.NonNls; public final class GradleCommonClassNames { @NonNls public static final String GRADLE_API_SCRIPT = "org.gradle.api.Script"; @NonNls public static final String GRADLE_API_PROJECT = "org.gradle.api.Project"; + @NonNls public static final String GRADLE_API_BASE_PLUGIN_CONVENTION = "org.gradle.api.plugins.BasePluginConvention"; + @NonNls public static final String GRADLE_API_JAVA_PLUGIN_CONVENTION = "org.gradle.api.plugins.JavaPluginConvention"; + @NonNls public static final String GRADLE_API_APPLICATION_PLUGIN_CONVENTION = "org.gradle.api.plugins.ApplicationPluginConvention"; + @NonNls public static final String GRADLE_API_WAR_CONVENTION = "org.gradle.api.plugins.WarPluginConvention"; @NonNls public static final String GRADLE_API_CONFIGURATION_CONTAINER = "org.gradle.api.artifacts.ConfigurationContainer"; + @NonNls public static final String GRADLE_API_DEPENDENCY_SUBSTITUTIONS = "org.gradle.api.artifacts.DependencySubstitutions"; + @NonNls public static final String GRADLE_API_RESOLUTION_STRATEGY = "org.gradle.api.artifacts.ResolutionStrategy"; @NonNls public static final String GRADLE_API_CONFIGURATION = "org.gradle.api.artifacts.Configuration"; @NonNls public static final String GRADLE_API_ARTIFACT_HANDLER = "org.gradle.api.artifacts.dsl.ArtifactHandler"; @NonNls public static final String GRADLE_API_DEPENDENCY_HANDLER = "org.gradle.api.artifacts.dsl.DependencyHandler"; @NonNls public static final String GRADLE_API_ARTIFACTS_EXTERNAL_MODULE_DEPENDENCY = "org.gradle.api.artifacts.ExternalModuleDependency"; + @NonNls public static final String GRADLE_API_ARTIFACTS_CLIENT_MODULE_DEPENDENCY = "org.gradle.api.artifacts.ClientModule"; @NonNls public static final String GRADLE_API_ARTIFACTS_MODULE_DEPENDENCY = "org.gradle.api.artifacts.ModuleDependency"; @NonNls public static final String GRADLE_API_ARTIFACTS_DEPENDENCY_ARTIFACT = "org.gradle.api.artifacts.DependencyArtifact"; @NonNls public static final String GRADLE_API_REPOSITORY_HANDLER = "org.gradle.api.artifacts.dsl.RepositoryHandler"; @@ -59,6 +66,7 @@ public final class GradleCommonClassNames { @NonNls public static final String GRADLE_BUILDSETUP_TASKS_SETUP_BUILD = "org.gradle.buildsetup.tasks.SetupBuild"; @NonNls public static final String GRADLE_API_TASK_CONTAINER = "org.gradle.api.tasks.TaskContainer"; @NonNls public static final String GRADLE_API_JAVA_ARCHIVES_MANIFEST = "org.gradle.api.java.archives.Manifest"; + @NonNls public static final String GRADLE_API_DOMAIN_OBJECT_COLLECTION = "org.gradle.api.DomainObjectCollection"; @NonNls public static final String GRADLE_API_NAMED_DOMAIN_OBJECT_COLLECTION = "org.gradle.api.NamedDomainObjectCollection"; @NonNls public static final String GRADLE_API_ARTIFACTS_REPOSITORIES_MAVEN_ARTIFACT_REPOSITORY = "org.gradle.api.artifacts.repositories.MavenArtifactRepository"; @NonNls public static final String GRADLE_API_ARTIFACTS_MAVEN_MAVEN_DEPLOYER = "org.gradle.api.artifacts.maven.MavenDeployer"; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java deleted file mode 100644 index 9cbe87c6ae72..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; - -import java.util.List; - -/** - * @author Vladislav.Soroka - * @since 8/29/13 - */ -public class GradleConfigurationsContributor implements GradleMethodContextContributor { - - private static final String CONFIGURATIONS = "configurations"; - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) { - return; - } - final String methodCall = methodCallInfo.get(0); - - String contributorClass = null; - if (methodCallInfo.size() == 1) { - if (methodCall.startsWith(CONFIGURATIONS + '.')) { - contributorClass = GradleCommonClassNames.GRADLE_API_CONFIGURATION; - } - else if (CONFIGURATIONS.equals(methodCall)) { - contributorClass = GradleCommonClassNames.GRADLE_API_CONFIGURATION_CONTAINER; - if (place instanceof GrReferenceExpressionImpl) { - GradleResolverUtil - .addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, GradleCommonClassNames.GRADLE_API_CONFIGURATION); - return; - } - } - } - else if (methodCallInfo.size() == 2) { - if (CONFIGURATIONS.equals(methodCallInfo.get(1))) { - contributorClass = GradleCommonClassNames.GRADLE_API_CONFIGURATION_CONTAINER; - if (place instanceof GrReferenceExpressionImpl) { - GradleResolverUtil - .addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, GradleCommonClassNames.GRADLE_API_CONFIGURATION); - return; - } - } - } - if (contributorClass != null) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, contributorClass); - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.kt new file mode 100644 index 000000000000..79fa41a9522e --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.kt @@ -0,0 +1,107 @@ +/* + * 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.service.resolve + +import com.intellij.patterns.ElementPattern +import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.ProcessingContext +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList +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.impl.GroovyPsiManager +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable +import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getContainingCall +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.resolveActualCall + +/** + * @author Vladislav.Soroka + * * + * @since 8/29/13 + */ +class GradleConfigurationsContributor : GradleMethodContextContributor { + + companion object { + val configurationsClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "configurations")) + val configurationReference = object : ElementPattern { + override fun getCondition() = null + override fun accepts(o: Any?) = false + override fun accepts(o: Any?, context: ProcessingContext): Boolean { + return o is GrExpression && o.type?.equalsToText(GRADLE_API_CONFIGURATION) ?: false + } + } + val configurationClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_DOMAIN_OBJECT_COLLECTION, "all")) + val dependencySubstitutionClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_RESOLUTION_STRATEGY, "dependencySubstitution")) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (configurationsClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_CONFIGURATION_CONTAINER, closure), Closure.DELEGATE_FIRST) + } + + // // resolve configuration ref closure: + // configurations.myConfiguration { + // extendsFrom(configurations.testCompile) + // } + if (psiElement().withParent(psiElement().withFirstChild(configurationReference)).accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_CONFIGURATION, closure), Closure.DELEGATE_FIRST) + } + + if (dependencySubstitutionClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_DEPENDENCY_SUBSTITUTIONS, closure), Closure.DELEGATE_FIRST) + } + return null + } + + + override fun process(methodCallInfo: List, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { + val psiManager = GroovyPsiManager.getInstance(place.project) + val psiElement = psiElement() + + if (psiElement.inside(configurationClosure).accepts(place)) { + val closure = PsiTreeUtil.getParentOfType(place, GrClosableBlock::class.java) ?: return true + val call = getContainingCall(closure) ?: return true + val result = resolveActualCall(call) + for (psiType in result.substitutor.substitutionMap.values) { + if (psiType.equalsToText(GRADLE_API_CONFIGURATION)) { + if (!GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_CONFIGURATION)) return false + return false + } + } + } + + if (psiElement.inside(configurationsClosure).accepts(place)) { + val name = place.text + if (place.parent is GrReferenceExpression || place.parent is GrArgumentList || + psiElement.withTreeParent(configurationsClosure).accepts(place)) { + val variable = GrLightVariable(place.manager, name, GRADLE_API_CONFIGURATION, place) + if (!processor.execute(variable, state)) return false + } + } + + return true + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java deleted file mode 100644 index 50e448a0b5ce..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2000-2014 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.psi.*; -import com.intellij.psi.impl.light.LightElement; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrImplicitVariableImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; -import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor; - -import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_CONFIGURATION; -import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_CONFIGURATION_CONTAINER; -import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE; - -/** - * @author Vladislav.Soroka - * @since 8/30/13 - */ -public class GradleConfigurationsNonCodeMembersContributor extends NonCodeMembersContributor { - - private static final String METHOD_GET_BY_NAME = "getByName"; - - @Override - public void processDynamicElements(@NotNull PsiType qualifierType, - @Nullable PsiClass aClass, - @NotNull PsiScopeProcessor processor, - @NotNull PsiElement place, - @NotNull ResolveState state) { - if (aClass == null) { - return; - } - - if (!GRADLE_API_CONFIGURATION_CONTAINER.equals(aClass.getQualifiedName())) { - return; - } - - // Assuming that the method call is equivalent to calling ConfigurationContainer.getByName() - processConfigurationAddition(aClass, processor, state, place); - } - - @SuppressWarnings("MethodMayBeStatic") - private void processConfigurationAddition(@NotNull PsiClass dependencyHandlerClass, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - - GrMethodCall call = PsiTreeUtil.getParentOfType(place, GrMethodCall.class); - if (call == null) { - // TODO replace with groovy implicit method - if(place instanceof GrReferenceExpressionImpl) { - GrReferenceExpressionImpl expression = (GrReferenceExpressionImpl)place; - String expr = expression.getCanonicalText(); - GrImplicitVariableImpl myPsi = new GrImplicitVariableImpl(place.getManager(), expr, GRADLE_API_CONFIGURATION, place); - processor.execute(myPsi, state); - setNavigation(myPsi, dependencyHandlerClass, METHOD_GET_BY_NAME, 1); - } - return; - } - GrArgumentList args = call.getArgumentList(); - int argsCount = GradleResolverUtil.getGrMethodArumentsCount(args); - - argsCount++; // Configuration name is delivered as an argument. - - if (argsCount == 1) { - GrLightMethodBuilder builder = new GrLightMethodBuilder(place.getManager(), METHOD_GET_BY_NAME); - PsiClassType type = PsiType.getJavaLangObject(place.getManager(), place.getResolveScope()); - builder.addParameter(new GrLightParameter("s", type, builder)); - processor.execute(builder, state); - - argsCount++; // we need method with extra argument of type Closure. - setNavigation(builder, dependencyHandlerClass, METHOD_GET_BY_NAME, argsCount); - } - } - - @SuppressWarnings("MethodMayBeStatic") - private void setNavigation(LightElement element, PsiClass dependencyHandlerClass, String methodName, int parametersCount) { - for (PsiMethod method : dependencyHandlerClass.findMethodsByName(methodName, false)) { - int methodParameterCount = method.getParameterList().getParametersCount(); - if (methodParameterCount == parametersCount && - method.getParameterList().getParameters()[methodParameterCount - 1].getType().equalsToText(GROOVY_LANG_CLOSURE)) { - element.setNavigationElement(method); - } - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDelegatesToProvider.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDelegatesToProvider.kt new file mode 100644 index 000000000000..276b42ec6ec5 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDelegatesToProvider.kt @@ -0,0 +1,40 @@ +/* + * 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.io.FileUtilRt +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.GrDelegatesToProvider + +/** + * @author Vladislav.Soroka + * @since 11/8/2016 + */ +class GradleDelegatesToProvider() : GrDelegatesToProvider { + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + val file = closure.containingFile + if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)) return null + + for (contributor in GradleMethodContextContributor.EP_NAME.extensions) { + val delegatesToInfo = contributor.getDelegatesToInfo(closure) + if (delegatesToInfo != null) return delegatesToInfo + } + return null + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java deleted file mode 100644 index e3070d5cb8d6..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; - -import java.util.List; - -/** - * @author Denis Zhdanov - * @since 8/14/13 12:58 PM - */ -public class GradleDependenciesContributor implements GradleMethodContextContributor { - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) return; - - String methodCall = ContainerUtil.getLastItem(methodCallInfo); - if (methodCall == null) return; - - if (!StringUtil.equals(methodCall, "dependencies")) return; - - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - if (methodCallInfo.size() == 2) { - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, GradleCommonClassNames.GRADLE_API_ARTIFACTS_EXTERNAL_MODULE_DEPENDENCY); - // Assuming that the method call is addition of new dependency into configuration. - PsiClass contributorClass = - psiManager.findClassWithCache(GradleCommonClassNames.GRADLE_API_DEPENDENCY_HANDLER, place.getResolveScope()); - if (contributorClass == null) return; - GradleResolverUtil.processMethod(methodCallInfo.get(0), contributorClass, processor, state, place, "add"); - } - else if (methodCallInfo.size() == 3) { - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, - GradleCommonClassNames.GRADLE_API_DEPENDENCY_HANDLER, - GradleCommonClassNames.GRADLE_API_ARTIFACTS_EXTERNAL_MODULE_DEPENDENCY, - GradleCommonClassNames.GRADLE_API_ARTIFACTS_DEPENDENCY_ARTIFACT, - GradleCommonClassNames.GRADLE_API_PROJECT); - } - else if (methodCallInfo.size() == 4) { - // Assuming that the method call is addition of new dependency into configuration. - PsiClass contributorClass = - psiManager.findClassWithCache(GradleCommonClassNames.GRADLE_API_DEPENDENCY_HANDLER, place.getResolveScope()); - if (contributorClass == null) return; - GradleResolverUtil.processMethod(methodCallInfo.get(0), contributorClass, processor, state, place, "add"); - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.kt new file mode 100644 index 000000000000..43829f88d98e --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.kt @@ -0,0 +1,105 @@ +/* + * 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.service.resolve + +import com.intellij.openapi.util.Key +import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.patterns.StandardPatterns.or +import com.intellij.psi.* +import com.intellij.psi.scope.BaseScopeProcessor +import com.intellij.psi.scope.ElementClassHint +import com.intellij.psi.scope.PsiScopeProcessor +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +import org.jetbrains.plugins.gradle.service.resolve.GradleResolverUtil.canBeMethodOf +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression +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.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * @author Vladislav.Soroka + * @since 11/10/2016 + */ +class GradleDependenciesContributor : GradleMethodContextContributor { + companion object { + val dependenciesClosure = groovyClosure().inMethod(or(psiMethod(GRADLE_API_PROJECT, "dependencies"), + psiMethod(GRADLE_API_SCRIPT_HANDLER, "dependencies"))) + val dependencyConfigurationClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_DEPENDENCY_HANDLER, "add")) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (dependencyConfigurationClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_ARTIFACTS_MODULE_DEPENDENCY, closure), Closure.DELEGATE_FIRST) + } + if (dependenciesClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_DEPENDENCY_HANDLER, closure), Closure.DELEGATE_FIRST) + } + return null + } + + override fun process(methodCallInfo: List, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { + val psiManager = GroovyPsiManager.getInstance(place.project) + val methodName = if (methodCallInfo.isNotEmpty()) methodCallInfo[0] else return true + + val classHint = processor.getHint(ElementClassHint.KEY) + val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint) + if (shouldProcessMethods && place is GrReferenceExpression && psiElement().inside(dependenciesClosure).accepts(place)) { + if (methodCallInfo.size == 2) { + val psiClass = psiManager.findClassWithCache(GRADLE_API_DEPENDENCY_HANDLER, place.getResolveScope()) ?: return true + if (canBeMethodOf(methodName, psiClass)) { + return true + } + val componentProcessor = AddDependencyNotationProcessor(processor, place, psiClass) + if (!psiClass.processDeclarations(componentProcessor, state, null, place)) return false + } + } + if (psiElement().inside(dependencyConfigurationClosure).accepts(place)) { + if (GradleResolverUtil.processDeclarations(psiManager, processor, state, place, + GRADLE_API_ARTIFACTS_MODULE_DEPENDENCY, + GRADLE_API_ARTIFACTS_CLIENT_MODULE_DEPENDENCY)) return false + } + return true + } + + class AddDependencyNotationProcessor(val delegate: PsiScopeProcessor, val place: PsiElement, val psiClass: PsiClass) : BaseScopeProcessor() { + override fun execute(method: PsiElement, state: ResolveState): Boolean { + method as? PsiMethod ?: return true + + val wrappedBase = GrLightMethodBuilder(place.manager, "add").apply { + navigationElement = method + containingClass = psiClass + } + wrappedBase.addParameter("configurationName", CommonClassNames.JAVA_LANG_OBJECT) + wrappedBase.addParameter("dependencyNotation", CommonClassNames.JAVA_LANG_OBJECT, true) + if (!delegate.execute(wrappedBase, state)) return false + return true + } + + override fun getHint(hintKey: Key) = if (hintKey == com.intellij.psi.scope.ElementClassHint.KEY) { + @Suppress("UNCHECKED_CAST") + ElementClassHint { it == com.intellij.psi.scope.ElementClassHint.DeclarationKind.METHOD } as T + } + else { + null + } + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.java deleted file mode 100644 index 6f49696a2cd2..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.java +++ /dev/null @@ -1,127 +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.util.text.StringUtil; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; - -import java.util.List; - -import static org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.*; - -/** - * @author Vladislav.Soroka - * @since 8/30/13 - */ -public class GradleDistributionsContributor implements GradleMethodContextContributor { - - static final String DISTRIBUTIONS = "distributions"; - private static final String CONTENTS_METHOD = "contents"; - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) { - return; - } - String methodCall = ContainerUtil.getLastItem(methodCallInfo); - if (methodCall == null) { - return; - } - - if (methodCallInfo.size() > 1 && DISTRIBUTIONS.equals(place.getText()) && place instanceof GrReferenceExpressionImpl) { - GradleResolverUtil.addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, GRADLE_API_DISTRIBUTION_CONTAINER); - } - - if (methodCallInfo.size() > 1 && methodCall.equals("project")) { - methodCallInfo.remove(methodCallInfo.size() - 1); - methodCall = ContainerUtil.getLastItem(methodCallInfo); - } - - if (methodCall == null || !StringUtil.startsWith(methodCall, DISTRIBUTIONS)) { - return; - } - - String closureMethod = null; - String configureClosureClazz = null; - String contributorClass = null; - boolean isRootRelated = StringUtil.startsWith(methodCall, DISTRIBUTIONS + '.'); - - if (methodCallInfo.size() == 1) { - configureClosureClazz = GRADLE_API_DISTRIBUTION_CONTAINER; - if (place instanceof GrReferenceExpressionImpl) { - String varClazz = - StringUtil.startsWith(methodCall, DISTRIBUTIONS + '.') ? GRADLE_API_DISTRIBUTION_CONTAINER : GRADLE_API_DISTRIBUTION; - GradleResolverUtil.addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, varClazz); - } - else { - contributorClass = GRADLE_API_DISTRIBUTION_CONTAINER; - } - closureMethod = "configure"; - } - else if (methodCallInfo.size() == 2) { - configureClosureClazz = GRADLE_API_DISTRIBUTION; - contributorClass = GRADLE_API_DISTRIBUTION; - closureMethod = "create"; - } - else if (methodCallInfo.size() == 3 && CONTENTS_METHOD.equals(place.getText())) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - PsiClass psiClass = psiManager.findClassWithCache(GRADLE_API_DISTRIBUTION, place.getResolveScope()); - - GrLightMethodBuilder methodWithClosure = - GradleResolverUtil.createMethodWithClosure(CONTENTS_METHOD, GRADLE_API_FILE_COPY_SPEC, null, place, psiManager); - if (methodWithClosure != null) { - if (psiClass != null) { - PsiMethod psiMethod = ArrayUtil.getFirstElement(psiClass.findMethodsByName(CONTENTS_METHOD, false)); - if (psiMethod != null) { - methodWithClosure.setNavigationElement(psiMethod); - } - } - processor.execute(methodWithClosure, state); - } - } - else if (methodCallInfo.size() == 4 && CONTENTS_METHOD.equals(methodCallInfo.get(1))) { - GradleResolverUtil.processDeclarations(methodCallInfo.get(0), GroovyPsiManager.getInstance(place.getProject()), - processor, state, place, GRADLE_API_FILE_COPY_SPEC); - } - - if (configureClosureClazz != null && !isRootRelated) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GrLightMethodBuilder methodWithClosure = - GradleResolverUtil.createMethodWithClosure(closureMethod, configureClosureClazz, null, place, psiManager); - if (methodWithClosure != null) { - processor.execute(methodWithClosure, state); - } - } - - if (contributorClass != null) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, contributorClass); - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.kt new file mode 100644 index 000000000000..35261283cfad --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDistributionsContributor.kt @@ -0,0 +1,103 @@ +/* + * 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.patterns.PsiJavaPatterns +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.ElementClassHint +import com.intellij.psi.scope.NameHint +import com.intellij.psi.scope.PsiScopeProcessor +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression +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.GrLightVariable +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 +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * @author Vladislav.Soroka + * * + * @since 8/30/13 + */ +class GradleDistributionsContributor : GradleMethodContextContributor { + + companion object { + val DISTRIBUTIONS_METHOD = "distributions" + val distributionsClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, DISTRIBUTIONS_METHOD)) + val distributionClosure = groovyClosure().withAncestor(2, distributionsClosure) + val contentsClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_DISTRIBUTION, "contents")) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (distributionsClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_DISTRIBUTION_CONTAINER, closure), Closure.DELEGATE_FIRST) + } + if (distributionClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_DISTRIBUTION, closure), Closure.DELEGATE_FIRST) + } + if (contentsClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_FILE_COPY_SPEC, closure), Closure.DELEGATE_FIRST) + } + return null + } + + override fun process(methodCallInfo: MutableList, + processor: PsiScopeProcessor, + state: ResolveState, + place: PsiElement): Boolean { + val classHint = processor.getHint(ElementClassHint.KEY) + val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint) + if (shouldProcessMethods && processor.getHint(NameHint.KEY)?.getName(state) == DISTRIBUTIONS_METHOD) { + val psiManager = GroovyPsiManager.getInstance(place.project) + val projectClass = psiManager.findClassWithCache(GRADLE_API_PROJECT, place.resolveScope) ?: return true + val distContainerClass = psiManager.createTypeByFQClassName(GRADLE_API_DISTRIBUTION_CONTAINER, place.resolveScope) ?: return true + val methodBuilder = GrLightMethodBuilder(place.manager, DISTRIBUTIONS_METHOD).apply { + containingClass = projectClass + returnType = distContainerClass + } + methodBuilder.addParameter("configuration", GROOVY_LANG_CLOSURE, true) + if (!processor.execute(methodBuilder, state)) return false + } + + val psiElement = PsiJavaPatterns.psiElement() + if (psiElement.inside(distributionsClosure).accepts(place)) { + val name = place.text + if (place.parent is GrMethodCallExpression) { + val psiManager = GroovyPsiManager.getInstance(place.project) + val methodBuilder = GradleResolverUtil.createMethodWithClosure( + name, GRADLE_API_DISTRIBUTION, null, place, psiManager) + if (methodBuilder != null) { + if (!processor.execute(methodBuilder, state)) return false + } + } + if (place.parent is GrReferenceExpression || psiElement.withTreeParent(distributionsClosure).accepts(place)) { + val variable = GrLightVariable(place.manager, name, GRADLE_API_DISTRIBUTION, place) + if (!processor.execute(variable, state)) return false + } + } + + return true + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.java deleted file mode 100644 index f853386987a0..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.service.resolve; - - -/** - * @author Vladislav.Soroka - * @since 11/18/13 - */ -public class GradleIdeaPluginScriptContributor extends GradleSimpleContributor { - public GradleIdeaPluginScriptContributor() { - super("idea", "org.gradle.plugins.ide.idea.model.IdeaModel"); - } -} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt new file mode 100644 index 000000000000..5c74025c43b0 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt @@ -0,0 +1,100 @@ +/* + * 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.service.resolve + +import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +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.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + + +/** + * @author Vladislav.Soroka + * @since 11/18/13 + */ +class GradleIdeaPluginScriptContributor : GradleMethodContextContributor { + + companion object { + val IDEA_METHOD = "idea" + val IDEA_MODEL_FQN = "org.gradle.plugins.ide.idea.model.IdeaModel" + val IDEA_PROJECT_FQN = "org.gradle.plugins.ide.idea.model.IdeaProject" + val IDEA_MODULE_FQN = "org.gradle.plugins.ide.idea.model.IdeaModule" + val IDEA_MODULE_IML_FQN = "org.gradle.plugins.ide.idea.model.IdeaModuleIml" + val IDE_XML_MERGER_FQN = "org.gradle.plugins.ide.api.XmlFileContentMerger" + val IDE_FILE_MERGER_FQN = "org.gradle.plugins.ide.api.FileContentMerger" + val IDEA_XML_MODULE_FQN = "org.gradle.plugins.ide.idea.model.Module" + val IDEA_XML_PROJECT_FQN = "org.gradle.plugins.ide.idea.model.Project" + val ideaClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, IDEA_METHOD)) + val ideaProjectClosure = groovyClosure().inMethod(psiMethod(IDEA_MODEL_FQN, "project")) + val ideaIprClosure = groovyClosure().inMethod(psiMethod(IDEA_PROJECT_FQN, "ipr")) + val ideaModuleClosure = groovyClosure().inMethod(psiMethod(IDEA_MODEL_FQN, "module")) + val ideaImlClosure = groovyClosure().inMethod(psiMethod(IDEA_MODULE_FQN, "iml")) + val ideaBeforeMergedClosure = groovyClosure().inMethod(psiMethod(IDE_FILE_MERGER_FQN, "beforeMerged")) + val ideaWhenMergedClosure = groovyClosure().inMethod(psiMethod(IDE_FILE_MERGER_FQN, "whenMerged")) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (ideaClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(IDEA_MODEL_FQN, closure), Closure.DELEGATE_FIRST) + } + if (ideaImlClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(IDEA_MODULE_IML_FQN, closure), Closure.DELEGATE_FIRST) + } + return null + } + + override fun process(methodCallInfo: List, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { + val classHint = processor.getHint(com.intellij.psi.scope.ElementClassHint.KEY) + val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint) + if (shouldProcessMethods && processor.getHint( + com.intellij.psi.scope.NameHint.KEY)?.getName(state) == IDEA_METHOD) { + val psiManager = GroovyPsiManager.getInstance(place.project) + val projectClass = psiManager.findClassWithCache(GRADLE_API_PROJECT, place.resolveScope) ?: return true + val returnClass = psiManager.createTypeByFQClassName(IDEA_MODEL_FQN, place.resolveScope) ?: return true + val methodBuilder = GrLightMethodBuilder(place.manager, IDEA_METHOD).apply { + containingClass = projectClass + returnType = returnClass + } + methodBuilder.addParameter("configuration", GROOVY_LANG_CLOSURE, true) + if (!processor.execute(methodBuilder, state)) return false + } + + val psiManager = GroovyPsiManager.getInstance(place.project) + if (psiElement().inside(ideaModuleClosure).accepts(place)) { + if (GradleResolverUtil.processDeclarations(psiManager, processor, state, place, IDEA_MODULE_FQN)) return false + } + + if (psiElement().inside(ideaProjectClosure).accepts(place)) { + if (psiElement().inside(ideaIprClosure).accepts(place)) { + if (GradleResolverUtil.processDeclarations(psiManager, processor, state, place, IDE_XML_MERGER_FQN)) return false + } + if (GradleResolverUtil.processDeclarations(psiManager, processor, state, place, IDEA_PROJECT_FQN)) return false + } + + return true + } +} \ No newline at end of file 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 index 24fb16278359..e33cb63319fc 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java @@ -78,17 +78,48 @@ public class GradleImplicitContributor implements GradleMethodContextContributor ); @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { + 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; + return true; } final String methodCall = getLastItem(methodCallInfo); - if (methodCall == null) return; + if (methodCall == null) return true; if (!methodCall.equals("task")) { if (methodCallInfo.size() == 1) { @@ -125,6 +156,7 @@ public class GradleImplicitContributor implements GradleMethodContextContributor } } } + return true; } public static void processImplicitDeclarations(@NotNull PsiScopeProcessor processor, @@ -185,7 +217,7 @@ public class GradleImplicitContributor implements GradleMethodContextContributor PsiClass contributorClass = psiManager.findClassWithCache(fqName, place.getResolveScope()); if (contributorClass == null) return; - GradleResolverUtil.processMethod(taskName, contributorClass, processor, state, place); + //GradleResolverUtil.processMethod(taskName, contributorClass, processor, state, place); } } else { @@ -203,8 +235,8 @@ public class GradleImplicitContributor implements GradleMethodContextContributor 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); + //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/GradleJavaContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleJavaContributor.kt new file mode 100644 index 000000000000..f5c782cf1319 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleJavaContributor.kt @@ -0,0 +1,105 @@ +/* + * 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.patterns.ElementPattern +import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.patterns.StandardPatterns.or +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.util.ProcessingContext +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +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.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.GrLightVariable +import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * @author Vladislav.Soroka + * @since 11/10/2016 + */ +class GradleJavaContributor : GradleMethodContextContributor { + companion object { + val sourceSetsClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_JAVA_PLUGIN_CONVENTION, "sourceSets")) + val sourceSetClosure = groovyClosure().withAncestor(2, sourceSetsClosure) + val sourceSetReference = object : ElementPattern { + override fun getCondition() = null + override fun accepts(o: Any?) = false + override fun accepts(o: Any?, context: ProcessingContext): Boolean { + return o is GrExpression && o.type?.equalsToText(GRADLE_API_SOURCE_SET) ?: false + } + } + + val sourceDirectorySetClosure = psiElement().andOr( + groovyClosure().withAncestor(2, sourceSetClosure), + groovyClosure().inMethod(or(psiMethod(GRADLE_API_SOURCE_SET, "java"), + psiMethod(GRADLE_API_SOURCE_SET, "resources")))) + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (sourceSetsClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_SOURCE_SET_CONTAINER, closure), Closure.DELEGATE_FIRST) + } + if (sourceSetClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_SOURCE_SET, closure), Closure.DELEGATE_FIRST) + } + if (sourceDirectorySetClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_SOURCE_DIRECTORY_SET, closure), Closure.DELEGATE_FIRST) + } + if (psiElement().withParent( + psiElement().withFirstChild(sourceSetReference)).accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_SOURCE_SET, closure), Closure.DELEGATE_FIRST) + } + return null + } + + override fun process(methodCallInfo: List, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { + val psiManager = GroovyPsiManager.getInstance(place.project) + if (!GradleResolverUtil.processDeclarations(psiManager, processor, state, place, + GRADLE_API_BASE_PLUGIN_CONVENTION, + GRADLE_API_JAVA_PLUGIN_CONVENTION, + GRADLE_API_APPLICATION_PLUGIN_CONVENTION, + GRADLE_API_WAR_CONVENTION)) { + return false + } + + val psiElement = psiElement() + if (psiElement.inside(sourceSetsClosure).accepts(place)) { + val name = place.text + if (place.parent is GrMethodCallExpression) { + val methodBuilder = GradleResolverUtil.createMethodWithClosure( + name, GRADLE_API_SOURCE_SET, null, place, psiManager) + if (methodBuilder != null) { + if (!processor.execute(methodBuilder, state)) return false + } + } + if (place.parent is GrReferenceExpression || psiElement.withTreeParent(sourceSetsClosure).accepts(place)) { + val variable = GrLightVariable(place.manager, name, GRADLE_API_SOURCE_SET, place) + if (!processor.execute(variable, state)) return false + } + } + + return true + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.java deleted file mode 100644 index 8ab490d898c2..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; - -import java.util.List; - -/** - * @{GradleMavenArtifactRepositoryContributor} provides gradle MavenArtifactRepository DSL resolving contributor. - * - * e.g. - * repositories { - * maven { - * url "http://snapshots.repository.codehaus.org/" - * } - * } - * - * @author Vladislav.Soroka - * @since 10/21/13 - */ -public class GradleMavenArtifactRepositoryContributor implements GradleMethodContextContributor { - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty() || methodCallInfo.size() < 3 || - !"repositories".equals(methodCallInfo.get(2)) || !"maven".equals(methodCallInfo.get(1))) { - return; - } - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, - GradleCommonClassNames.GRADLE_API_ARTIFACTS_REPOSITORIES_MAVEN_ARTIFACT_REPOSITORY); - PsiClass contributorClass = psiManager.findClassWithCache( - GradleCommonClassNames.GRADLE_API_ARTIFACTS_REPOSITORIES_MAVEN_ARTIFACT_REPOSITORY, place.getResolveScope()); - if (contributorClass == null) return; - GradleResolverUtil.processMethod(methodCallInfo.get(0), contributorClass, processor, state, place); - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.kt new file mode 100644 index 000000000000..7e2962142d1d --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenArtifactRepositoryContributor.kt @@ -0,0 +1,76 @@ +/* + * 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.service.resolve + +import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.patterns.StandardPatterns.or +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import groovy.lang.Closure +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.* +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock +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.patterns.groovyClosure +import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo + +/** + * Provides gradle MavenArtifactRepository DSL resolving contributor. + * + * e.g. + * repositories { + * maven { + * url "http://snapshots.repository.codehaus.org/" + * } + * } + * + * @author Vladislav.Soroka + * @since 10/21/13 + */ +class GradleMavenArtifactRepositoryContributor : GradleMethodContextContributor { + companion object { + val repositoriesClosure = groovyClosure().inMethod(or(psiMethod(GRADLE_API_PROJECT, "repositories"), + psiMethod(GRADLE_API_SCRIPT_HANDLER, "repositories"))) + val repositoryClosure = psiElement().andOr( + groovyClosure().withAncestor(2, repositoriesClosure), + groovyClosure().inMethod(psiMethod(GRADLE_API_REPOSITORY_HANDLER, "maven"))) + } + + override fun process(methodCallInfo: List, + processor: PsiScopeProcessor, + state: ResolveState, + place: PsiElement): Boolean { + + val psiManager = GroovyPsiManager.getInstance(place.project) + if (methodCallInfo.isNotEmpty() && psiElement().inside(repositoryClosure).accepts(place)) { + if (!GradleResolverUtil.processDeclarations( + psiManager, processor, state, place, GRADLE_API_ARTIFACTS_REPOSITORIES_MAVEN_ARTIFACT_REPOSITORY)) return false + } + return true + } + + override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? { + if (repositoriesClosure.accepts(closure)) { + return DelegatesToInfo(TypesUtil.createType(GRADLE_API_REPOSITORY_HANDLER, closure), Closure.DELEGATE_FIRST) + } +// if (repositoryClosure.accepts(closure)) { +// return DelegatesToInfo(TypesUtil.createType(GRADLE_API_ARTIFACTS_REPOSITORIES_MAVEN_ARTIFACT_REPOSITORY, closure), DELEGATE_FIRST) +// } + return null + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenDeployerContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenDeployerContributor.java deleted file mode 100644 index 682786542249..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMavenDeployerContributor.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; - -import java.util.List; - -/** - * @{GradleMavenArtifactRepositoryContributor} provides gradle MavenArtifactRepository DSL resolving contributor. - * - * e.g. - * repositories { - * maven { - * url "http://snapshots.repository.codehaus.org/" - * } - * } - * - * @author Vladislav.Soroka - * @since 10/21/13 - */ -public class GradleMavenDeployerContributor implements GradleMethodContextContributor { - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty() || methodCallInfo.size() < 3 || - !"repositories".equals(methodCallInfo.get(2)) || !"mavenDeployer".equals(methodCallInfo.get(1))) { - return; - } - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations( - psiManager, processor, state, place, - GradleCommonClassNames.GRADLE_API_ARTIFACTS_MAVEN_MAVEN_DEPLOYER); - PsiClass contributorClass = psiManager.findClassWithCache( - GradleCommonClassNames.GRADLE_API_ARTIFACTS_MAVEN_MAVEN_DEPLOYER, place.getResolveScope()); - if (contributorClass == null) return; - GradleResolverUtil.processMethod(methodCallInfo.get(0), contributorClass, processor, state, place); - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMethodContextContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMethodContextContributor.java index d08616276435..508e3fba117b 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMethodContextContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMethodContextContributor.java @@ -20,7 +20,10 @@ import com.intellij.psi.PsiElement; 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.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor; +import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo; import java.util.List; @@ -56,9 +59,17 @@ public interface GradleMethodContextContributor { * @param processor the processor receiving the declarations. * @param state current resolve state * @param place the original element from which the tree up walk was initiated. + * @return true if the processing should continue or false if it should be stopped. */ - void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place); + default boolean process(@NotNull List methodCallInfo, + @NotNull PsiScopeProcessor processor, + @NotNull ResolveState state, + @NotNull PsiElement place) { + return true; + } + + @Nullable + default DelegatesToInfo getDelegatesToInfo(@NotNull GrClosableBlock closure) { + return null; + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt new file mode 100644 index 000000000000..16a1e1835df2 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt @@ -0,0 +1,33 @@ +/* + * 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.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT +import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager + +/** + * @author Vladislav.Soroka + * @since 11/10/2016 + */ +class GradleProjectContributor : GradleMethodContextContributor { + override fun process(methodCallInfo: List, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean { + val psiManager = GroovyPsiManager.getInstance(place.project) + return GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_PROJECT) + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java index a2286d4e6ea6..ff5a5b4bdea5 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.gradle.service.resolve; import com.intellij.openapi.util.RecursionManager; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.util.GradleLog; @@ -29,14 +28,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgument import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; 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.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightField; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import java.util.Arrays; @@ -122,87 +119,19 @@ public class GradleResolverUtil { return methodWithClosure; } - public static void processMethod(@NotNull String methodName, - @NotNull PsiClass handlerClass, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - processMethod(methodName, handlerClass, processor, state, place, null); - } - - public static void processMethod(@NotNull String methodName, - @NotNull PsiClass handlerClass, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place, - @Nullable String defaultMethodName) { - GrLightMethodBuilder builder = new GrLightMethodBuilder(place.getManager(), methodName); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getManager().getProject()); - PsiType type = new PsiArrayType(factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, place.getResolveScope())); - builder.addParameter(new GrLightParameter("param", type, builder)); - PsiClassType retType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, 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 = getGrMethodArumentsCount(args); - argsCount++; // Configuration name is delivered as an argument. - - // handle setter's shortcut facilities - final String setter = GroovyPropertyUtils.getSetterName(methodName); - for (PsiMethod method : handlerClass.findMethodsByName(setter, false)) { - if (method.getParameterList().getParametersCount() == 1) { - builder.setNavigationElement(method); - return; - } - } - - for (PsiMethod method : handlerClass.findMethodsByName(methodName, false)) { - if (method.getParameterList().getParametersCount() == argsCount) { - builder.setNavigationElement(method); - return; - } - } - - if (defaultMethodName != null) { - for (PsiMethod method : handlerClass.findMethodsByName(defaultMethodName, false)) { - if (method.getParameterList().getParametersCount() == argsCount) { - builder.setNavigationElement(method); - return; - } - } - } - } - - public static void processDeclarations(@NotNull GroovyPsiManager psiManager, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place, - @NotNull String... fqNames) { - processDeclarations(null, psiManager, processor, state, place, fqNames); - } - - public static void processDeclarations(@Nullable String methodName, - @NotNull GroovyPsiManager psiManager, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place, - @NotNull String... fqNames) { + public static boolean processDeclarations(@NotNull GroovyPsiManager psiManager, + @NotNull PsiScopeProcessor processor, + @NotNull ResolveState state, + @NotNull PsiElement place, + @NotNull String... fqNames) { for (String fqName : fqNames) { if(fqName == null) continue; PsiClass psiClass = psiManager.findClassWithCache(fqName, place.getResolveScope()); if (psiClass != null) { - psiClass.processDeclarations(processor, state, null, place); - if (methodName != null) { - processMethod(methodName, psiClass, processor, state, place); - } + if (!UtilKt.processDeclarations(psiClass, processor, state, place)) return false; } } + return true; } @Nullable diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java deleted file mode 100644 index 7b4fe8c95e54..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; - -import java.util.List; -import java.util.Set; - -import static org.jetbrains.plugins.gradle.service.resolve.GradleDistributionsContributor.DISTRIBUTIONS; -import static org.jetbrains.plugins.gradle.service.resolve.GradleSourceSetsContributor.SOURCE_SETS; - -/** - * @author Denis Zhdanov - * @since 8/14/13 1:03 PM - */ -public class GradleRootContributor implements GradleMethodContextContributor { - - private final GradleSourceSetsContributor mySourceSetsContributor; - private final GradleDistributionsContributor myDistributionsContributor; - - public GradleRootContributor(GradleSourceSetsContributor sourceSetsContributor, GradleDistributionsContributor contributor) { - mySourceSetsContributor = sourceSetsContributor; - myDistributionsContributor = contributor; - } - - private final static Set BUILD_SCRIPT_BLOCKS = ContainerUtil.newHashSet( - "subprojects", - "allprojects", - "beforeEvaluate", - "afterEvaluate", - SOURCE_SETS, - DISTRIBUTIONS - ); - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.size() > 2) { - return; - } - - if (methodCallInfo.size() == 2 && !BUILD_SCRIPT_BLOCKS.contains(methodCallInfo.get(1))) { - return; - } - if (methodCallInfo.size() > 0) { - String method = ContainerUtil.getLastItem(methodCallInfo); - if (method != null && StringUtil.startsWith(method, SOURCE_SETS)) { - mySourceSetsContributor.process(methodCallInfo, processor, state, place); - return; - } - if (method != null && StringUtil.startsWith(method, DISTRIBUTIONS)) { - myDistributionsContributor.process(methodCallInfo, processor, state, place); - return; - } - } - - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(methodCallInfo.size() > 0 ? methodCallInfo.get(0) : null, - psiManager, processor, state, place, - GradleCommonClassNames.GRADLE_API_PROJECT); - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java index 2b2747d7d08f..185c287d61e1 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java @@ -66,9 +66,6 @@ public class GradleScriptContributor extends NonCodeMembersContributor { current != null; current = PsiTreeUtil.getParentOfType(current, GrMethodCall.class)) { GrExpression expression = current.getInvokedExpression(); - if (expression == null) { - continue; - } String text = expression.getText(); if (text != null) { methodInfo.add(text); @@ -81,7 +78,7 @@ public class GradleScriptContributor extends NonCodeMembersContributor { } for (GradleMethodContextContributor contributor : GradleMethodContextContributor.EP_NAME.getExtensions()) { - contributor.process(methodInfo, processor, state, place); + if (!contributor.process(methodInfo, processor, state, place)) return; } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSimpleContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSimpleContributor.java deleted file mode 100644 index 4a3163f69e2a..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSimpleContributor.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; - -import java.util.List; - -/** - * @author Vladislav.Soroka - * @since 8/30/13 - */ -public abstract class GradleSimpleContributor implements GradleMethodContextContributor { - - private final String blockName; - private final String fqName; - private final List myMixIns; - - protected GradleSimpleContributor(@NotNull String blockName, @NotNull String fqName, String... mixIns) { - this.blockName = blockName; - this.fqName = fqName; - myMixIns = ContainerUtil.newArrayList(mixIns); - } - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty() || methodCallInfo.size() < 2 || !blockName.equals(methodCallInfo.get(1))) { - return; - } - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, fqName); - for(final String mixin : myMixIns) { - PsiClass contributorClass = - psiManager.findClassWithCache(mixin, place.getResolveScope()); - if (contributorClass == null) continue; - GradleResolverUtil.processMethod(methodCallInfo.get(0), contributorClass, processor, state, place); - } - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSourceSetsContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSourceSetsContributor.java deleted file mode 100644 index f5a1a7ae79db..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleSourceSetsContributor.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.service.resolve; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveState; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; - -import java.util.List; - -/** - * @author Vladislav.Soroka - * @since 8/29/13 - */ -public class GradleSourceSetsContributor implements GradleMethodContextContributor { - static final String SOURCE_SETS = "sourceSets"; - private static final String CONFIGURE_CLOSURE_METHOD = "configure"; - private static final int SOURCE_SET_CONTAINER_LEVEL = 1; - private static final int SOURCE_SET_LEVEL = 2; - private static final int SOURCE_DIRECTORY_LEVEL = 3; - private static final int SOURCE_DIRECTORY_CLOSURE_LEVEL = 4; - - @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) { - return; - } - String methodCall = ContainerUtil.getLastItem(methodCallInfo); - if (methodCall == null) { - return; - } - - if (methodCallInfo.size() > 1 && SOURCE_SETS.equals(place.getText()) && place instanceof GrReferenceExpressionImpl) { - GradleResolverUtil - .addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER); - } - - if (methodCallInfo.size() > 1 && methodCall.equals("project")) { - methodCallInfo.remove(methodCallInfo.size() - 1); - methodCall = ContainerUtil.getLastItem(methodCallInfo); - } - - if (methodCall == null || methodCallInfo.size() > SOURCE_DIRECTORY_CLOSURE_LEVEL || !StringUtil.startsWith(methodCall, SOURCE_SETS)) { - return; - } - - String configureClosureClazz = null; - String contributorClass = null; - - boolean isRootRelated = StringUtil.startsWith(methodCall, SOURCE_SETS + '.'); - - if (methodCallInfo.size() == SOURCE_SET_CONTAINER_LEVEL) { - configureClosureClazz = GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER; - if (place instanceof GrReferenceExpressionImpl) { - String varClazz = StringUtil.startsWith(methodCall, SOURCE_SETS + '.') - ? GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER - : GradleCommonClassNames.GRADLE_API_SOURCE_SET; - GradleResolverUtil.addImplicitVariable(processor, state, (GrReferenceExpressionImpl)place, varClazz); - } - else { - contributorClass = GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER; - } - } - else if (methodCallInfo.size() == SOURCE_SET_LEVEL) { - configureClosureClazz = GradleCommonClassNames.GRADLE_API_SOURCE_SET; - contributorClass = GradleCommonClassNames.GRADLE_API_SOURCE_SET; - } - else if (methodCallInfo.size() == SOURCE_DIRECTORY_LEVEL) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - PsiClass psiClass = psiManager.findClassWithCache(GradleCommonClassNames.GRADLE_API_SOURCE_SET, place.getResolveScope()); - configureClosureClazz = - GradleResolverUtil.canBeMethodOf(place.getText(), psiClass) ? null : GradleCommonClassNames.GRADLE_API_SOURCE_DIRECTORY_SET; - contributorClass = GradleCommonClassNames.GRADLE_API_SOURCE_DIRECTORY_SET; - } - else if (methodCallInfo.size() == SOURCE_DIRECTORY_CLOSURE_LEVEL) { - contributorClass = GradleCommonClassNames.GRADLE_API_SOURCE_DIRECTORY_SET; - } - - if (configureClosureClazz != null && !isRootRelated) { - final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GrLightMethodBuilder methodWithClosure = - GradleResolverUtil - .createMethodWithClosure(CONFIGURE_CLOSURE_METHOD, configureClosureClazz, null, place, psiManager); - if (methodWithClosure != null) { - processor.execute(methodWithClosure, state); - } - } - //else { - // GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - // GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GradleCommonClassNames.GRADLE_API_PROJECT); - //} - if (contributorClass != null) { - GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, contributorClass); - } - } -} 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 index 77e734a8b09f..2121b4a55b4c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java @@ -42,11 +42,11 @@ import java.util.List; public class GradleTaskContributor implements GradleMethodContextContributor { @Override - public void process(@NotNull List methodCallInfo, - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @NotNull PsiElement place) { - if (methodCallInfo.isEmpty()) return; + 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())) { @@ -59,28 +59,19 @@ public class GradleTaskContributor implements GradleMethodContextContributor { processTaskAddition(methodCallInfo.get(0), GradleCommonClassNames.GRADLE_API_TASK_CONTAINER, processor, state, place); } else { - processTaskTypeParameter(methodCallInfo.get(0), processor, state, place); + processTaskTypeParameter(processor, state, place); } GradleImplicitContributor.processImplicitDeclarations(processor, state, place); } else if (methodCallInfo.size() >= 3) { - processTaskTypeParameter(methodCallInfo.get(0), processor, state, place); - + processTaskTypeParameter(processor, state, place); GradleImplicitContributor.processImplicitDeclarations(processor, state, place); - - if (place.getText().equals(GradleSourceSetsContributor.SOURCE_SETS) && - StringUtil.startsWith(methodCallInfo.get(0), GradleSourceSetsContributor.SOURCE_SETS + '.')) { - GradleResolverUtil.addImplicitVariable(processor, state, place, GradleCommonClassNames.GRADLE_API_SOURCE_SET_CONTAINER); - } - if (place.getText().equals(GradleDistributionsContributor.DISTRIBUTIONS) && - StringUtil.startsWith(methodCallInfo.get(0), GradleDistributionsContributor.DISTRIBUTIONS + '.')) { - GradleResolverUtil.addImplicitVariable(processor, state, place, GradleCommonClassNames.GRADLE_API_DISTRIBUTION_CONTAINER); - } } + return true; } - private static void processTaskTypeParameter(@NotNull String methodCall, @NotNull PsiScopeProcessor processor, + private static void processTaskTypeParameter(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @NotNull PsiElement place) { final int taskTypeParameterLevel = 3; @@ -102,7 +93,7 @@ public class GradleTaskContributor implements GradleMethodContextContributor { PsiImmediateClassType immediateClassType = (PsiImmediateClassType)psiType; for (PsiType type : immediateClassType.getParameters()) { GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject()); - GradleResolverUtil.processDeclarations(methodCall, psiManager, processor, state, place, TypesUtil.getQualifiedName(type)); + GradleResolverUtil.processDeclarations(psiManager, processor, state, place, TypesUtil.getQualifiedName(type)); } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/dsl/GradleCompletionWeigher.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/dsl/GradleCompletionWeigher.java new file mode 100644 index 000000000000..84d827236f4d --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/dsl/GradleCompletionWeigher.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.service.resolve.dsl; + +import com.intellij.codeInsight.completion.CompletionLocation; +import com.intellij.codeInsight.completion.CompletionWeigher; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; + +/** + * @author Vladislav.Soroka + * @since 11/7/2016 + */ +public class GradleCompletionWeigher extends CompletionWeigher { + + @Override + public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) { + PsiFile containingFile = location.getCompletionParameters().getPosition().getContainingFile(); + if (!(containingFile instanceof GroovyFileBase)) { + return null; + } + + if (!FileUtilRt.extensionEquals(containingFile.getName(), GradleConstants.EXTENSION)) { + return null; + } + + Object o = element.getObject(); + if (o instanceof ResolveResult) { + PsiElement psiElement = ((ResolveResult)o).getElement(); + PsiFile psiFile = null; + if (psiElement != null) { + psiFile = psiElement.getContainingFile(); + } + if (psiFile == null && psiElement instanceof PsiMember) { + PsiClass psiClass = ((PsiMember)psiElement).getContainingClass(); + psiFile = psiClass != null ? psiClass.getContainingFile() : null; + } + if (psiFile instanceof PsiJavaFile) { + if (((PsiJavaFile)psiFile).getPackageName().startsWith("org.gradle")) { + return 1; + } + } + } + return -1; + } +} 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 new file mode 100644 index 000000000000..ea6c0e897c4b --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt @@ -0,0 +1,70 @@ +/* + * 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.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.scope.BaseScopeProcessor +import com.intellij.psi.scope.ElementClassHint +import com.intellij.psi.scope.NameHint.KEY +import com.intellij.psi.scope.PsiScopeProcessor + +/** + * @author Vladislav.Soroka + * @since 11/11/2016 + */ + +fun processDeclarations(handlerClass: PsiClass, + processor: PsiScopeProcessor, + state: ResolveState, + place: PsiElement): Boolean { + val name = processor.getHint(KEY)?.getName(state) + val componentClass = handlerClass + val componentProcessor = ComponentProcessor(processor, place, name) + if (name == null) { + if (!componentClass.processDeclarations(componentProcessor, state, null, place)) return false + } + else { + for (method in componentClass.findMethodsByName(name, true)) { + if (!componentProcessor.execute(method, state)) return false + } + for (prefix in arrayOf("add", "set")) { + for (method in componentClass.findMethodsByName(prefix + name.capitalize(), true)) { + if (!componentProcessor.execute(method, state)) return false + } + } + } + return true +} + +class ComponentProcessor(val delegate: PsiScopeProcessor, val place: PsiElement, val name: String?) : BaseScopeProcessor() { + + override fun execute(method: PsiElement, state: ResolveState): Boolean { + method as? PsiMethod ?: return true + return delegate.execute(method, state) + } + + override fun getHint(hintKey: Key): T? = if (hintKey == com.intellij.psi.scope.ElementClassHint.KEY) { + @Suppress("UNCHECKED_CAST") + ElementClassHint { it == com.intellij.psi.scope.ElementClassHint.DeclarationKind.METHOD } as T + } + else { + null + } +} \ No newline at end of file