diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index acc6f3a3d0a2..5f8a4ec9a260 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -31,6 +31,7 @@
+
@@ -72,6 +73,7 @@
+
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java
new file mode 100644
index 000000000000..61c3e1848183
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsContributor.java
@@ -0,0 +1,86 @@
+/*
+ * 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.PsiVariable;
+import com.intellij.psi.ResolveState;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ConfigurationContainer;
+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.GrImplicitVariableImpl;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 8/29/13
+ */
+public class GradleConfigurationsContributor implements GradleMethodContextContributor {
+
+ private static final String CONFIGURATIONS = "configurations";
+
+ @Override
+ public void process(@NotNull List methodCallInfo,
+ @NotNull PsiScopeProcessor processor,
+ @NotNull ResolveState state,
+ @NotNull PsiElement place) {
+ if (methodCallInfo.isEmpty()) {
+ return;
+ }
+ final String methodCall = methodCallInfo.get(0);
+
+ PsiClass contributorClass = null;
+ GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject());
+ if (methodCallInfo.size() == 1) {
+ if (methodCall.startsWith(CONFIGURATIONS + '.')) {
+ contributorClass = psiManager.findClassWithCache(Configuration.class.getName(), place.getResolveScope());
+ }
+ else if (CONFIGURATIONS.equals(methodCall)) {
+ contributorClass = psiManager.findClassWithCache(ConfigurationContainer.class.getName(), place.getResolveScope());
+ if (place instanceof GrReferenceExpressionImpl) {
+ addImplicitConfiguration(processor, state, (GrReferenceExpressionImpl)place);
+ return;
+ }
+ }
+ }
+ else if (methodCallInfo.size() == 2) {
+ if (CONFIGURATIONS.equals(methodCallInfo.get(1))) {
+ contributorClass = psiManager.findClassWithCache(ConfigurationContainer.class.getName(), place.getResolveScope());
+ if (place instanceof GrReferenceExpressionImpl) {
+ addImplicitConfiguration(processor, state, (GrReferenceExpressionImpl)place);
+ return;
+ }
+ }
+ }
+ if (contributorClass != null) {
+ contributorClass.processDeclarations(processor, state, null, place);
+ }
+ }
+
+ @SuppressWarnings("MethodMayBeStatic")
+ private void addImplicitConfiguration(@NotNull PsiScopeProcessor processor,
+ @NotNull ResolveState state,
+ @NotNull GrReferenceExpressionImpl expression) {
+ String expr = expression.getCanonicalText();
+ PsiVariable myPsi = new GrImplicitVariableImpl(expression.getManager(), expr, Configuration.class.getName(), expression);
+ processor.execute(myPsi, state);
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java
new file mode 100644
index 000000000000..54de0da26200
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleConfigurationsNonCodeMembersContributor.java
@@ -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.psi.*;
+import com.intellij.psi.impl.light.LightElement;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import com.intellij.psi.util.PsiTreeUtil;
+import groovy.lang.Closure;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ConfigurationContainer;
+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.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;
+
+/**
+ * @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,
+ PsiClass aClass,
+ PsiScopeProcessor processor,
+ PsiElement place,
+ ResolveState state) {
+ if (place == null) {
+ return;
+ }
+
+ if (!ConfigurationContainer.class.getName().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
+ GrReferenceExpressionImpl expression = (GrReferenceExpressionImpl)place;
+ String expr = expression.getCanonicalText();
+ GrImplicitVariableImpl myPsi = new GrImplicitVariableImpl(place.getManager(), expr, Configuration.class.getName(), place);
+ processor.execute(myPsi, state);
+ setNavigation(myPsi, dependencyHandlerClass, METHOD_GET_BY_NAME, 1);
+ return;
+ }
+ GrArgumentList args = call.getArgumentList();
+ if (args == null) {
+ return;
+ }
+ 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(Closure.class.getName())) {
+ element.setNavigationElement(method);
+ }
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java
index 2b980cc27c2c..06727fbe3802 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleDependenciesContributor.java
@@ -35,7 +35,7 @@ import java.util.List;
* @since 8/14/13 12:58 PM
*/
public class GradleDependenciesContributor implements GradleMethodContextContributor {
-
+
@Override
public void process(@NotNull List methodCallInfo,
@NotNull PsiScopeProcessor processor,
@@ -50,7 +50,7 @@ public class GradleDependenciesContributor implements GradleMethodContextContrib
if (i != 1) {
return;
}
-
+
// Assuming that the method call is addition of new dependency into configuration.
GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject());
PsiClass contributorClass = psiManager.findClassWithCache(DependencyHandler.class.getName(), place.getResolveScope());
@@ -70,7 +70,7 @@ public class GradleDependenciesContributor implements GradleMethodContextContrib
PsiClassType type = PsiType.getJavaLangObject(place.getManager(), place.getResolveScope());
builder.addParameter(new GrLightParameter("dependencyInfo", type, builder));
processor.execute(builder, state);
-
+
GrMethodCall call = PsiTreeUtil.getParentOfType(place, GrMethodCall.class);
if (call == null) {
return;
@@ -79,20 +79,8 @@ public class GradleDependenciesContributor implements GradleMethodContextContrib
if (args == null) {
return;
}
- int argsCount = 0;
- boolean namedArgProcessed = false;
- for (GroovyPsiElement arg : args.getAllArguments()) {
- if (arg instanceof GrNamedArgument) {
- if (!namedArgProcessed) {
- namedArgProcessed = true;
- argsCount++;
- }
- }
- else {
- argsCount++;
- }
- }
-
+
+ int argsCount = GradleResolverUtil.getGrMethodArumentsCount(args);
argsCount++; // Configuration name is delivered as an argument.
for (PsiMethod method : dependencyHandlerClass.findMethodsByName("add", false)) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
new file mode 100644
index 000000000000..fb2a539ac155
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 8/30/13
+ */
+public class GradleResolverUtil {
+
+ public static int getGrMethodArumentsCount(GrArgumentList args) {
+ int argsCount = 0;
+ boolean namedArgProcessed = false;
+ for (GroovyPsiElement arg : args.getAllArguments()) {
+ if (arg instanceof GrNamedArgument) {
+ if (!namedArgProcessed) {
+ namedArgProcessed = true;
+ argsCount++;
+ }
+ }
+ else {
+ argsCount++;
+ }
+ }
+ return argsCount;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java
index 2e5613f5a77e..d30ef89d6d03 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleRootContributor.java
@@ -19,12 +19,13 @@ 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.Stack;
+import com.intellij.util.containers.ContainerUtil;
import org.gradle.api.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import java.util.List;
+import java.util.Set;
/**
* @author Denis Zhdanov
@@ -32,12 +33,22 @@ import java.util.List;
*/
public class GradleRootContributor implements GradleMethodContextContributor {
+ private final static Set PROJECT_ACTIONS = ContainerUtil.newHashSet(
+ "subprojects",
+ "allprojects",
+ "beforeEvaluate",
+ "afterEvaluate");
+
@Override
public void process(@NotNull List methodCallInfo,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
- if (methodCallInfo.size() > 1) {
+ if(methodCallInfo.size() > 2) {
+ return;
+ }
+
+ if (methodCallInfo.size() == 2 && !PROJECT_ACTIONS.contains(methodCallInfo.get(1))) {
return;
}