<stubIndex implementation="org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnonymousClassIndex"/>
<referencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.ConstructorReferencesSearcher"/>
+ <referencesSearch implementation="org.jetbrains.plugins.groovy.findUsages.GrAliasedImportedElementSearcher"/>
+
<antCustomCompiler implementation="org.jetbrains.plugins.groovy.ant.GroovyAntCustomCompilerProvider"/>
<project.converterProvider implementation="org.jetbrains.plugins.groovy.config.GroovyModuleConverterProvider"/>
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.NullableComputable;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
}
};
- return helper.processElementsWithWord(processor,
- searchScope,
- propertyName,
- UsageSearchContext.IN_CODE,
- false);
+ return helper.processElementsWithWord(processor, searchScope, propertyName, UsageSearchContext.IN_CODE, false);
}
- private String getPropertyName(final PsiMethod method) {
- return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Nullable
+ private static String getPropertyName(final PsiMethod method) {
+ return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
+ @Nullable
public String compute() {
return GroovyPropertyUtils.getPropertyName(method);
}
--- /dev/null
+/*
+ * Copyright 2000-2010 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.groovy.findUsages;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.NullableComputable;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.TextOccurenceProcessor;
+import com.intellij.psi.search.UsageSearchContext;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * @author Maxim.Medvedev
+ */
+public class GrAliasedImportedElementSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
+ private static final ThreadLocal<Object> I_WAS_HERE = new ThreadLocal<Object>();
+
+ public boolean execute(final ReferencesSearch.SearchParameters parameters, final Processor<PsiReference> consumer) {
+ final PsiElement elementToSearch = parameters.getElementToSearch();
+ if (!(elementToSearch instanceof PsiMember)) return true;
+ if (I_WAS_HERE.get() != null) return true;
+
+ try {
+ I_WAS_HERE.set(Boolean.TRUE);
+ final TextOccurenceProcessor processor = new MyTextOccurenceProcessor(elementToSearch, consumer);
+
+ final SearchScope groovySearchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable<SearchScope>() {
+ public SearchScope compute() {
+ return parameters.getEffectiveSearchScope();
+ }
+ });
+
+ if (!ReferencesSearch.search(elementToSearch, groovySearchScope).forEach(new MyProcessor(null, processor))) return false;
+
+ if (elementToSearch instanceof PsiMethod && isAccessor(elementToSearch)) {
+ final PsiField field = ApplicationManager.getApplication().runReadAction(new Computable<PsiField>() {
+ public PsiField compute() {
+ return GroovyPropertyUtils.findFieldForAccessor((PsiMethod)elementToSearch, true);
+ }
+ });
+ if (field != null) {
+ final String prefix = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ public String compute() {
+ return GroovyPropertyUtils.getAccessorPrefix((PsiMethod)elementToSearch);
+ }
+ });
+ if (prefix == null) return true;
+ if (!ReferencesSearch.search(field, groovySearchScope).forEach(new MyProcessor(prefix, processor))) return false;
+ }
+ }
+ return true;
+ }
+ finally {
+ I_WAS_HERE.set(null);
+ }
+
+ }
+
+ private static Boolean isAccessor(final PsiElement elementToSearch) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ public Boolean compute() {
+ return GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)elementToSearch);
+ }
+ });
+ }
+
+ static class MyProcessor implements Processor<PsiReference> {
+ private final String prefix;
+ private final TextOccurenceProcessor processor;
+
+ MyProcessor(@Nullable String prefix, TextOccurenceProcessor processor) {
+ this.prefix = prefix;
+ this.processor = processor;
+ }
+
+ public boolean process(PsiReference psiReference) {
+ final PsiElement element = psiReference.getElement();
+ if (element == null) return true;
+
+ String alias = getAlias(element);
+ if (alias == null) return true;
+
+ final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
+ public PsiFile compute() {
+ return element.getContainingFile();
+ }
+ });
+
+ if (prefix != null) {
+ if (!PsiManager.getInstance(element.getProject()).getSearchHelper()
+ .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), prefix + GroovyPropertyUtils.capitalize(alias),
+ UsageSearchContext.IN_CODE,
+ false)) {
+ return false;
+ }
+ }
+
+ return PsiManager.getInstance(element.getProject()).getSearchHelper()
+ .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, false);
+ }
+
+ private static String getAlias(final PsiElement element) {
+ return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
+ public String compute() {
+ if (!(element.getParent() instanceof GrImportStatement)) return null;
+ final GrImportStatement importStatement = (GrImportStatement)element.getParent();
+ if (!importStatement.isAliasedImport()) return null;
+ return importStatement.getImportedName();
+ }
+ });
+ }
+
+ }
+
+static class MyTextOccurenceProcessor implements TextOccurenceProcessor {
+ private final PsiElement elementToSearch;
+ private final Processor<PsiReference> consumer;
+
+ public MyTextOccurenceProcessor(PsiElement elementToSearch, Processor<PsiReference> consumer) {
+ this.elementToSearch = elementToSearch;
+ this.consumer = consumer;
+ }
+
+ public boolean execute(PsiElement element, int offsetInElement) {
+ final PsiReference[] refs = element.getParent().getReferences();
+ for (PsiReference ref : refs) {
+ if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
+ if (ref.isReferenceTo(elementToSearch)) {
+ return consumer.process(ref);
+ }
+ }
+ }
+ return true;
+ }
+ }
+}
package org.jetbrains.plugins.groovy.lang.completion;
import com.intellij.codeInsight.completion.*;
-import com.intellij.codeInsight.lookup.*;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
public void consume(Object element) {
if (element instanceof PsiClass) {
final PsiClass clazz = (PsiClass)element;
- final MutableLookupElement<PsiClass> lookupElement = LookupElementFactory.getInstance().createLookupElement(clazz);
+ final LookupElement lookupElement = GroovyCompletionUtil.getLookupElement(clazz);
result.addElement(GroovyCompletionUtil.setTailTypeForConstructor(clazz, lookupElement));
+ } else if (element instanceof LookupElement && ((LookupElement)element).getObject() instanceof PsiClass) {
+ result.addElement(GroovyCompletionUtil
+ .setTailTypeForConstructor(((PsiClass)((LookupElement)element).getObject()), ((LookupElement)element)));
}
else {
- result.addElement(LookupItemUtil.objectToLookupItem(element));
+ result.addElement(GroovyCompletionUtil.getLookupElement(element));
}
}
});
// final boolean addGDKMethods = parameters.getInvocationCount() > 1;
((GrReferenceElement)reference).processVariants(new Consumer<Object>() {
public void consume(Object element) {
- LookupElement lookupElement = LookupItemUtil.objectToLookupItem(element);
+ LookupElement lookupElement = GroovyCompletionUtil.getLookupElement(element);
// if (lookupElement.getObject() instanceof GrGdkMethod && !addGDKMethods) return;
- if (lookupElement instanceof LookupItem) {
- lookupElement = ((LookupItem)lookupElement).setInsertHandler(new GroovyInsertHandlerAdapter());
- }
result.addElement(lookupElement);
}
});
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.util.Function;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
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.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*;
+
/**
* @author ilyas
*/
-public abstract class GroovyCompletionUtil {
+public class GroovyCompletionUtil {
+
+ private GroovyCompletionUtil() {
+ }
/**
* Return true if last element of curren statement is expression
*/
public static boolean endsWithExpression(PsiElement statement) {
while (statement != null &&
- !(statement instanceof GrExpression)) {
+ !(statement instanceof GrExpression)) {
statement = statement.getLastChild();
}
return statement != null;
public static PsiElement nearestLeftSibling(PsiElement elem) {
elem = elem.getPrevSibling();
while (elem != null &&
- (elem instanceof PsiWhiteSpace ||
+ (elem instanceof PsiWhiteSpace ||
elem instanceof PsiComment ||
GroovyTokenTypes.mNLS.equals(elem.getNode().getElementType()))) {
elem = elem.getPrevSibling();
return elem;
}
- public static boolean isIncomplete(PsiElement element) {
- while (element != null) {
- final PsiElement child = element.getLastChild();
- if (child instanceof PsiErrorElement) return true;
- element = child;
- }
- return false;
- }
-
/**
* Shows wether keyword may be placed asas a new statement beginning
*
return (previousLeaf == null || SEPARATORS.contains(previousLeaf.getNode().getElementType()));
}
+ @Nullable
public static PsiElement getLeafByOffset(int offset, PsiElement element) {
if (offset < 0) {
return null;
return variableDeclaration.getVariables()[0] == parent;
}
- /**
- * Checks next element after modifier candidate to be appropriate
- *
- * @param element
- * @return
- */
- public static boolean canBeModifier(PsiElement element) {
- PsiElement next = element.getNextSibling();
- while (next != null && (next instanceof PsiWhiteSpace ||
- next instanceof PsiComment)) {
- next = next.getNextSibling();
- }
- return (next == null || SEPARATORS.contains(next.getNode().getElementType()));
- }
-
private static final TokenSet SEPARATORS = TokenSet.create(GroovyElementTypes.mNLS,
- GroovyElementTypes.mSEMI);
+ GroovyElementTypes.mSEMI);
public static boolean asSimpleVariable(PsiElement context) {
return isInTypeDefinitionBody(context) &&
- isNewStatement(context, true);
+ isNewStatement(context, true);
}
public static boolean isInTypeDefinitionBody(PsiElement context) {
return (context.getParent() instanceof GrCodeReferenceElement &&
- context.getParent().getParent() instanceof GrClassTypeElement &&
- context.getParent().getParent().getParent() instanceof GrTypeDefinitionBody) ||
- context.getParent() instanceof GrTypeDefinitionBody;
+ context.getParent().getParent() instanceof GrClassTypeElement &&
+ context.getParent().getParent().getParent() instanceof GrTypeDefinitionBody) ||
+ context.getParent() instanceof GrTypeDefinitionBody;
}
public static boolean asVariableInBlock(PsiElement context) {
if (context.getParent() instanceof GrReferenceExpression &&
(context.getParent().getParent() instanceof GrOpenBlock ||
- context.getParent().getParent() instanceof GrClosableBlock) &&
+ context.getParent().getParent() instanceof GrClosableBlock) &&
isNewStatement(context, true)) {
return true;
}
if (context.getParent() instanceof GrReferenceExpression &&
context.getParent().getParent() instanceof GrApplicationStatement &&
(context.getParent().getParent().getParent() instanceof GrOpenBlock ||
- context.getParent().getParent().getParent() instanceof GrClosableBlock) &&
+ context.getParent().getParent().getParent() instanceof GrClosableBlock) &&
isNewStatement(context, true)) {
return true;
}
return context.getParent() instanceof GrTypeDefinitionBody &&
- isNewStatement(context, true);
- }
-
- public static boolean inMemberDeclaration(PsiElement context) {
- if (context.getParent() instanceof GrReferenceElement &&
- context.getParent().getParent() instanceof GrTypeElement) {
- PsiElement parent = context.getParent().getParent().getParent();
- if (parent instanceof GrMethod || parent instanceof GrVariableDeclaration) {
- return parent.getParent() instanceof GrTypeDefinitionBody || parent.getParent() instanceof GroovyFile;
- }
- }
- return false;
+ isNewStatement(context, true);
}
public static boolean asTypedMethod(PsiElement context) {
return context.getParent() instanceof GrReferenceElement &&
- context.getParent().getParent() instanceof GrTypeElement &&
- context.getParent().getParent().getParent() instanceof GrMethod &&
- context.getParent().getParent().getParent().getParent() instanceof GrTypeDefinitionBody &&
- context.getTextRange().getStartOffset() == context.getParent().getParent().getParent().getParent().getTextRange().getStartOffset();
+ context.getParent().getParent() instanceof GrTypeElement &&
+ context.getParent().getParent().getParent() instanceof GrMethod &&
+ context.getParent().getParent().getParent().getParent() instanceof GrTypeDefinitionBody &&
+ context.getTextRange().getStartOffset() ==
+ context.getParent().getParent().getParent().getParent().getTextRange().getStartOffset();
}
public static Object[] getCompletionVariants(GroovyResolveResult[] candidates) {
Object[] result = new Object[candidates.length];
+ Outer:
for (int i = 0; i < result.length; i++) {
final PsiElement element = candidates[i].getElement();
final PsiElement context = candidates[i].getCurrentFileResolveContext();
- if (context instanceof GrImportStatement) {
- final String importedName = ((GrImportStatement) context).getImportedName();
- if (importedName != null && element != null) {
- result[i] = LookupElementBuilder.create(element, importedName).setPresentableText(importedName);
- continue;
+ if (context instanceof GrImportStatement && element != null) {
+ final String importedName = ((GrImportStatement)context).getImportedName();
+ if (importedName != null) {
+ final GrCodeReferenceElement importReference = ((GrImportStatement)context).getImportReference();
+ if (importReference != null) {
+ final GroovyResolveResult[] results = importReference.multiResolve(false);
+ for (GroovyResolveResult r : results) {
+ final PsiElement resolved = r.getElement();
+ if (PsiManager.getInstance(context.getProject()).areElementsEquivalent(resolved, element)) {
+ result[i] = generateLookupForImportedElement(candidates[i], importedName);
+ continue Outer;
+ }
+ else {
+ if (resolved instanceof PsiField && element instanceof PsiMethod && isAccessorFor((PsiMethod)element, (PsiField)resolved)) {
+ result[i] =
+ generateLookupForImportedElement(candidates[i], getAccessorPrefix((PsiMethod)element) + capitalize(importedName));
+ continue Outer;
+ }
+ }
+
+ }
+ }
}
}
result[i] = element;
return result;
}
- public static LookupElement setTailTypeForConstructor(PsiClass clazz, LookupElement lookupElement) {
- return LookupElementDecorator.withInsertHandler(lookupElement, ParenthesesInsertHandler.getInstance(hasConstructorParameters(clazz)));
+ private static LookupElementBuilder generateLookupForImportedElement(GroovyResolveResult resolveResult, String importedName) {
+ final PsiElement element = resolveResult.getElement();
+ assert element != null;
+ final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
+ LookupElementBuilder builder = LookupElementBuilder.create(element, importedName).setPresentableText(importedName);
+ return setupLookupBuilder(element, substitutor, builder);
+ }
+
+ public static LookupElement getLookupElement(Object o) {
+ if (o instanceof LookupElement) return (LookupElement)o;
+ if (o instanceof PsiNamedElement) return generateLookupElement((PsiNamedElement)o);
+ if (o instanceof PsiElement) return setupLookupBuilder((PsiElement)o, PsiSubstitutor.EMPTY, LookupElementBuilder.create(o, ((PsiElement)o).getText()));
+ return LookupElementBuilder.create(o, o.toString());
+ }
+ public static LookupElementBuilder generateLookupElement(PsiNamedElement element) {
+ LookupElementBuilder builder = LookupElementBuilder.create(element);
+ return setupLookupBuilder(element, PsiSubstitutor.EMPTY, builder);
+ }
+
+ public static LookupElementBuilder setupLookupBuilder(PsiElement element, PsiSubstitutor substitutor, LookupElementBuilder builder) {
+ builder = builder.setIcon(element.getIcon(Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS))
+ .setInsertHandler(new GroovyInsertHandler());
+ builder = setTailText(element, builder, substitutor);
+ builder = setTypeText(element, builder, substitutor);
+ return builder;
+ }
+
+ private static LookupElementBuilder setTailText(PsiElement element, LookupElementBuilder builder, PsiSubstitutor substitutor) {
+ if (element instanceof PsiMethod) {
+ builder = builder.setTailText(PsiFormatUtil.formatMethod((PsiMethod)element, substitutor, PsiFormatUtil.SHOW_PARAMETERS,
+ PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE));
+ }
+ else if (element instanceof PsiClass) {
+ String tailText = getPackageText((PsiClass)element);
+ final PsiClass psiClass = (PsiClass)element;
+ if ((substitutor == null || substitutor.getSubstitutionMap().size() == 0) && psiClass.getTypeParameters().length > 0) {
+ tailText = "<" + StringUtil.join(psiClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
+ public String fun(PsiTypeParameter psiTypeParameter) {
+ return psiTypeParameter.getName();
+ }
+ }, "," + (showSpaceAfterComma(psiClass) ? " " : "")) + ">" + tailText;
+ }
+ builder = builder.setTailText(tailText, true);
+ }
+ return builder;
+ }
+
+ private static String getPackageText(PsiClass psiClass) {
+ @NonNls String packageName = PsiFormatUtil.getPackageDisplayName(psiClass);
+ return " (" + packageName + ")";
+ }
+
+
+ private static boolean showSpaceAfterComma(PsiClass element) {
+ return CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_AFTER_COMMA;
+ }
+
+
+ private static LookupElementBuilder setTypeText(PsiElement element, LookupElementBuilder builder, PsiSubstitutor substitutor) {
+ if (element instanceof PsiVariable) {
+ builder = builder.setTypeText(substitutor.substitute(((PsiVariable)element).getType()).getPresentableText());
+ }
+ else if (element instanceof PsiMethod) {
+ final PsiType type = substitutor.substitute(((PsiMethod)element).getReturnType());
+ if (type != null) {
+ builder = builder.setTypeText(type.getPresentableText());
+ }
+ }
+ return builder;
}
public static boolean hasConstructorParameters(PsiClass clazz) {
return false;
}
-
+ public static LookupElement setTailTypeForConstructor(PsiClass clazz, LookupElement lookupElement) {
+ return LookupElementDecorator.withInsertHandler(lookupElement, ParenthesesInsertHandler.getInstance(hasConstructorParameters(clazz)));
+ }
}
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
-import org.jetbrains.plugins.groovy.lang.resolve.processors.AccessorResolverProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
/**
}
ResolveState state = _state.put(ResolverProcessor.RESOLVE_CONTEXT, this);
- JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
if (isOnDemand()) {
- GrCodeReferenceElement ref = getImportReference();
- if (ref != null) {
- if (isStatic()) {
- final PsiElement resolved = ref.resolve();
- if (resolved instanceof PsiClass) {
- final PsiClass clazz = (PsiClass)resolved;
- if (clazz != null) {
- if (!processAllMembers(processor, clazz)) return false;
+ if (!processDeclarationsForMultipleElements(processor, lastParent, place, state)) return false;
+ }
+ else {
+ if (!processDeclarationsForSingleElement(processor, state)) return false;
+ }
+
+ return true;
+ }
+
+ private boolean processDeclarationsForSingleElement(PsiScopeProcessor processor, ResolveState state) {
+ JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
+ String name = getImportedName();
+ if (name == null) return true;
+
+ NameHint nameHint = processor.getHint(NameHint.KEY);
+
+ GrCodeReferenceElement ref = getImportReference();
+ if (ref == null) return true;
+
+ String qName = ref.getCanonicalText();
+ if (qName.indexOf('.') <= 0) return true;
+
+ if (isStatic()) {
+ final int i = qName.lastIndexOf('.');
+ if (i > 0) {
+ final String classQName = qName.substring(0, i);
+ PsiClass clazz = facade.findClass(classQName, getResolveScope());
+ if (clazz != null) {
+ final String refName = ref.getReferenceName();
+ if (nameHint == null || name.equals(nameHint.getName(state))) {
+ final PsiField field = clazz.findFieldByName(refName, false);
+ if (field != null && field.hasModifierProperty(PsiModifier.STATIC)) {
+ if (!processor.execute(field, state)) return false;
}
- }
- }
- else {
- String qName = PsiUtil.getQualifiedReferenceText(ref);
- if (qName != null) {
- PsiPackage aPackage = facade.findPackage(qName);
- if (aPackage != null) {
- if (!aPackage.processDeclarations(processor, state, lastParent, place)) return false;
+
+ for (PsiMethod method : clazz.findMethodsByName(refName, false)) {
+ if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ if (!processor.execute(method, state)) return false;
+ }
}
}
+
+ final PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, refName, true, true);
+ if (getter != null &&
+ (nameHint == null || name.equals(GroovyPropertyUtils.getPropertyNameByGetterName(nameHint.getName(state), true)))) {
+ if (!processor.execute(getter, state)) return false;
+ }
+
+ final PsiMethod setter = GroovyPropertyUtils.findPropertySetter(clazz, refName, true, true);
+ if (setter != null &&
+ (nameHint == null || name.equals(GroovyPropertyUtils.getPropertyNameBySetterName(nameHint.getName(state))))) {
+ if (!processor.execute(setter, state)) return false;
+ }
}
}
}
else {
- String name = getImportedName();
- if (name != null) {
- NameHint nameHint = processor.getHint(NameHint.KEY);
- //todo [DIANA] look more carefully
-
- GrCodeReferenceElement ref = getImportReference();
- if (ref != null) {
- String qName = ref.getCanonicalText();
- if (qName != null && qName.indexOf('.') > 0) {
- if (!isStatic()) {
- if (nameHint == null || name.equals(nameHint.getName(state))) {
- PsiClass clazz = facade.findClass(qName, getResolveScope());
- if (clazz != null && !processor.execute(clazz, state)) return false;
- }
- }
- else {
- final int i = qName.lastIndexOf('.');
- if (i > 0) {
- final String classQName = qName.substring(0, i);
- PsiClass clazz = facade.findClass(classQName, getResolveScope());
- if (clazz != null) {
- final String refName = ref.getReferenceName();
- if (nameHint == null || name.equals(nameHint.getName(state))) {
- final PsiField field = clazz.findFieldByName(refName, false);
- if (field != null && field.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(field, state)) {
- return false;
- }
-
- for (PsiMethod method : clazz.findMethodsByName(refName, false)) {
- if (method.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(method, state)) return false;
- }
- }
-
- if (processor instanceof AccessorResolverProcessor) {
- final PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, refName, true, true);
- if (getter != null &&
- (nameHint == null ||
- name.equals(GroovyPropertyUtils.getPropertyNameByGetterName(nameHint.getName(state), true)))) {
- processor.execute(getter, state);
- }
-
- final PsiMethod setter = GroovyPropertyUtils.findPropertySetter(clazz, refName, true, true);
- if (setter != null &&
- (nameHint == null || name.equals(GroovyPropertyUtils.getPropertyNameBySetterName(nameHint.getName(state))))) {
- processor.execute(setter, state);
- }
- }
- }
- }
- }
- }
+ if (nameHint == null || name.equals(nameHint.getName(state))) {
+ PsiClass clazz = facade.findClass(qName, getResolveScope());
+ if (clazz != null) {
+ if (!processor.execute(clazz, state)) return false;
}
}
}
+ return true;
+ }
+ private boolean processDeclarationsForMultipleElements(PsiScopeProcessor processor,
+ PsiElement lastParent,
+ PsiElement place,
+ ResolveState state) {
+ GrCodeReferenceElement ref = getImportReference();
+ if (ref == null) return true;
+
+ if (isStatic()) {
+ final PsiElement resolved = ref.resolve();
+ if (resolved instanceof PsiClass) {
+ final PsiClass clazz = (PsiClass)resolved;
+ if (!processAllMembers(processor, clazz)) return false;
+ }
+ }
+ else {
+ String qName = PsiUtil.getQualifiedReferenceText(ref);
+ if (qName != null) {
+ PsiPackage aPackage = JavaPsiFacade.getInstance(getProject()).findPackage(qName);
+ if (aPackage != null) {
+ if (!aPackage.processDeclarations(processor, state, lastParent, place)) return false;
+ }
+ }
+ }
return true;
}
}
public boolean isReferenceTo(PsiElement element) {
- return getManager().areElementsEquivalent(element, resolve());
+ final PsiManager manager = getManager();
+ if (element instanceof PsiNamedElement && getParent() instanceof GrImportStatement) {
+ final GroovyResolveResult[] results = multiResolve(false);
+ for (GroovyResolveResult result : results) {
+ if (manager.areElementsEquivalent(result.getElement(), element)) return true;
+ }
+ }
+ return manager.areElementsEquivalent(element, resolve());
}
@NotNull
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
public class GroovyPropertyUtils {
private static final String IS_PREFIX = "is";
private static final String GET_PREFIX = "get";
+ private static final String SET_PREFIX = "set";
private GroovyPropertyUtils() {
}
@Nullable
public static String getPropertyNameBySetterName(String methodName) {
- if (methodName.startsWith("set") && methodName.length() > 3) {
+ if (methodName.startsWith(SET_PREFIX) && methodName.length() > 3) {
return StringUtil.decapitalize(methodName.substring(3));
}
else {
/**
* Returns getter names in priority order
+ *
* @param name property name
* @return getter names
*/
}
public static String[] suggestSettersName(@NotNull String name) {
- return new String[]{"set"+capitalize(name)};
+ return new String[]{SET_PREFIX + capitalize(name)};
}
public static boolean isSetterName(String name) {
- return name != null && name.startsWith("set") && name.length() > 3 && isUpperCase(name.charAt(3));
+ return name != null && name.startsWith(SET_PREFIX) && name.length() > 3 && isUpperCase(name.charAt(3));
}
public static boolean isProperty(@Nullable PsiClass aClass, @Nullable String propertyName, boolean isStatic) {
return Introspector.decapitalize(s);
}
+ @Nullable
+ public static PsiField findFieldForAccessor(PsiMethod accessor, boolean checkSuperClasses) {
+ final PsiClass psiClass = accessor.getContainingClass();
+ if (psiClass == null) return null;
+ PsiField field = null;
+ if (!checkSuperClasses) {
+ field = psiClass.findFieldByName(getPropertyNameByAccessorName(accessor.getName()), true);
+ }
+ else {
+ final String name = getPropertyNameByAccessorName(accessor.getName());
+ assert name != null;
+ final PsiField[] allFields = psiClass.getAllFields();
+ for (PsiField psiField : allFields) {
+ if (name.equals(psiField.getName())) {
+ field = psiField;
+ break;
+ }
+ }
+ }
+ if (field == null) return null;
+ if (field.hasModifierProperty(GrModifier.STATIC) == accessor.hasModifierProperty(GrModifier.STATIC)) {
+ return field;
+ }
+ return null;
+ }
+
+ @Nullable
+ public static String getGetterPrefix(PsiMethod getter) {
+ final String name = getter.getName();
+ if (name.startsWith(GET_PREFIX)) return GET_PREFIX;
+ if (name.startsWith(IS_PREFIX)) return IS_PREFIX;
+
+ return null;
+ }
+
+ @Nullable
+ public static String getSetterPrefix(PsiMethod setter) {
+ if (setter.getName().startsWith(SET_PREFIX)) return SET_PREFIX;
+ return null;
+ }
+
+ @Nullable
+ public static String getAccessorPrefix(PsiMethod method) {
+ final String prefix = getGetterPrefix(method);
+ if (prefix != null) return prefix;
+
+ return getSetterPrefix(method);
+ }
+
+ public static boolean isAccessorFor(PsiMethod accessor, PsiField field) {
+ final String accessorName = accessor.getName();
+ final String fieldName = field.getName();
+ if (!ArrayUtil.contains(accessorName, suggestGettersName(fieldName)) &&
+ !ArrayUtil.contains(accessorName, suggestSettersName(fieldName))) {
+ return false;
+ }
+ final PsiClass accessorClass = accessor.getContainingClass();
+ final PsiClass fieldClass = field.getContainingClass();
+ if (!field.getManager().areElementsEquivalent(accessorClass, fieldClass)) return false;
+ return accessor.hasModifierProperty(GrModifier.STATIC) == field.hasModifierProperty(GrModifier.STATIC);
+ }
}
}
public void testTypeAlias() throws Throwable {
+ doTestImpl("A.groovy", 2);
+ }
+
+ public void testMethodAlias() throws Throwable {
+ doTestImpl("A.groovy", 2);
+ }
+
+ public void testAliasImportedProperty() throws Throwable {
+ myFixture.addFileToProject("Abc.groovy", "class Abc {static def foo}");
doTestImpl("A.groovy", 1);
}
+ public void testGetterWhenAliasedImportedProperty() throws Throwable {
+ myFixture.addFileToProject("Abc.groovy", "class Abc {static def foo}");
+ doTestImpl("A.groovy", 2);
+ }
+
public void testForInParameter() throws Throwable {
doTestImpl("A.groovy", 1);
}
""")
def ref = findReference()
def resolved = ref.resolve()
- assertNull resolved
+ assertInstanceOf resolved, GrAccessorMethod
}
public void testPropertyInCallExpression() {
def resolved = ref.resolve()
assertInstanceOf(resolved, GrField)
}
+
+ public void testSetterToAliasedImportedProperty() {
+ myFixture.addFileToProject("a.groovy", """class Foo {
+ static def bar
+}""")
+ myFixture.configureByText("b.groovy", """import static Foo.bar as foo
+set<caret>Foo(2)
+""")
+ def ref = findReference()
+ def resolved = ref.resolve()
+ assertInstanceOf resolved, GrAccessorMethod
+ }
+
+ public void testPhysicalSetterToStaticallyImportedProperty() {
+ myFixture.addFileToProject("a.groovy", """class Foo {
+ static def bar
+ static def setBar(def bar){}
+}""")
+ myFixture.configureByText("b.groovy", """import static Foo.bar as foo
+set<caret>Foo(2)
+""")
+ def ref = findReference()
+ def resolved = ref.resolve()
+ assertInstanceOf resolved, GrMethod
+ }
}
\ No newline at end of file
--- /dev/null
+import static Abc.f<caret>oo as bar
+
+print getBar()
+
+setBar 2
+
+bar = 4;
+bar++
\ No newline at end of file
--- /dev/null
+import static Abc.foo as bar
+
+print getBa<caret>r()
+
+setBar 2
+
+bar = 4;
+bar++
\ No newline at end of file
--- /dev/null
+import static java.lang.Math.min as alias
+
+print al<caret>ias(1, 2)
\ No newline at end of file