gradle: DSL resolve rework

This commit is contained in:
Vladislav.Soroka
2016-11-29 20:50:24 +03:00
parent e3f371128b
commit c0f464bd1d
32 changed files with 1037 additions and 1029 deletions
@@ -21,7 +21,7 @@
<postStartupActivity implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleProjectStartupActivity"/>
<externalSystemTaskNotificationListener
implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleMavenProjectImportNotificationListener"/>
<completion.contributor language="Groovy" order="first"
implementationClass="org.jetbrains.plugins.gradle.integrations.maven.codeInsight.completion.MavenDependenciesGradleCompletionContributor"/>
<!--<completion.contributor language="Groovy" order="first"-->
<!--implementationClass="org.jetbrains.plugins.gradle.integrations.maven.codeInsight.completion.MavenDependenciesGradleCompletionContributor"/>-->
</extensions>
</idea-plugin>
+7 -11
View File
@@ -58,19 +58,16 @@
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleRootContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleTaskContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleProjectContributor"/>
<!--<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleTaskContributor"/>-->
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleConfigurationsContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleBuildScriptContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleDistributionsContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleIdeaPluginScriptContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleRepositoriesContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleMavenArtifactRepositoryContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleMavenDeployerContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleDependenciesContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleArtifactsContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleSourceSetsContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleImplicitContributor"/>
<resolve.contributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleJavaContributor"/>
<projectResolve implementation="org.jetbrains.plugins.gradle.service.project.BaseGradleProjectResolverExtension"/>
<frameworkSupport implementation="org.jetbrains.plugins.gradle.frameworkSupport.GradleJavaFrameworkSupportProvider"/>
<frameworkSupport implementation="org.jetbrains.plugins.gradle.frameworkSupport.GradleGroovyFrameworkSupportProvider"/>
@@ -153,6 +150,8 @@
implementationClass="org.jetbrains.plugins.gradle.documentation.GradleDocumentationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.plugins.gradle.codeInsight.UseDistributionWithSourcesNotificationProvider"/>
<annotator language="Groovy" implementationClass="org.jetbrains.plugins.gradle.service.resolve.dsl.GradleDslAnnotator"/>
<weigher key="completion" implementationClass="org.jetbrains.plugins.gradle.service.resolve.dsl.GradleCompletionWeigher"
id="myWeigher" order="first"/>
<localInspection language="Groovy" groupPath="Gradle" shortName="MultipleRepositoryUrls"
bundle="org.jetbrains.plugins.gradle.codeInspection.GradleInspectionBundle"
@@ -160,7 +159,7 @@
implementationClass="org.jetbrains.plugins.gradle.codeInspection.MultipleRepositoryUrlsInspection"/>
<copyPastePreProcessor implementation="org.jetbrains.plugins.gradle.action.PasteMvnDependencyPreProcessor"/>
</extensions>
<extensions defaultExtensionNs="org.intellij.groovy">
@@ -170,10 +169,7 @@
<variableEnhancer order="first" implementation="org.jetbrains.plugins.gradle.service.resolve.GradleClosureAsAnonymousParameterEnhancer"/>
<membersContributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleSettingsScriptContributor"/>
<membersContributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleScriptContributor"/>
<membersContributor implementation="org.jetbrains.plugins.gradle.service.resolve.GradleConfigurationsNonCodeMembersContributor"/>
<methodDescriptor class="org.gradle.api.Project" name="apply">
<namedArgument name="plugin" values="java,groovy,idea,eclipse,scala,antlr,application,ear,jetty,maven,osgi,war,announce,build-announcements,checkstyle,codenarc,eclipse-wtp,findbugs,jdepend,pmd,project-report,signing,sonar"/>
</methodDescriptor>
<delegatesToProvider implementation="org.jetbrains.plugins.gradle.service.resolve.GradleDelegatesToProvider"/>
<referenceTypeEnhancer implementation="org.jetbrains.plugins.gradle.service.resolve.NamedDomainObjectCollectionTypeEnhancer"/>
<unresolvedHighlightFilter implementation="org.jetbrains.plugins.gradle.service.resolve.GradleUnresolvedReferenceFilter"/>
</extensions>
@@ -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<String> 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);
}
}
}
}
@@ -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<String>,
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)
}
}
@@ -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);
}
}
@@ -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
}
}
@@ -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";
@@ -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<String> 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);
}
}
}
@@ -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<PsiElement> {
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<String>, 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
}
}
@@ -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);
}
}
}
}
@@ -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
}
}
@@ -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<String> 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");
}
}
}
@@ -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<String>, 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 <T : Any?> 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
}
}
}
@@ -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<String> 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);
}
}
}
@@ -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<String>,
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
}
}
@@ -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");
}
}
@@ -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<String>, 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
}
}
@@ -78,17 +78,48 @@ public class GradleImplicitContributor implements GradleMethodContextContributor
);
@Override
public void process(@NotNull List<String> methodCallInfo,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
public boolean process(@NotNull List<String> 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<String, ExternalProperty> 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<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);
}
}
}
@@ -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<PsiElement> {
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<String>, 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
}
}
@@ -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<String> 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);
}
}
@@ -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<String>,
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
}
}
@@ -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<String> 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);
}
}
@@ -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<String> methodCallInfo,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place);
default boolean process(@NotNull List<String> methodCallInfo,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
return true;
}
@Nullable
default DelegatesToInfo getDelegatesToInfo(@NotNull GrClosableBlock closure) {
return null;
}
}
@@ -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<String>, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean {
val psiManager = GroovyPsiManager.getInstance(place.project)
return GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GRADLE_API_PROJECT)
}
}
@@ -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
@@ -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<String> BUILD_SCRIPT_BLOCKS = ContainerUtil.newHashSet(
"subprojects",
"allprojects",
"beforeEvaluate",
"afterEvaluate",
SOURCE_SETS,
DISTRIBUTIONS
);
@Override
public void process(@NotNull List<String> 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);
}
}
@@ -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;
}
}
}
@@ -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<String> 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<String> 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);
}
}
}
@@ -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<String> 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);
}
}
}
@@ -42,11 +42,11 @@ import java.util.List;
public class GradleTaskContributor implements GradleMethodContextContributor {
@Override
public void process(@NotNull List<String> methodCallInfo,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
if (methodCallInfo.isEmpty()) return;
public boolean process(@NotNull List<String> 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));
}
}
}
@@ -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;
}
}
@@ -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 <T : Any?> getHint(hintKey: Key<T>): 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
}
}