IDEA-99150 Groovy: correct processing of script classes in Java

This commit is contained in:
Max Medvedev
2013-01-16 13:35:31 +04:00
parent 1d3d3b28a2
commit 540f45ee1e
2 changed files with 62 additions and 69 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -16,35 +16,34 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.*;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import javax.swing.*;
import java.util.ArrayList;
@@ -209,20 +208,30 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
@NotNull
public PsiMethod[] getMethods() {
GrMethod[] methods = myFile.getMethods();
byte hasMain = 1;
byte hasRun = 1;
for (GrMethod method : methods) {
if (method.isEquivalentTo(myMainMethod)) hasMain = 0;
else if (method.isEquivalentTo(myRunMethod)) hasRun = 0;
}
if (hasMain + hasRun == 0) return methods;
return CachedValuesManager.getManager(getProject()).getCachedValue(this, new CachedValueProvider<PsiMethod[]>() {
@Nullable
@Override
public Result<PsiMethod[]> compute() {
PsiMethod[] methods = myFile.getMethods();
PsiMethod[] result = new PsiMethod[methods.length + hasMain + hasRun];
if (hasMain == 1) result[0] = myMainMethod;
if (hasRun == 1) result[hasMain] = myRunMethod;
System.arraycopy(methods, 0, result, hasMain + hasRun, methods.length);
return result;
byte hasMain = 1;
byte hasRun = 1;
for (PsiMethod method : methods) {
if (method.isEquivalentTo(myMainMethod)) {
hasMain = 0;
}
else if (method.isEquivalentTo(myRunMethod)) hasRun = 0;
}
if (hasMain + hasRun == 0) return Result.create(methods, myFile);
PsiMethod[] result = new PsiMethod[methods.length + hasMain + hasRun];
if (hasMain == 1) result[0] = myMainMethod;
if (hasRun == 1) result[hasMain] = myRunMethod;
System.arraycopy(methods, 0, result, hasMain + hasRun, methods.length);
return Result.create(result, myFile);
}
});
}
@NotNull
@@ -257,11 +266,11 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
@NotNull
public PsiClass[] getAllInnerClasses() {
return PsiClass.EMPTY_ARRAY;
return PsiClassImplUtil.getAllInnerClasses(this);
}
public PsiField findFieldByName(String name, boolean checkBases) {
return null;
return PsiClassImplUtil.findFieldByName(this, name, checkBases);
}
public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) {
@@ -280,16 +289,16 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
@NotNull
public List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(String name, boolean checkBases) {
return new ArrayList<Pair<PsiMethod, PsiSubstitutor>>();
return PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases);
}
@NotNull
public List<Pair<PsiMethod, PsiSubstitutor>> getAllMethodsAndTheirSubstitutors() {
return new ArrayList<Pair<PsiMethod, PsiSubstitutor>>();
return PsiClassImplUtil.getAllWithSubstitutorsByMap(this, PsiClassImplUtil.MemberType.METHOD);
}
public PsiClass findInnerClassByName(String name, boolean checkBases) {
return null;
return PsiClassImplUtil.findInnerByName(this, name, checkBases);
}
public PsiTypeParameterList getTypeParameterList() {
@@ -388,40 +397,7 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
@NotNull final ResolveState state,
@Nullable PsiElement lastParent,
@NotNull PsiElement place) {
for (GrTopLevelDefinition definition : myFile.getTopLevelDefinitions()) {
if (!(definition instanceof PsiClass)) {
if (!ResolveUtil.processElement(processor, definition, state)) return false;
}
}
for (GrVariable variable : getScriptFields()) {
if (!GrClassImplUtil.isSameDeclaration(place, variable)) {
if (!ResolveUtil.processElement(processor, variable, state)) {
return false;
}
}
}
if (!ResolveUtil.processElement(processor, myMainMethod, state) || !ResolveUtil.processElement(processor, myRunMethod, state)) {
return false;
}
final PsiClass scriptClass = getSuperClass();
//noinspection RedundantIfStatement
if (scriptClass != null && !scriptClass.processDeclarations(new BaseScopeProcessor() {
public boolean execute(@NotNull PsiElement element, ResolveState state) {
return !(element instanceof PsiNamedElement) || ResolveUtil.processElement(processor, (PsiNamedElement)element, state);
}
@Override
public <T> T getHint(@NotNull Key<T> hintKey) {
return processor.getHint(hintKey);
}
}, state, lastParent, place)) {
return false;
}
return true;
return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, ContainerUtil.<PsiClass>newHashSet(), lastParent, place, false);
}
@Override
@@ -1,17 +1,17 @@
/*
* Copyright 2000-2007 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
* Copyright 2000-2013 JetBrains s.r.o.
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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
*
* 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.
* 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.groovy.lang.resolve;
@@ -25,6 +25,7 @@ import com.intellij.psi.impl.light.LightMethodBuilder
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod
import org.jetbrains.plugins.groovy.util.TestUtils
/**
@@ -86,4 +87,20 @@ class A {
assertNotNull(ref.resolve())
}
void testScriptMethods() {
myFixture.addFileToProject('Foo.groovy', '''\
void foo(int x = 5) {}
void foo(String s) {}
''')
final ref = configureByText('A.java', '''\
class A {
void bar() {
new Foo().fo<caret>o()
}
}''')
assertInstanceOf(ref.resolve(), GrReflectedMethod)
}
}