diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index 929aac917e50..2c8ec7438bfb 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -67,6 +67,7 @@
+
@@ -170,6 +171,7 @@
+
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt
index a2dabe81ec5c..01269ca7ffa8 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleArtifactsContributor.kt
@@ -31,6 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod
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.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.patterns.groovyClosure
@@ -57,7 +58,8 @@ class GradleArtifactsContributor : GradleMethodContextContributor {
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)
+ val myPsi = GrLightField(text, JAVA_LANG_OBJECT, place)
+ processor.execute(myPsi, state)
return false
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java
index 732645d7c305..8c809e22b926 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleCommonClassNames.java
@@ -45,6 +45,7 @@ public final class GradleCommonClassNames {
@NonNls public static final String GRADLE_API_DISTRIBUTION_CONTAINER = "org.gradle.api.distribution.DistributionContainer";
@NonNls public static final String GRADLE_API_DISTRIBUTION = "org.gradle.api.distribution.Distribution";
@NonNls public static final String GRADLE_API_FILE_COPY_SPEC = "org.gradle.api.file.CopySpec";
+ @NonNls public static final String GRADLE_API_FILE_CONFIGURABLE_FILE_TREE = "org.gradle.api.file.ConfigurableFileTree";
@NonNls public static final String GRADLE_API_SCRIPT_HANDLER = "org.gradle.api.initialization.dsl.ScriptHandler";
@NonNls public static final String GRADLE_API_TASK = "org.gradle.api.Task";
@NonNls public static final String GRADLE_API_DEFAULT_TASK = "org.gradle.api.DefaultTask";
@@ -60,6 +61,8 @@ public final class GradleCommonClassNames {
@NonNls public static final String GRADLE_API_TASKS_DIAGNOSTICS_PROPERTY_REPORT_TASK = "org.gradle.api.tasks.diagnostics.PropertyReportTask";
@NonNls public static final String GRADLE_API_TASKS_DIAGNOSTICS_TASK_REPORT_TASK = "org.gradle.api.tasks.diagnostics.TaskReportTask";
@NonNls public static final String GRADLE_API_TASKS_TESTING_TEST = "org.gradle.api.tasks.testing.Test";
+ @NonNls public static final String GRADLE_API_JUNIT_OPTIONS = "org.gradle.api.tasks.testing.junit.JUnitOptions";
+ @NonNls public static final String GRADLE_API_TEST_LOGGING_CONTAINER = "org.gradle.api.tasks.testing.logging.TestLoggingContainer";
@NonNls public static final String GRADLE_API_TASKS_UPLOAD = "org.gradle.api.tasks.Upload";
@NonNls public static final String GRADLE_API_ARTIFACTS_REPOSITORIES_FLAT_DIRECTORY_ARTIFACT_REPOSITORY = "org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository";
@NonNls public static final String GRADLE_LANGUAGE_JVM_TASKS_PROCESS_RESOURCES = "org.gradle.language.jvm.tasks.ProcessResources";
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt
index 7e9fd14c5490..1d3a8f54360c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleIdeaPluginScriptContributor.kt
@@ -66,6 +66,12 @@ class GradleIdeaPluginScriptContributor : GradleMethodContextContributor {
if (ideaImlClosure.accepts(closure)) {
return DelegatesToInfo(TypesUtil.createType(IDEA_MODULE_IML_FQN, closure), Closure.DELEGATE_FIRST)
}
+ if (ideaProjectClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(IDEA_PROJECT_FQN, closure), Closure.DELEGATE_FIRST)
+ }
+ if (ideaModuleClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(IDEA_MODULE_FQN, closure), Closure.DELEGATE_FIRST)
+ }
return null
}
@@ -86,15 +92,10 @@ class GradleIdeaPluginScriptContributor : GradleMethodContextContributor {
}
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
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMiscContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMiscContributor.kt
new file mode 100644
index 000000000000..35d8b7a021cb
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleMiscContributor.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.PsiClass
+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.GroovyFile
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
+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.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.DELEGATES_TO_KEY
+import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo
+
+/**
+ * @author Vladislav.Soroka
+ *
+ * @since 11/24/2016
+ */
+class GradleMiscContributor : GradleMethodContextContributor {
+ companion object {
+ val useJUnitClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_TASKS_TESTING_TEST, "useJUnit"))
+ val testLoggingClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_TASKS_TESTING_TEST, "testLogging"))
+ val downloadClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "download"))
+ val domainCollectionWithTypeClosure = groovyClosure().inMethod(psiMethod("org.gradle.api.DomainObjectCollection", "withType"))
+
+ val downloadSpecFqn = "de.undercouch.gradle.tasks.download.DownloadSpec"
+ val pluginDependenciesSpecFqn = "org.gradle.plugin.use.PluginDependenciesSpec"
+ }
+
+ override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? {
+ if (useJUnitClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(GRADLE_API_JUNIT_OPTIONS, closure), Closure.DELEGATE_FIRST)
+ }
+ if (testLoggingClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(GRADLE_API_TEST_LOGGING_CONTAINER, closure), Closure.DELEGATE_FIRST)
+ }
+ if (downloadClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(downloadSpecFqn, closure), Closure.DELEGATE_FIRST)
+ }
+
+ if (domainCollectionWithTypeClosure.accepts(closure)) {
+ val parent = closure.parent
+ if (parent is GrMethodCallExpression) {
+ val psiElement = parent.argumentList.allArguments.singleOrNull()?.reference?.resolve()
+ if (psiElement is PsiClass) {
+ return DelegatesToInfo(TypesUtil.createType(psiElement.qualifiedName, closure), Closure.DELEGATE_FIRST)
+ }
+ }
+ }
+ return null
+ }
+
+ override fun process(methodCallInfo: MutableList, processor: PsiScopeProcessor, state: ResolveState, place: PsiElement): Boolean {
+
+ val classHint = processor.getHint(com.intellij.psi.scope.ElementClassHint.KEY)
+ val shouldProcessMethods = ResolveUtil.shouldProcessMethods(classHint)
+ val psiManager = GroovyPsiManager.getInstance(place.project)
+ val resolveScope = place.resolveScope
+
+ if (shouldProcessMethods && place.parent?.parent is GroovyFile && place.text == "plugins") {
+ val pluginsDependenciesClass = psiManager.findClassWithCache(pluginDependenciesSpecFqn, resolveScope) ?: return true
+ val returnClass = psiManager.createTypeByFQClassName(pluginDependenciesSpecFqn, resolveScope) ?: return true
+ val methodBuilder = GrLightMethodBuilder(place.manager, "plugins").apply {
+ containingClass = pluginsDependenciesClass
+ returnType = returnClass
+ }
+ methodBuilder.addAndGetParameter("configuration", GROOVY_LANG_CLOSURE, false).putUserData(DELEGATES_TO_KEY, pluginDependenciesSpecFqn)
+ place.putUserData(RESOLVED_CODE, true)
+ if (!processor.execute(methodBuilder, state)) return false
+ }
+
+ if (psiElement().inside(domainCollectionWithTypeClosure).accepts(place)) {
+
+ }
+ return true
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleNonCodeMembersContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleNonCodeMembersContributor.kt
new file mode 100644
index 000000000000..574284b4f419
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleNonCodeMembersContributor.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiType
+import com.intellij.psi.ResolveState
+import com.intellij.psi.scope.PsiScopeProcessor
+import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor
+
+/**
+ * @author Vladislav.Soroka
+ *
+ * @since 11/25/2016
+ */
+class GradleNonCodeMembersContributor : NonCodeMembersContributor() {
+ override fun processDynamicElements(qualifierType: PsiType,
+ aClass: PsiClass?,
+ processor: PsiScopeProcessor,
+ place: PsiElement,
+ state: ResolveState) {
+ if (aClass == null) return
+ val containingFile = place.containingFile
+ if (!containingFile.isGradleScript() || containingFile?.originalFile?.virtualFile == aClass.containingFile?.originalFile?.virtualFile) return
+
+ processDeclarations(aClass, processor, state, place)
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt
index 12fef0241940..180175ca5944 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleProjectContributor.kt
@@ -19,8 +19,7 @@ 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_FILE_COPY_SPEC
-import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT
+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
@@ -36,6 +35,7 @@ class GradleProjectContributor : GradleMethodContextContributor {
companion object {
val copySpecClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "copy", "copySpec"))
+ val fileTreeClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "fileTree"))
}
@@ -43,6 +43,9 @@ class GradleProjectContributor : GradleMethodContextContributor {
if (copySpecClosure.accepts(closure)) {
return DelegatesToInfo(TypesUtil.createType(GRADLE_API_FILE_COPY_SPEC, closure), Closure.DELEGATE_FIRST)
}
+ if (fileTreeClosure.accepts(closure)) {
+ return DelegatesToInfo(TypesUtil.createType(GRADLE_API_FILE_CONFIGURABLE_FILE_TREE, closure), Closure.DELEGATE_FIRST)
+ }
return null
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
index ff5a5b4bdea5..bf0dc6242340 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
@@ -60,25 +60,6 @@ public class GradleResolverUtil {
return argsCount;
}
- public static void addImplicitVariable(@NotNull PsiScopeProcessor processor,
- @NotNull ResolveState state,
- @NotNull GrReferenceExpressionImpl expression,
- @NotNull String type) {
- if (expression.getQualifier() == null && expression.getReferenceName() != null) {
- PsiVariable myPsi = new GrLightField(expression.getReferenceName(), type, expression);
- processor.execute(myPsi, state);
- }
- }
-
- public static void addImplicitVariable(@NotNull PsiScopeProcessor processor,
- @NotNull ResolveState state,
- @NotNull PsiElement element,
- @NotNull String type) {
- PsiVariable myPsi = new GrLightField(element.getText(), type, element);
- processor.execute(myPsi, state);
- }
-
-
@Nullable
public static GrLightMethodBuilder createMethodWithClosure(@NotNull String name,
@Nullable String returnType,
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java
index 185c287d61e1..402211b113ba 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java
@@ -53,13 +53,7 @@ public class GradleScriptContributor extends NonCodeMembersContributor {
@NotNull PsiScopeProcessor processor,
@NotNull PsiElement place,
@NotNull ResolveState state) {
- if (!(aClass instanceof GroovyScriptClass)) {
- return;
- }
-
- PsiFile file = aClass.getContainingFile();
- if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)
- || GradleConstants.SETTINGS_FILE_NAME.equals(file.getName())) return;
+ if(!UtilKt.isResolvedInGradleScript(aClass)) return;
List methodInfo = ContainerUtilRt.newArrayList();
for (GrMethodCall current = PsiTreeUtil.getParentOfType(place, GrMethodCall.class);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt
index d7bdcf02e099..d0313f17a367 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/util.kt
@@ -17,10 +17,9 @@ package org.jetbrains.plugins.gradle.service.resolve
import com.intellij.openapi.util.Key
import com.intellij.psi.*
-import com.intellij.psi.scope.BaseScopeProcessor
-import com.intellij.psi.scope.ElementClassHint
-import com.intellij.psi.scope.NameHint.KEY
import com.intellij.psi.scope.PsiScopeProcessor
+import org.jetbrains.plugins.gradle.util.GradleConstants.EXTENSION
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass
import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns
import java.util.*
@@ -28,51 +27,40 @@ import java.util.*
* @author Vladislav.Soroka
* @since 11/11/2016
*/
+internal fun PsiClass?.isResolvedInGradleScript() = this is GroovyScriptClass && this.containingFile.isGradleScript()
+
+internal fun PsiFile?.isGradleScript() = this?.originalFile?.virtualFile?.extension == EXTENSION
@JvmField val RESOLVED_CODE = Key.create("gradle.resolved")
-fun processDeclarations(handlerClass: PsiClass,
+fun processDeclarations(aClass: PsiClass,
processor: PsiScopeProcessor,
state: ResolveState,
place: PsiElement): Boolean {
- val name = processor.getHint(KEY)?.getName(state)
- val componentClass = handlerClass
- val componentProcessor = ComponentProcessor(processor, place, name)
+ val name = processor.getHint(com.intellij.psi.scope.NameHint.KEY)?.getName(state)
if (name == null) {
- if (!componentClass.processDeclarations(componentProcessor, state, null, place)) return false
+ aClass.processDeclarations(processor, state, null, place)
}
else {
+ val isSetterCandidate = name.startsWith("set")
val processedSignatures = HashSet>()
- for (method in componentClass.findMethodsByName(name, true)) {
- processedSignatures.add(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))
+ for (method in aClass.findMethodsByName(name, true)) {
+ if (!isSetterCandidate) {
+ processedSignatures.add(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))
+ }
place.putUserData(RESOLVED_CODE, true)
- if (!componentProcessor.execute(method, state)) return false
+ if (!processor.execute(method, state)) return false
}
- for (prefix in arrayOf("add", "set")) {
- for (method in componentClass.findMethodsByName(prefix + name.capitalize(), true)) {
+
+ if (!isSetterCandidate) {
+ for (method in aClass.findMethodsByName("set" + name.capitalize(), true)) {
if (processedSignatures.contains(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))) continue
place.putUserData(RESOLVED_CODE, true)
- if (!componentProcessor.execute(method, state)) return false
+ if (!processor.execute(method, state)) return false
}
}
}
return true
}
-class ComponentProcessor(val delegate: PsiScopeProcessor, val place: PsiElement, val name: String?) : BaseScopeProcessor() {
-
- override fun execute(method: PsiElement, state: ResolveState): Boolean {
- method as? PsiMethod ?: return true
- return delegate.execute(method, state)
- }
-
- override fun getHint(hintKey: Key): T? = if (hintKey == com.intellij.psi.scope.ElementClassHint.KEY) {
- @Suppress("UNCHECKED_CAST")
- ElementClassHint { it == com.intellij.psi.scope.ElementClassHint.DeclarationKind.METHOD } as T
- }
- else {
- null
- }
-}
-
fun psiMethodInClass(containingClass: String) = GroovyPatterns.psiMethod().definedInClass(containingClass)
\ No newline at end of file