From 2e70734cc1421a165aadb91a7aa2f11404d369b5 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 10 Jun 2010 14:21:18 +0400 Subject: [PATCH 01/81] find usages & completion for aliased imported members --- plugins/groovy/src/META-INF/plugin.xml | 2 + .../GrAliasedImportedElementSearcher.java | 134 +++++++++++++ .../GroovyCompletionContributor.java | 17 +- .../lang/completion/GroovyCompletionUtil.java | 182 ++++++++++++------ .../imports/GrImportStatementImpl.java | 148 +++++++------- .../types/GrCodeReferenceElementImpl.java | 9 +- .../lang/psi/util/GroovyPropertyUtils.java | 71 ++++++- .../lang/findUsages/FindUsagesTest.java | 6 +- .../lang/resolve/ResolvePropertyTest.groovy | 27 ++- .../testdata/findUsages/methodAlias/A.groovy | 3 + 10 files changed, 458 insertions(+), 141 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java create mode 100644 plugins/groovy/testdata/findUsages/methodAlias/A.groovy diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 32f213571706..9cc9d2b1bb2e 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -209,6 +209,8 @@ + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java new file mode 100644 index 000000000000..fd94725717ce --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java @@ -0,0 +1,134 @@ +/* + * 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.Key; +import com.intellij.openapi.util.NullableComputable; +import com.intellij.psi.*; +import com.intellij.psi.search.*; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.util.Processor; +import com.intellij.util.QueryExecutor; +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 { + private static final Key SEARCHING_FOR_IT = Key.create("SEARCHING_FOR_IT"); + + public boolean execute(final ReferencesSearch.SearchParameters parameters, final Processor consumer) { + final PsiElement elementToSearch = parameters.getElementToSearch(); + if (!(elementToSearch instanceof PsiMember)) return true; + if (elementToSearch.getUserData(SEARCHING_FOR_IT) != null) return true; + try { + elementToSearch.putUserData(SEARCHING_FOR_IT, Boolean.TRUE); + final TextOccurenceProcessor processor = new TextOccurenceProcessor() { + 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; + } + }; + final PsiSearchHelper helper = PsiManager.getInstance(elementToSearch.getProject()).getSearchHelper(); + + final SearchScope groovySearchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { + public SearchScope compute() { + return parameters.getEffectiveSearchScope(); + } + }); + + if (!ReferencesSearch.search(elementToSearch, groovySearchScope).forEach(new Processor() { + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + String alias = ApplicationManager.getApplication().runReadAction(new NullableComputable() { + public String compute() { + if (!(element.getParent() instanceof GrImportStatement)) return null; + final GrImportStatement importStatement = (GrImportStatement)element.getParent(); + if (!importStatement.isAliasedImport()) return null; + return importStatement.getImportedName(); + } + }); + if (alias == null) return true; + + final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile compute() { + return element.getContainingFile(); + } + }); + + return helper + .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, false); + } + })) return false; + + if (elementToSearch instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)elementToSearch)) { + final PsiField field = GroovyPropertyUtils.findFieldForAccessor((PsiMethod)elementToSearch, true); + if (field != null) { + try { + field.putUserData(SEARCHING_FOR_IT, Boolean.TRUE); + if (!ReferencesSearch.search(field, groovySearchScope).forEach(new Processor() { + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + String alias = ApplicationManager.getApplication().runReadAction(new NullableComputable() { + public String compute() { + if (!(element.getParent() instanceof GrImportStatement)) return null; + final GrImportStatement importStatement = (GrImportStatement)element.getParent(); + if (!importStatement.isAliasedImport()) return null; + return importStatement.getImportedName(); + } + }); + if (alias == null) return true; + final String prefix = GroovyPropertyUtils.getAccessorPrefix((PsiMethod)elementToSearch); + if (prefix == null) return true; + + alias = prefix + alias; + final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile compute() { + return element.getContainingFile(); + } + }); + + return helper + .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, + false); + } + })) { + return false; + } + } + finally { + field.putUserData(SEARCHING_FOR_IT, null); + } + } + } + return true; + } + finally { + elementToSearch.putUserData(SEARCHING_FOR_IT, null); + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 1d9367cca069..b1760594c8bb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -16,7 +16,10 @@ 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; @@ -109,11 +112,14 @@ public class GroovyCompletionContributor extends CompletionContributor { public void consume(Object element) { if (element instanceof PsiClass) { final PsiClass clazz = (PsiClass)element; - final MutableLookupElement 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)); } } }); @@ -123,11 +129,8 @@ public class GroovyCompletionContributor extends CompletionContributor { // final boolean addGDKMethods = parameters.getInvocationCount() > 1; ((GrReferenceElement)reference).processVariants(new Consumer() { 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); } }); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java index 3969ebb13f53..f09e23bc2fd7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java @@ -20,13 +20,18 @@ import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; 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; @@ -44,10 +49,15 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; 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 @@ -57,7 +67,7 @@ public abstract class GroovyCompletionUtil { */ public static boolean endsWithExpression(PsiElement statement) { while (statement != null && - !(statement instanceof GrExpression)) { + !(statement instanceof GrExpression)) { statement = statement.getLastChild(); } return statement != null; @@ -67,7 +77,7 @@ public abstract class GroovyCompletionUtil { 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(); @@ -75,15 +85,6 @@ public abstract class GroovyCompletionUtil { 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 * @@ -100,6 +101,7 @@ public abstract class GroovyCompletionUtil { return (previousLeaf == null || SEPARATORS.contains(previousLeaf.getNode().getElementType())); } + @Nullable public static PsiElement getLeafByOffset(int offset, PsiElement element) { if (offset < 0) { return null; @@ -131,40 +133,25 @@ public abstract class GroovyCompletionUtil { 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; } @@ -172,46 +159,54 @@ public abstract class GroovyCompletionUtil { 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; @@ -220,8 +215,75 @@ public abstract class GroovyCompletionUtil { 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() { + 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) { @@ -233,5 +295,7 @@ public abstract class GroovyCompletionUtil { return false; } - + public static LookupElement setTailTypeForConstructor(PsiClass clazz, LookupElement lookupElement) { + return LookupElementDecorator.withInsertHandler(lookupElement, ParenthesesInsertHandler.getInstance(hasConstructorParameters(clazz))); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java index 39b9b21e3f77..f1424fb74903 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java @@ -32,7 +32,6 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; 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; /** @@ -61,86 +60,97 @@ public class GrImportStatementImpl extends GroovyPsiElementImpl implements GrImp } 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; + } + + for (PsiMethod method : clazz.findMethodsByName(refName, false)) { + if (method.hasModifierProperty(PsiModifier.STATIC)) { + if (!processor.execute(method, 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; - } + + 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; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java index 19f5b023c1be..f92c116ed874 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java @@ -195,7 +195,14 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl implement } 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 diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java index e112eceff2dc..72157037ab82 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java @@ -19,9 +19,11 @@ import com.intellij.openapi.project.Project; 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; @@ -33,6 +35,7 @@ import java.beans.Introspector; 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() { } @@ -166,7 +169,7 @@ public class 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 { @@ -200,6 +203,7 @@ public class GroovyPropertyUtils { /** * Returns getter names in priority order + * * @param name property name * @return getter names */ @@ -208,11 +212,11 @@ public class GroovyPropertyUtils { } 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) { @@ -253,4 +257,65 @@ public class GroovyPropertyUtils { 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); + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java index b58675e1b321..abcdceb0ca72 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java @@ -110,7 +110,11 @@ public class FindUsagesTest extends LightGroovyTestCase { } public void testTypeAlias() throws Throwable { - doTestImpl("A.groovy", 1); + doTestImpl("A.groovy", 2); + } + + public void testMethodAlias() throws Throwable { + doTestImpl("A.groovy", 2); } public void testForInParameter() throws Throwable { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 7402d5dcbff0..55f7ceec3a42 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -497,7 +497,7 @@ setBar(2) """) def ref = findReference() def resolved = ref.resolve() - assertNull resolved + assertInstanceOf resolved, GrAccessorMethod } public void testPropertyInCallExpression() { @@ -545,4 +545,29 @@ print new X().@foo 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 +setFoo(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 +setFoo(2) +""") + def ref = findReference() + def resolved = ref.resolve() + assertInstanceOf resolved, GrMethod + } } \ No newline at end of file diff --git a/plugins/groovy/testdata/findUsages/methodAlias/A.groovy b/plugins/groovy/testdata/findUsages/methodAlias/A.groovy new file mode 100644 index 000000000000..4528895ef19c --- /dev/null +++ b/plugins/groovy/testdata/findUsages/methodAlias/A.groovy @@ -0,0 +1,3 @@ +import static java.lang.Math.min as alias + +print alias(1, 2) \ No newline at end of file From ed4c5d4278c6a0831c8baeecb0ccc0f2da56f537 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 10 Jun 2010 17:43:30 +0400 Subject: [PATCH 02/81] [Mercurial] Rollback of HgRemoveCheckinHandler changes. Correct fix: change for locally deleted files is provided by HgChangeProvider. --- plugins/hg4idea/hg4idea.iml | 1 - .../org/zmlx/hg4idea/HgVcsMessages.properties | 4 - plugins/hg4idea/src/META-INF/plugin.xml | 1 - .../zmlx/hg4idea/HgRemoveCheckinHandler.java | 130 ------------------ .../HgRemoveCheckinHandlerFactory.java | 38 ----- .../hg4idea/provider/HgChangeProvider.java | 12 +- .../provider/commit/HgCheckinEnvironment.java | 121 ++++++++-------- 7 files changed, 60 insertions(+), 247 deletions(-) delete mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandler.java delete mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandlerFactory.java diff --git a/plugins/hg4idea/hg4idea.iml b/plugins/hg4idea/hg4idea.iml index ccb452415959..b8677676d493 100644 --- a/plugins/hg4idea/hg4idea.iml +++ b/plugins/hg4idea/hg4idea.iml @@ -13,7 +13,6 @@ - diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index baa7501fcff7..7eed0e136d1a 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -62,11 +62,7 @@ hg4idea.add.progress=Adding files to Mercurial hg4idea.remove.single.title=Remove file from Mercurial hg4idea.remove.single.body=Do you want to remove the following file from Mercurial?\n{0}\n\nIf you say NO, you can still remove it later manually. -hg4idea.remove.commit.single.body=Do you want to remove the following file from Mercurial?\n{0}\n\nIf you say NO, the file will be excluded from the commit, but you can still remove it later manually. hg4idea.remove.multiple.title=Remove files from Mercurial -hg4idea.remove.commit.multiple.title=Select files to remove from Mercurial -hg4idea.remove.commit.multiple.description=The files you select will be scheduled on deletion from Mercurial and then committed.
Others won't be neither removed from the repository, nor committed. -hg4idea.remove.button.ok=Remove hg4idea.remove.progress=Removing files from the VCS... hg4idea.move.progress=Moving files in the VCS... diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 98ab049147e2..0406e1850618 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -27,7 +27,6 @@ - diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandler.java deleted file mode 100644 index ac0f6e8320eb..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandler.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.zmlx.hg4idea; - -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.TitlePanel; -import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.CommitExecutor; -import com.intellij.openapi.vcs.changes.ui.*; -import com.intellij.openapi.vcs.checkin.CheckinHandler; -import com.intellij.util.PairConsumer; -import com.intellij.util.ui.ConfirmationDialog; -import gnu.trove.THashSet; - -import javax.swing.*; -import javax.swing.tree.DefaultTreeModel; -import java.awt.*; -import java.util.*; -import java.util.List; - -/** - * HgRemoveCheckinHandler scans the changes which are ready for commit - * for files, which were deleted on the file system, but not from the VCS, - * and proposes a dialog to select files which are to be removed from the VCS. - */ -public class HgRemoveCheckinHandler extends CheckinHandler { - - private final CheckinProjectPanel myCheckinPanel; - private final Project myProject; - - public HgRemoveCheckinHandler(CheckinProjectPanel checkinPanel) { - myCheckinPanel = checkinPanel; - myProject = checkinPanel.getProject(); - } - - @Override - public ReturnResult beforeCheckin(CommitExecutor executor, final PairConsumer additionalDataConsumer) { - // find missing changes - final List missingChanges = new LinkedList(); - for (Change c : myCheckinPanel.getSelectedChanges()) { - if (c.getFileStatus() == FileStatus.DELETED_FROM_FS) { - missingChanges.add(c); - } - } - - if (missingChanges.isEmpty()) { - return ReturnResult.COMMIT; - } - - // show a simple confirmation for 1 missing change, or more complex dialog for 2 or more changes - final Collection changesToRemove = new THashSet(); - VcsShowConfirmationOption confirmation = ProjectLevelVcsManager.getInstance(myProject).getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, HgVcs.getInstance(myProject)); - if (missingChanges.size() == 1) { - if (ConfirmationDialog - .requestForConfirmation(confirmation, myProject, - HgVcsMessages.message("hg4idea.remove.commit.single.body", missingChanges.get(0).getBeforeRevision().getFile().getPresentableUrl()), - HgVcsMessages.message("hg4idea.remove.single.title"), Messages.getQuestionIcon())) { - changesToRemove.add(missingChanges.get(0)); - } - } else { - final SelectMissingChangesDialog dialog = new SelectMissingChangesDialog(myProject, missingChanges, confirmation); - dialog.show(); - if (dialog.isOK()) { - changesToRemove.addAll(dialog.getSelectedChanges()); - } else { - return ReturnResult.CANCEL; - } - } - - if (!changesToRemove.isEmpty()) { - removeChangesAndUpdateCommitted(changesToRemove, additionalDataConsumer); - } - return ReturnResult.COMMIT; - } - - private void removeChangesAndUpdateCommitted(final Collection changesToRemove, - final PairConsumer additionalDataConsumer) { - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - final List filepathsToRemove = new ArrayList(changesToRemove.size()); - for (Change c : changesToRemove) { - filepathsToRemove.add(c.getBeforeRevision().getFile()); - } - HgUtil.removeFilesFromVcs(myProject, filepathsToRemove); - additionalDataConsumer.consume(HgVcs.getInstance(myProject), changesToRemove); - } - }, HgVcsMessages.message("hg4idea.remove.progress"), true, myProject); - } - - private class SelectMissingChangesDialog extends AbstractSelectFilesDialog { - - public SelectMissingChangesDialog(final Project project, List originalFiles, VcsShowConfirmationOption confirmation) { - super(project, false, confirmation, null); - myFileList = new ChangesTreeList(project, originalFiles, true, true, null, null) { - protected DefaultTreeModel buildTreeModel(final List changes, ChangeNodeDecorator changeNodeDecorator) { - return new TreeModelBuilder(project, false).buildModel(changes, changeNodeDecorator); - } - - protected List getSelectedObjects(final ChangesBrowserNode node) { - return node.getAllChangesUnder(); - } - - protected Change getLeadSelectedObject(final ChangesBrowserNode node) { - final Object o = node.getUserObject(); - if (o instanceof Change) { - return (Change) o; - } - return null; - } - }; - myFileList.setChangesToDisplay(originalFiles); - myPanel.add(myFileList, BorderLayout.CENTER); - setOKButtonText(HgVcsMessages.message("hg4idea.remove.button.ok")); - setTitle(HgVcsMessages.message("hg4idea.remove.multiple.title")); - init(); - } - - public Collection getSelectedChanges() { - return myFileList.getIncludedChanges(); - } - - protected JComponent createTitlePane() { - return new TitlePanel(HgVcsMessages.message("hg4idea.remove.commit.multiple.title"), HgVcsMessages.message( - "hg4idea.remove.commit.multiple.description")); - } - - } - -} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandlerFactory.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandlerFactory.java deleted file mode 100644 index 78f0ec9e2e20..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRemoveCheckinHandlerFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.zmlx.hg4idea; - -import com.intellij.openapi.vcs.CheckinProjectPanel; -import com.intellij.openapi.vcs.checkin.CheckinHandler; -import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory; -import org.jetbrains.annotations.NotNull; - -/** - * HgRemoveCheckinHandlerFactory provides the {@link CheckinHandler} which scans - * the changes list for files, which were deleted on the file system, but not from - * the VCS. - * - * @author Kirill Likhodedov - */ -public class HgRemoveCheckinHandlerFactory extends CheckinHandlerFactory { - - @NotNull - @Override - public CheckinHandler createHandler(final CheckinProjectPanel checkinPanel) { - return new HgRemoveCheckinHandler(checkinPanel); - } - -} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index 8972250a2731..bd90fe3982c6 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -177,15 +177,9 @@ public class HgChangeProvider implements ChangeProvider { MISSING() { @Override void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - new HgContentRevision(project, beforeFile, parentRevision), - null, - FileStatus.DELETED_FROM_FS, - builder, - vcsKey - ); + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + builder.processLocallyDeletedFile(new LocallyDeletedChange(beforeFile.toFilePath())); } }, diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index 698868ba2cb7..f1e0c624394d 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -18,7 +18,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeList; @@ -34,20 +33,16 @@ import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgFile; import org.zmlx.hg4idea.HgRevisionNumber; import org.zmlx.hg4idea.HgVcsMessages; -import gnu.trove.THashSet; -import org.zmlx.hg4idea.*; - import org.zmlx.hg4idea.command.*; import java.util.*; -import java.util.List; public class HgCheckinEnvironment implements CheckinEnvironment { - private final Project myProject; + private final Project project; public HgCheckinEnvironment(Project project) { - this.myProject = project; + this.project = project; } public RefreshableOnComponent createAdditionalOptionsPanel(CheckinProjectPanel panel, @@ -69,36 +64,25 @@ public class HgCheckinEnvironment implements CheckinEnvironment { @SuppressWarnings({"ThrowableInstanceNeverThrown"}) public List commit(List changes, String preparedComment, @NotNull NullableFunction parametersHolder) { - final List exceptions = new LinkedList(); - final Collection removedChanges = (Collection) parametersHolder.fun(HgVcs.getInstance(myProject)); + List exceptions = new LinkedList(); + for (Map.Entry> entry : getFilesByRepository(changes).entrySet()) { - for (final Map.Entry> entry : groupChangesByRepository(changes).entrySet()) { - // separate commit for each repository - final VirtualFile repo = entry.getKey(); - final HgCommitCommand command = new HgCommitCommand(myProject, repo, preparedComment); - - // commit files, except those which were deleted from filesystem, but not from the VCS. - // HgRemoveCheckinHandler proposes to remove such files from the VCS before commit. - // If some of those weren't removed, it was done intentionally, so just silently ignore them. - final Set selectedFiles = new THashSet(); - for (Change c : entry.getValue()) { - if (c.getFileStatus() == FileStatus.DELETED_FROM_FS) { - if (removedChanges == null || !removedChanges.contains(c)) { // missing and not removed from vcs via the HgRemoveCheckinHandler - continue; - } - } - final FilePath filepath = (c.getAfterRevision() == null ? c.getBeforeRevision().getFile() : c.getAfterRevision().getFile()); - selectedFiles.add(new HgFile(repo, filepath)); - } + VirtualFile repo = entry.getKey(); + Set selectedFiles = entry.getValue(); + HgCommitCommand command = new HgCommitCommand(project, repo, preparedComment); + if (isMergeCommit(repo)) { //partial commits are not allowed during merges //verifyResult that all changed files in the repo are selected //If so, commit the entire repository //If not, abort - final Set changedFilesNotInCommit = getChangedFilesNotInCommit(repo, selectedFiles); - if (!changedFilesNotInCommit.isEmpty()) { + Set changedFilesNotInCommit = getChangedFilesNotInCommit(repo, selectedFiles); + boolean partial = !changedFilesNotInCommit.isEmpty(); + + + if (partial) { final StringBuilder filesNotIncludedString = new StringBuilder(); for (HgFile hgFile : changedFilesNotInCommit) { filesNotIncludedString.append("
  • "); @@ -109,17 +93,12 @@ public class HgCheckinEnvironment implements CheckinEnvironment { //abort return exceptions; } - // else : all was included, or it was OK to commit everything, - // so no need to set the files on the command, because then mercurial will complain - } - } - else { - if (selectedFiles.isEmpty()) { // nothing to commit. Aborting here, because otherwise 'hg commit' without specifying files will commit all files. - return exceptions; } + // else : all was included, or it was OK to commit everything, + // so no need to set the files on the command, because then mercurial will complain + } else { command.setFiles(selectedFiles); } - try { command.execute(); } catch (HgCommandException e) { @@ -132,13 +111,13 @@ public class HgCheckinEnvironment implements CheckinEnvironment { } private boolean isMergeCommit(VirtualFile repo) { - return new HgWorkingCopyRevisionsCommand(myProject).parents(repo).size() > 1; + return new HgWorkingCopyRevisionsCommand(project).parents(repo).size() > 1; } private Set getChangedFilesNotInCommit(VirtualFile repo, Set selectedFiles) { - List parents = new HgWorkingCopyRevisionsCommand(myProject).parents(repo); + List parents = new HgWorkingCopyRevisionsCommand(project).parents(repo); - HgStatusCommand statusCommand = new HgStatusCommand(myProject); + HgStatusCommand statusCommand = new HgStatusCommand(project); statusCommand.setBaseRevision(parents.get(0)); statusCommand.setIncludeUnknown(false); statusCommand.setIncludeIgnored(false); @@ -163,7 +142,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment { Runnable runnable = new Runnable() { public void run() { choice[0] = Messages.showOkCancelDialog( - myProject, + project, HgVcsMessages.message("hg4idea.commit.partial.merge.message", filesNotIncludedString), HgVcsMessages.message("hg4idea.commit.partial.merge.title"), null @@ -184,14 +163,21 @@ public class HgCheckinEnvironment implements CheckinEnvironment { } public List scheduleMissingFileForDeletion(List files) { - HgUtil.removeFilesFromVcs(myProject, files); + HgRemoveCommand command = new HgRemoveCommand(project); + for (FilePath filePath : files) { + VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, filePath); + if (vcsRoot == null) { + continue; + } + command.execute(new HgFile(vcsRoot, filePath)); + } return null; } public List scheduleUnversionedFilesForAddition(List files) { - HgAddCommand command = new HgAddCommand(myProject); + HgAddCommand command = new HgAddCommand(project); for (VirtualFile file : files) { - VirtualFile vcsRoot = VcsUtil.getVcsRootFor(myProject, file); + VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, file); if (vcsRoot == null) { continue; } @@ -204,32 +190,39 @@ public class HgCheckinEnvironment implements CheckinEnvironment { return false; } - /** - * Groups the changes by repository roots. - * @param changes the list of all changes. - * @return Changes grouped by repository roots. - */ - private Map> groupChangesByRepository(List changes) { - final Map> result = new HashMap>(); + private Map> getFilesByRepository(List changes) { + Map> result = new HashMap>(); for (Change change : changes) { - final ContentRevision afterRevision = change.getAfterRevision(); - final ContentRevision beforeRevision = change.getBeforeRevision(); - assert beforeRevision != null || afterRevision != null; // nothing-to-nothing change cannot happen. - final FilePath filePath = (afterRevision != null) ? afterRevision.getFile() : beforeRevision.getFile(); + ContentRevision afterRevision = change.getAfterRevision(); + ContentRevision beforeRevision = change.getBeforeRevision(); - final VirtualFile repo = VcsUtil.getVcsRootFor(myProject, filePath); - if (repo == null || filePath.isDirectory()) { - continue; + if (afterRevision != null) { + addFile(result, afterRevision.getFile()); } - - List repoChanges = result.get(repo); - if (repoChanges == null) { - repoChanges = new ArrayList(); - result.put(repo, repoChanges); + if (beforeRevision != null) { + addFile(result, beforeRevision.getFile()); } - repoChanges.add(change); } return result; } + private void addFile(Map> result, FilePath filePath) { + if (filePath == null) { + return; + } + + VirtualFile repo = VcsUtil.getVcsRootFor(project, filePath); + if (repo == null || filePath.isDirectory()) { + return; + } + + Set hgFiles = result.get(repo); + if (hgFiles == null) { + hgFiles = new HashSet(); + result.put(repo, hgFiles); + } + + hgFiles.add(new HgFile(repo, filePath)); + } + } From 1ec6e0154cbfa2b1534b0a13c756272f471e83e1 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 11 Jun 2010 13:50:34 +0400 Subject: [PATCH 03/81] [Mercurial] Fix: update the change list view immediately after change by tracking unsaved files. --- .../org/zmlx/hg4idea/command/HgChange.java | 4 ++ .../hg4idea/provider/HgChangeProvider.java | 52 +++++++++++++------ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChange.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChange.java index db30989082a0..e9c8af2c5145 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChange.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChange.java @@ -77,4 +77,8 @@ public final class HgChange { .toHashCode(); } + @Override + public String toString() { + return String.format("HgChange#%s %s => %s", status, beforeFile, afterFile); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index bd90fe3982c6..80d8cf53dd6b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -12,12 +12,10 @@ // limitations under the License. package org.zmlx.hg4idea.provider; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; @@ -30,8 +28,8 @@ import java.util.*; public class HgChangeProvider implements ChangeProvider { - private final Project project; - private final VcsKey vcsKey; + private final Project myProject; + private final VcsKey myVcsKey; private static final EnumMap PROCESSORS = new EnumMap(HgFileStatusEnum.class); @@ -48,8 +46,8 @@ public class HgChangeProvider implements ChangeProvider { } public HgChangeProvider(Project project, VcsKey vcsKey) { - this.project = project; - this.vcsKey = vcsKey; + this.myProject = project; + this.myVcsKey = vcsKey; } public void getChanges(VcsDirtyScope dirtyScope, ChangelistBuilder builder, @@ -61,6 +59,8 @@ public class HgChangeProvider implements ChangeProvider { for (FilePath filePath : dirtyScope.getDirtyFiles()) { process(builder, filePath, processedRoots); } + + processUnsavedChanges(builder, dirtyScope.getDirtyFilesNoExpand()); } public boolean isModifiedDocumentTrackingRequired() { @@ -72,18 +72,18 @@ public class HgChangeProvider implements ChangeProvider { private void process(ChangelistBuilder builder, FilePath filePath, Set processedRoots) { - VirtualFile repo = VcsUtil.getVcsRootFor(project, filePath); + VirtualFile repo = VcsUtil.getVcsRootFor(myProject, filePath); if (repo == null || processedRoots.contains(repo)) { return; } - Set hgChanges = new HgStatusCommand(project).execute(repo); + Set hgChanges = new HgStatusCommand(myProject).execute(repo); if (hgChanges == null || hgChanges.isEmpty()) { return; } sendChanges(builder, hgChanges, - new HgResolveCommand(project).list(repo), - new HgWorkingCopyRevisionsCommand(project).identify(repo), - new HgWorkingCopyRevisionsCommand(project).firstParent(repo) + new HgResolveCommand(myProject).list(repo), + new HgWorkingCopyRevisionsCommand(myProject).identify(repo), + new HgWorkingCopyRevisionsCommand(myProject).firstParent(repo) ); processedRoots.add(repo); } @@ -100,10 +100,10 @@ public class HgChangeProvider implements ChangeProvider { && resolveStatus.get(afterFile) == HgResolveStatusEnum.UNRESOLVED) { builder.processChange( new Change( - new HgContentRevision(project, beforeFile, parentRevision), + new HgContentRevision(myProject, beforeFile, parentRevision), HgCurrentContentRevision.create(afterFile, workingRevision), FileStatus.MERGED_WITH_CONFLICTS - ), vcsKey); + ), myVcsKey); continue; } @@ -115,7 +115,7 @@ public class HgChangeProvider implements ChangeProvider { HgChangeProcessor processor = PROCESSORS.get(status); if (processor != null) { - processor.process(project, vcsKey, builder, + processor.process(myProject, myVcsKey, builder, workingRevision, parentRevision, beforeFile, afterFile); } } @@ -134,6 +134,26 @@ public class HgChangeProvider implements ChangeProvider { return false; } + /** + * Finds modified but unsaved files in the given list of dirty files and notifies the builder about MODIFIED changes. + */ + public void processUnsavedChanges(ChangelistBuilder builder, Set dirtyFiles) { + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + for (FilePath filePath : dirtyFiles) { + final VirtualFile vf = filePath.getVirtualFile(); + if (vf != null && fileDocumentManager.isFileModifiedAndDocumentUnsaved(vf)) { + final VirtualFile root = vcsManager.getVcsRootFor(vf); + if (root != null) { + final HgRevisionNumber beforeRevisionNumber = new HgWorkingCopyRevisionsCommand(myProject).identify(root); + builder.processChange(new Change(new HgContentRevision(myProject, new HgFile(myProject, vf), beforeRevisionNumber), + CurrentContentRevision.create(filePath), FileStatus.MODIFIED), myVcsKey); + } + } + } + } + + private enum HgChangeProcessor { ADDED() { @Override From 4253f7b08c6e4a12b7b6c7123a9cf867a62aade0 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 11 Jun 2010 18:40:11 +0400 Subject: [PATCH 04/81] PersistentHM must be closed (fixes UpdateCacheTest). --- .../git4idea/history/GitUsersComponent.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/GitUsersComponent.java b/plugins/git4idea/src/git4idea/history/GitUsersComponent.java index 87c069db5ba3..0b94557e79de 100644 --- a/plugins/git4idea/src/git4idea/history/GitUsersComponent.java +++ b/plugins/git4idea/src/git4idea/history/GitUsersComponent.java @@ -65,6 +65,7 @@ public class GitUsersComponent implements ProjectComponent { private VcsListener myVcsListener; private final GitVcs myVcs; private final ProjectLevelVcsManager myManager; + private final File myFile; public GitUsersComponent(final ProjectLevelVcsManager manager) { myVcs = (GitVcs) manager.findVcsByName(GitVcs.getKey().getName()); @@ -74,14 +75,8 @@ public class GitUsersComponent implements ProjectComponent { final File vcsFile = new File(PathManager.getSystemPath(), "vcs"); File file = new File(vcsFile, "git_users"); file.mkdirs(); - file = new File(file, myVcs.getProject().getLocationHash()); + myFile = new File(file, myVcs.getProject().getLocationHash()); - try { - myState = new PersistentHashMap(file, new EnumeratorStringDescriptor(), createExternalizer()); - } - catch (IOException e) { - myState = null; - } myAccessMap = new HashMap>(); // every 10 seconds is ok to check @@ -157,12 +152,27 @@ public class GitUsersComponent implements ProjectComponent { } public void activate() { + try { + myState = new PersistentHashMap(myFile, new EnumeratorStringDescriptor(), createExternalizer()); + } + catch (IOException e) { + myState = null; + } + myIsActive = true; myManager.addVcsListener(myVcsListener); myControlledCycle.start(); } public void deactivate() { + if (myState != null) try { + myState.close(); + } + catch (IOException e) { + LOG.info(e); + } + myState = null; + synchronized (myLock) { myAccessMap.clear(); } From 5f94fd361b4fb15e14cf62f6899d33ebe3303eb9 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 11 Jun 2010 19:10:27 +0400 Subject: [PATCH 05/81] WI-2271 © symbol highlighted red in incomplete HTML 4.01 transitional and in HTML 5 documents --- .../resources/standardSchemas/html5/xhtml5.xsd | 17 +++++++++++++++++ .../javaee/InternalResourceProvider.java | 2 +- xml/impl/src/com/intellij/xml/util/XmlUtil.java | 8 +++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/xml/impl/resources/standardSchemas/html5/xhtml5.xsd b/xml/impl/resources/standardSchemas/html5/xhtml5.xsd index ae33bd7badb3..05f119bd295d 100644 --- a/xml/impl/resources/standardSchemas/html5/xhtml5.xsd +++ b/xml/impl/resources/standardSchemas/html5/xhtml5.xsd @@ -1,4 +1,21 @@ + + %HTMLlat1; + + + %HTMLsymbol; + + + %HTMLspecial; +]> + diff --git a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java index c52f535a49ad..37089231cd27 100644 --- a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java +++ b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java @@ -38,7 +38,7 @@ public class InternalResourceProvider implements StandardResourceProvider{ impl.addInternalResource("http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd","xhtml1-strict.xsd"); impl.addInternalResource("http://www.w3.org/TR/html4/strict.dtd","xhtml1-strict.dtd"); - impl.addInternalResource("http://www.w3.org/TR/html4/loose.dtd","xhtml1-transitional.dtd"); + impl.addInternalResource(XmlUtil.HTML4_LOOSE_URI,"xhtml1-transitional.dtd"); impl.addInternalResource("http://www.w3.org/TR/html4/frameset.dtd","xhtml1-frameset.dtd"); impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd","xhtml1-strict.dtd"); impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd","xhtml1-transitional.dtd"); diff --git a/xml/impl/src/com/intellij/xml/util/XmlUtil.java b/xml/impl/src/com/intellij/xml/util/XmlUtil.java index f1d1680fd4e6..503d5c09874d 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/XmlUtil.java @@ -148,6 +148,7 @@ public class XmlUtil { @NonNls public static final String TAG_DIR_NS_PREFIX = "urn:jsptagdir:"; @NonNls public static final String VALUE_ATTR_NAME = "value"; @NonNls public static final String ENUMERATION_TAG_NAME = "enumeration"; + public static final String HTML4_LOOSE_URI = "http://www.w3.org/TR/html4/loose.dtd"; private XmlUtil() { @@ -970,7 +971,12 @@ public class XmlUtil { String docType = doctype.getDtdUri(); if (docType == null && PsiTreeUtil.getParentOfType(doctype, XmlDocument.class) instanceof HtmlDocumentImpl) { - docType = HTML5_SCHEMA_LOCATION; + + final String publicId = doctype.getPublicId(); + if (publicId != null && publicId.indexOf("-//W3C//DTD HTML") != -1) { + return HTML4_LOOSE_URI; + } + if (publicId == null) docType = HTML5_SCHEMA_LOCATION; } return docType; } From b78c36e05afd01d5b9309ae284e75bf8383f5c99 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 11 Jun 2010 19:35:38 +0400 Subject: [PATCH 06/81] NPE --- .../src/com/intellij/openapi/ui/DialogWrapper.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index ec921fdc2814..bf1149306301 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -40,7 +40,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; -import javax.swing.border.LineBorder; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; @@ -427,7 +426,7 @@ public abstract class DialogWrapper { } setMargin(button); if (action.getValue(DEFAULT_ACTION) != null) { - if (!myPeer.isHeadless()) { + if (myPeer != null && !myPeer.isHeadless()) { getRootPane().setDefaultButton(button); } } @@ -1340,4 +1339,4 @@ public abstract class DialogWrapper { String getDoNotShowMessage(); } -} \ No newline at end of file +} From 213320384d480eafea2d892f94c19b5afd3d207a Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 11 Jun 2010 20:03:58 +0400 Subject: [PATCH 07/81] [rev by anna] correctly search for classes & subpackages in gnat/gradle non-classpath jars --- .../src/com/intellij/psi/NonClasspathClassFinder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java index ca17db61386f..4583c530df75 100644 --- a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java +++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java @@ -73,8 +73,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder { List result = new ArrayList(); for (final VirtualFile classRoot : classRoots) { if (scope.contains(classRoot)) { - final String pkgName = psiPackage.getName(); - final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot; + final String pkgName = psiPackage.getQualifiedName(); + final VirtualFile dir = classRoot.findFileByRelativePath(pkgName.replace('.', '/')); if (dir != null && dir.isDirectory()) { for (final VirtualFile file : dir.getChildren()) { if (!file.isDirectory()) { @@ -121,8 +121,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder { List result = new ArrayList(); for (final VirtualFile classRoot : classRoots) { if (scope.contains(classRoot)) { - final String pkgName = psiPackage.getName(); - final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot; + final String pkgName = psiPackage.getQualifiedName(); + final VirtualFile dir = classRoot.findFileByRelativePath(pkgName.replace('.', '/')); if (dir != null && dir.isDirectory()) { for (final VirtualFile file : dir.getChildren()) { if (file.isDirectory()) { From 8746b6515b868a44f4845ac93378795f008ee04a Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Fri, 11 Jun 2010 21:48:01 +0400 Subject: [PATCH 08/81] XML index, initialPatternCondition indexed, minor configuration fixes --- .../intellij/patterns/PsiJavaPatterns.java | 19 ++++++- .../intellij/patterns/PsiElementPattern.java | 18 +++--- .../com/intellij/util/PatternValuesIndex.java | 12 ++-- .../patterns/InitialPatternConditionPlus.java | 30 ++++++++++ .../intellij/patterns/StandardPatterns.java | 24 +++++++- .../plugins/intelliLang/Configuration.java | 23 ++++++-- .../PatternBasedInjectionHelper.java | 29 +++++++--- .../inject/xml/XmlLanguageInjector.java | 56 ++++++++++++++++--- .../xml-support/resources/xmlInjections.xml | 7 --- 9 files changed, 173 insertions(+), 45 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/patterns/InitialPatternConditionPlus.java diff --git a/java/openapi/src/com/intellij/patterns/PsiJavaPatterns.java b/java/openapi/src/com/intellij/patterns/PsiJavaPatterns.java index e4dad22a0195..05ca4cf80b70 100644 --- a/java/openapi/src/com/intellij/patterns/PsiJavaPatterns.java +++ b/java/openapi/src/com/intellij/patterns/PsiJavaPatterns.java @@ -18,8 +18,11 @@ package com.intellij.patterns; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.util.ProcessingContext; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; /** * @author peter @@ -55,10 +58,15 @@ public class PsiJavaPatterns extends StandardPatterns{ } public static PsiJavaElementPattern.Capture psiLiteral(final ElementPattern value) { - return new PsiJavaElementPattern.Capture(new InitialPatternCondition(PsiLiteral.class) { + return new PsiJavaElementPattern.Capture(new InitialPatternConditionPlus(PsiLiteral.class) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { return o instanceof PsiLiteral && (value == null || value.accepts(((PsiLiteral)o).getValue(), context)); } + + @Override + public List> getPatterns() { + return Collections.>singletonList(value); + } }); } @@ -78,11 +86,16 @@ public class PsiJavaPatterns extends StandardPatterns{ public static PsiJavaElementPattern.Capture literalExpression(final ElementPattern value) { - return new PsiJavaElementPattern.Capture(new InitialPatternCondition(PsiLiteralExpression.class) { + return new PsiJavaElementPattern.Capture(new InitialPatternConditionPlus(PsiLiteralExpression.class) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { return o instanceof PsiLiteralExpression && (value == null || value.accepts(((PsiLiteralExpression)o).getValue(), context)); } + + @Override + public List> getPatterns() { + return Collections.>singletonList(value); + } }); } diff --git a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java index de6be8172cea..6f4c943c1653 100644 --- a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java +++ b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java @@ -18,19 +18,21 @@ package com.intellij.patterns; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.vfs.VirtualFile; -import static com.intellij.patterns.PlatformPatterns.psiElement; -import static com.intellij.patterns.StandardPatterns.collection; -import static com.intellij.patterns.StandardPatterns.not; import com.intellij.psi.*; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.PairProcessor; import com.intellij.util.ProcessingContext; import com.intellij.util.ReflectionCache; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import static com.intellij.patterns.PlatformPatterns.psiElement; +import static com.intellij.patterns.StandardPatterns.collection; +import static com.intellij.patterns.StandardPatterns.not; + /** * @author peter */ @@ -206,11 +208,13 @@ public abstract class PsiElementPattern _withText(final ElementPattern pattern) { - return new PatternCondition("_withText") { - public boolean accepts(@NotNull final T t, final ProcessingContext context) { - return pattern.getCondition().accepts(t.getText(), context); + return new PatternConditionPlus("_withText", pattern) { + @Override + public boolean processValues(T t, + ProcessingContext context, + PairProcessor processor) { + return processor.process(t.getText(), context); } - }; } diff --git a/platform/lang-impl/src/com/intellij/util/PatternValuesIndex.java b/platform/lang-impl/src/com/intellij/util/PatternValuesIndex.java index b3758671f1ae..8a8f6dbc318f 100644 --- a/platform/lang-impl/src/com/intellij/util/PatternValuesIndex.java +++ b/platform/lang-impl/src/com/intellij/util/PatternValuesIndex.java @@ -15,10 +15,7 @@ */ package com.intellij.util; -import com.intellij.patterns.ElementPattern; -import com.intellij.patterns.PatternCondition; -import com.intellij.patterns.PatternConditionPlus; -import com.intellij.patterns.ValuePatternCondition; +import com.intellij.patterns.*; import gnu.trove.THashSet; import java.util.Collection; @@ -51,7 +48,12 @@ public class PatternValuesIndex { stack.add(next); while (!stack.isEmpty()) { final ElementPattern pattern = stack.removeFirst(); - for (PatternCondition condition : pattern.getCondition().getConditions()) { + final ElementPatternCondition patternCondition = pattern.getCondition(); + final InitialPatternCondition initialCondition = patternCondition.getInitialCondition(); + if (initialCondition instanceof InitialPatternConditionPlus) { + stack.addAll(((InitialPatternConditionPlus)initialCondition).getPatterns()); + } + for (PatternCondition condition : patternCondition.getConditions()) { if (condition instanceof PatternConditionPlus) { stack.add(((PatternConditionPlus)condition).getValuePattern()); } diff --git a/platform/platform-api/src/com/intellij/patterns/InitialPatternConditionPlus.java b/platform/platform-api/src/com/intellij/patterns/InitialPatternConditionPlus.java new file mode 100644 index 000000000000..f3697c02dcb4 --- /dev/null +++ b/platform/platform-api/src/com/intellij/patterns/InitialPatternConditionPlus.java @@ -0,0 +1,30 @@ +/* + * 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 com.intellij.patterns; + +import java.util.List; + +/** + * @author peter +*/ +public abstract class InitialPatternConditionPlus extends InitialPatternCondition { + + protected InitialPatternConditionPlus(final Class aAcceptedClass) { + super(aAcceptedClass); + } + + public abstract List> getPatterns(); +} diff --git a/platform/platform-api/src/com/intellij/patterns/StandardPatterns.java b/platform/platform-api/src/com/intellij/patterns/StandardPatterns.java index c06bdf05a2c2..c7bbe80d6800 100644 --- a/platform/platform-api/src/com/intellij/patterns/StandardPatterns.java +++ b/platform/platform-api/src/com/intellij/patterns/StandardPatterns.java @@ -22,6 +22,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + /** * @author peter */ @@ -83,7 +87,7 @@ public class StandardPatterns { } public static ElementPattern or(final ElementPattern... patterns) { - return new ObjectPattern.Capture(new InitialPatternCondition(Object.class) { + return new ObjectPattern.Capture(new InitialPatternConditionPlus(Object.class) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { for (final ElementPattern pattern : patterns) { if (pattern.getCondition().accepts(o, context)) return true; @@ -102,11 +106,15 @@ public class StandardPatterns { } } + @Override + public List> getPatterns() { + return Arrays.>asList(patterns); + } }); } public static ElementPattern and(final ElementPattern... patterns) { - return new ObjectPattern.Capture(new InitialPatternCondition(Object.class) { + return new ObjectPattern.Capture(new InitialPatternConditionPlus(Object.class) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { for (final ElementPattern pattern : patterns) { if (!pattern.getCondition().accepts(o, context)) return false; @@ -124,11 +132,16 @@ public class StandardPatterns { pattern.getCondition().append(builder, indent + " "); } } + + @Override + public List> getPatterns() { + return Arrays.>asList(patterns); + } }); } public static ObjectPattern.Capture not(final ElementPattern pattern) { - return new ObjectPattern.Capture(new InitialPatternCondition(Object.class) { + return new ObjectPattern.Capture(new InitialPatternConditionPlus(Object.class) { public boolean accepts(@Nullable final Object o, final ProcessingContext context) { return !pattern.getCondition().accepts(o, context); } @@ -137,6 +150,11 @@ public class StandardPatterns { pattern.getCondition().append(builder.append("not("), indent + " "); builder.append(")"); } + + @Override + public List> getPatterns() { + return Collections.>singletonList(pattern); + } }); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index ad764c365c70..ef099cf3fbf1 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -16,7 +16,9 @@ package org.intellij.plugins.intelliLang; import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.cl.PluginClassLoader; import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.undo.DocumentReference; @@ -199,14 +201,25 @@ public final class Configuration implements PersistentStateComponent, M } } } - final THashSet visitedUrls = new THashSet(); + final THashSet visited = new THashSet(); for (IdeaPluginDescriptor pluginDescriptor : PluginManager.getPlugins()) { + if (pluginDescriptor instanceof IdeaPluginDescriptorImpl && !((IdeaPluginDescriptorImpl)pluginDescriptor).isEnabled()) continue; final ClassLoader loader = pluginDescriptor.getPluginClassLoader(); - final URL url = loader != null ? loader.getResource("META-INF/languageInjections.xml") : null; - if (url == null) continue; - if (!visitedUrls.add(url.getFile())) continue; // for DEBUG mode + if (!visited.add(loader)) continue; + if (loader instanceof PluginClassLoader && ((PluginClassLoader)loader).getUrls().isEmpty()) continue; try { - cfgList.add(load(url.openStream())); + final Enumeration enumeration = loader.getResources("META-INF/languageInjections.xml"); + if (enumeration == null) continue; + while (enumeration.hasMoreElements()) { + URL url = enumeration.nextElement(); + if (!visited.add(url.getFile())) continue; // for DEBUG mode + try { + cfgList.add(load(url.openStream())); + } + catch (Exception e) { + LOG.warn(e); + } + } } catch (Exception e) { LOG.warn(e); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java index 2265c607efcb..1bd24d63f251 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java @@ -54,13 +54,9 @@ public class PatternBasedInjectionHelper { final String[] parts = text.split("[,|\\s]+"); boolean useMatches = false; for (String part : parts) { - if (!StringUtil.escapeToRegexp(part).equals(part)) { - try { - final URL url = new URL(part); - } - catch (MalformedURLException e) { - useMatches = true; - } + if (isRegexp(part)) { + useMatches = true; + break; } } if (useMatches) { @@ -83,6 +79,25 @@ public class PatternBasedInjectionHelper { return sb; } + public static boolean isRegexp(final String s) { + boolean hasReChars = false; + for (int i = 0, len = s.length(); i < len; i++) { + final char c = s.charAt(i); + if (c == ' ' || c == '_' || c == '-' || Character.isLetterOrDigit(c)) continue; + hasReChars = true; + break; + } + if (hasReChars) { + try { + new URL(s); + } + catch (MalformedURLException e) { + return true; + } + } + return false; + } + private Set getStaticMethods() { if (myStaticMethods == null) { myStaticMethods = getStaticMethods(mySupportId); diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java index c30bc7c79e95..26b40fadea22 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java @@ -20,6 +20,7 @@ import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.Trinity; @@ -37,6 +38,7 @@ import com.intellij.util.PairProcessor; import com.intellij.util.PatternValuesIndex; import gnu.trove.THashMap; import org.intellij.plugins.intelliLang.Configuration; +import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper; import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.intellij.plugins.intelliLang.inject.InjectorUtils; import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; @@ -46,6 +48,7 @@ import org.intellij.plugins.intelliLang.inject.config.InjectionPlace; import org.jetbrains.annotations.NotNull; import java.util.*; +import java.util.regex.Pattern; /** * This is the main part of the injection code. The component registers a language injector, the reference provider that @@ -60,7 +63,7 @@ public final class XmlLanguageInjector implements MultiHostInjector { private final Configuration myConfiguration; private final Project myProject; - private CachedValue> myXmlIndex; + private CachedValue>> myXmlIndex; public XmlLanguageInjector(Configuration configuration, Project project) { myConfiguration = configuration; @@ -73,9 +76,11 @@ public final class XmlLanguageInjector implements MultiHostInjector { } public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull PsiElement host) { + final XmlElement xmlElement = (XmlElement) host; + if (notInIndex(xmlElement)) return; final TreeSet ranges = new TreeSet(InjectorUtils.RANGE_COMPARATOR); - final PsiFile containingFile = host.getContainingFile(); - getInjectedLanguage(host, new PairProcessor>>() { + final PsiFile containingFile = xmlElement.getContainingFile(); + getInjectedLanguage(xmlElement, new PairProcessor>>() { public boolean process(final Language language, List> list) { for (Trinity trinity : list) { if (ranges.contains(trinity.third.shiftRight(trinity.first.getTextRange().getStartOffset()))) return true; @@ -92,7 +97,6 @@ public final class XmlLanguageInjector implements MultiHostInjector { }); } - void getInjectedLanguage(final PsiElement place, final PairProcessor>> processor) { if (place instanceof XmlTag) { final XmlTag xmlTag = (XmlTag)place; @@ -189,10 +193,35 @@ public final class XmlLanguageInjector implements MultiHostInjector { } } - private Collection getXmlAnnotatedElementsValue() { + // NOTE: local name of an xml entity or attribute value should match at least one string in the index + private boolean notInIndex(XmlElement xmlElement) { + final Pair> index = getXmlAnnotatedElementsValue(); + final XmlTag tag; + if (xmlElement instanceof XmlAttribute) { + final XmlAttribute attribute = (XmlAttribute)xmlElement; + if (areThereInjectionsWithText(attribute.getLocalName(), index)) return false; + if (areThereInjectionsWithText(attribute.getValue(), index)) return false; + //if (areThereInjectionsWithText(attribute.getNamespace(), index)) return false; + tag = attribute.getParent(); + } + else tag = (XmlTag)xmlElement; + if (areThereInjectionsWithText(tag.getLocalName(), index)) return false; + //if (areThereInjectionsWithText(tag.getNamespace(), index)) return false; + return true; + } + + + private static boolean areThereInjectionsWithText(final String text, Pair> index) { + if (text == null) return false; + if (index.second.contains(text)) return true; + if (index.first.matcher(text).matches()) return true; + return false; + } + + private Pair> getXmlAnnotatedElementsValue() { if (myXmlIndex == null) { - myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider>() { - public Result> compute() { + myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider>>() { + public Result>> compute() { final Map, BaseInjection> map = new THashMap, BaseInjection>(); for (BaseInjection injection : myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID)) { for (InjectionPlace place : injection.getInjectionPlaces()) { @@ -201,7 +230,8 @@ public final class XmlLanguageInjector implements MultiHostInjector { } } final Set stringSet = PatternValuesIndex.buildStringIndex(map.keySet()); - final Result> r = new Result>(stringSet, myConfiguration); + final Result>> r = new Result>>( + Pair.>create(buildPattern(stringSet), stringSet), myConfiguration); r.setLockValue(true); return r; } @@ -210,4 +240,14 @@ public final class XmlLanguageInjector implements MultiHostInjector { return myXmlIndex.getValue(); } + private static Pattern buildPattern(Set stringSet) { + final StringBuilder sb = new StringBuilder(); + for (String s : stringSet) { + if (!PatternBasedInjectionHelper.isRegexp(s)) continue; + if (sb.length() > 0) sb.append('|'); + sb.append("(?:").append(s).append(")"); + } + return Pattern.compile(sb.toString()); + } + } diff --git a/plugins/IntelliLang/xml-support/resources/xmlInjections.xml b/plugins/IntelliLang/xml-support/resources/xmlInjections.xml index ba2aa348db45..496709f21375 100644 --- a/plugins/IntelliLang/xml-support/resources/xmlInjections.xml +++ b/plugins/IntelliLang/xml-support/resources/xmlInjections.xml @@ -76,11 +76,4 @@ lower-case(@type)='text/css' - - Bare Tapestry EL in attribute value - ${ - } - - - From 5f4e6f80cc05d3114a14b0ddd812c0e70ad37868 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Fri, 11 Jun 2010 22:05:29 +0400 Subject: [PATCH 09/81] list iteration performance --- .../plugins/intelliLang/inject/config/BaseInjection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java index 8f3bfbe0f8ba..75a92ce3aef4 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java @@ -147,7 +147,8 @@ public class BaseInjection implements Injection, PersistentStateComponent Date: Fri, 11 Jun 2010 22:34:55 +0400 Subject: [PATCH 10/81] turn on default injection UI --- .../intelliLang/inject/AbstractLanguageInjectionSupport.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index 6f9d4b9b401a..a511b60a3cf7 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -19,7 +19,6 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; @@ -73,7 +72,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection } public AnAction[] createAddActions(final Project project, final Consumer consumer) { - if (!ApplicationManagerEx.getApplicationEx().isInternal()) return AnAction.EMPTY_ARRAY; return new AnAction[] { createDefaultAddAction(project, consumer, this) }; } @@ -85,7 +83,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection return new AnAction() { @Override public void actionPerformed(AnActionEvent e) { - if (!ApplicationManagerEx.getApplicationEx().isInternal()) return; final BaseInjection originalInjection = producer.create(); final BaseInjection newInjection = showDefaultInjectionUI(project, originalInjection.copy()); if (newInjection != null) { @@ -114,7 +111,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection @Nullable protected static BaseInjection showDefaultInjectionUI(Project project, BaseInjection injection) { - if (!ApplicationManagerEx.getApplicationEx().isInternal()) return null; final BaseInjectionPanel panel = new BaseInjectionPanel(injection, project); panel.reset(); final DialogBuilder builder = new DialogBuilder(project); From 5edd8327cb655b44139da32ee17a79519829668d Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 13 Jun 2010 16:46:38 +0400 Subject: [PATCH 11/81] IDEA-53924: Groovy, Find Usages: usages of class members imported via alias are not found --- .../AccessorReferencesSearcher.java | 14 +- .../GrAliasedImportedElementSearcher.java | 182 ++++++++++-------- .../lang/findUsages/FindUsagesTest.java | 10 + .../findUsages/aliasImportedProperty/A.groovy | 8 + .../A.groovy | 8 + 5 files changed, 136 insertions(+), 86 deletions(-) create mode 100644 plugins/groovy/testdata/findUsages/aliasImportedProperty/A.groovy create mode 100644 plugins/groovy/testdata/findUsages/getterWhenAliasedImportedProperty/A.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java index de1510920eaa..4c245a70493b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java @@ -18,6 +18,7 @@ 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.PsiSearchHelper; import com.intellij.psi.search.SearchScope; @@ -26,6 +27,7 @@ import com.intellij.psi.search.UsageSearchContext; 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; @@ -60,15 +62,13 @@ public class AccessorReferencesSearcher implements QueryExecutor() { + @Nullable + private static String getPropertyName(final PsiMethod method) { + return ApplicationManager.getApplication().runReadAction(new NullableComputable() { + @Nullable public String compute() { return GroovyPropertyUtils.getPropertyName(method); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java index fd94725717ce..d67bdbd5ff55 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java @@ -17,13 +17,16 @@ package org.jetbrains.plugins.groovy.findUsages; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.NullableComputable; import com.intellij.psi.*; -import com.intellij.psi.search.*; +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; @@ -32,28 +35,16 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; * @author Maxim.Medvedev */ public class GrAliasedImportedElementSearcher implements QueryExecutor { - private static final Key SEARCHING_FOR_IT = Key.create("SEARCHING_FOR_IT"); + private static final ThreadLocal I_WAS_HERE = new ThreadLocal(); public boolean execute(final ReferencesSearch.SearchParameters parameters, final Processor consumer) { final PsiElement elementToSearch = parameters.getElementToSearch(); if (!(elementToSearch instanceof PsiMember)) return true; - if (elementToSearch.getUserData(SEARCHING_FOR_IT) != null) return true; + if (I_WAS_HERE.get() != null) return true; + try { - elementToSearch.putUserData(SEARCHING_FOR_IT, Boolean.TRUE); - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - 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; - } - }; - final PsiSearchHelper helper = PsiManager.getInstance(elementToSearch.getProject()).getSearchHelper(); + I_WAS_HERE.set(Boolean.TRUE); + final TextOccurenceProcessor processor = new MyTextOccurenceProcessor(elementToSearch, consumer); final SearchScope groovySearchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { public SearchScope compute() { @@ -61,74 +52,107 @@ public class GrAliasedImportedElementSearcher implements QueryExecutor() { - public boolean process(PsiReference reference) { - final PsiElement element = reference.getElement(); - String alias = ApplicationManager.getApplication().runReadAction(new NullableComputable() { - public String compute() { - if (!(element.getParent() instanceof GrImportStatement)) return null; - final GrImportStatement importStatement = (GrImportStatement)element.getParent(); - if (!importStatement.isAliasedImport()) return null; - return importStatement.getImportedName(); - } - }); - if (alias == null) return true; + if (!ReferencesSearch.search(elementToSearch, groovySearchScope).forEach(new MyProcessor(null, processor))) return false; - final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiFile compute() { - return element.getContainingFile(); - } - }); - - return helper - .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, false); - } - })) return false; - - if (elementToSearch instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)elementToSearch)) { - final PsiField field = GroovyPropertyUtils.findFieldForAccessor((PsiMethod)elementToSearch, true); + if (elementToSearch instanceof PsiMethod && isAccessor(elementToSearch)) { + final PsiField field = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiField compute() { + return GroovyPropertyUtils.findFieldForAccessor((PsiMethod)elementToSearch, true); + } + }); if (field != null) { - try { - field.putUserData(SEARCHING_FOR_IT, Boolean.TRUE); - if (!ReferencesSearch.search(field, groovySearchScope).forEach(new Processor() { - public boolean process(PsiReference psiReference) { - final PsiElement element = psiReference.getElement(); - String alias = ApplicationManager.getApplication().runReadAction(new NullableComputable() { - public String compute() { - if (!(element.getParent() instanceof GrImportStatement)) return null; - final GrImportStatement importStatement = (GrImportStatement)element.getParent(); - if (!importStatement.isAliasedImport()) return null; - return importStatement.getImportedName(); - } - }); - if (alias == null) return true; - final String prefix = GroovyPropertyUtils.getAccessorPrefix((PsiMethod)elementToSearch); - if (prefix == null) return true; - - alias = prefix + alias; - final PsiFile containingFile = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiFile compute() { - return element.getContainingFile(); - } - }); - - return helper - .processElementsWithWord(processor, GlobalSearchScope.fileScope(containingFile), alias, UsageSearchContext.IN_CODE, - false); - } - })) { - return false; + final String prefix = ApplicationManager.getApplication().runReadAction(new Computable() { + public String compute() { + return GroovyPropertyUtils.getAccessorPrefix((PsiMethod)elementToSearch); } - } - finally { - field.putUserData(SEARCHING_FOR_IT, null); - } + }); + if (prefix == null) return true; + if (!ReferencesSearch.search(field, groovySearchScope).forEach(new MyProcessor(prefix, processor))) return false; } } return true; } finally { - elementToSearch.putUserData(SEARCHING_FOR_IT, null); + I_WAS_HERE.set(null); + } + + } + + private static Boolean isAccessor(final PsiElement elementToSearch) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + return GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)elementToSearch); + } + }); + } + + static class MyProcessor implements Processor { + 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() { + 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() { + 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 consumer; + + public MyTextOccurenceProcessor(PsiElement elementToSearch, Processor 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; } } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java index abcdceb0ca72..44c7dba2cf5f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java @@ -117,6 +117,16 @@ public class FindUsagesTest extends LightGroovyTestCase { 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); } diff --git a/plugins/groovy/testdata/findUsages/aliasImportedProperty/A.groovy b/plugins/groovy/testdata/findUsages/aliasImportedProperty/A.groovy new file mode 100644 index 000000000000..502c2b152431 --- /dev/null +++ b/plugins/groovy/testdata/findUsages/aliasImportedProperty/A.groovy @@ -0,0 +1,8 @@ +import static Abc.foo as bar + +print getBar() + +setBar 2 + +bar = 4; +bar++ \ No newline at end of file diff --git a/plugins/groovy/testdata/findUsages/getterWhenAliasedImportedProperty/A.groovy b/plugins/groovy/testdata/findUsages/getterWhenAliasedImportedProperty/A.groovy new file mode 100644 index 000000000000..9dc2d5bb5581 --- /dev/null +++ b/plugins/groovy/testdata/findUsages/getterWhenAliasedImportedProperty/A.groovy @@ -0,0 +1,8 @@ +import static Abc.foo as bar + +print getBar() + +setBar 2 + +bar = 4; +bar++ \ No newline at end of file From b8ad835a9392f1e954dce82d15da97e95ebb0509 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 13 Jun 2010 17:38:09 +0400 Subject: [PATCH 12/81] IDEA-55668: Rename field refactoring does not work --- .../refactoring/rename/RenameJavaVariableProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java index 4bc6ba351d5e..8a3d350c78fb 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.rename; +import com.intellij.lang.StdLanguages; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -133,7 +134,7 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor { } public void prepareRenaming(final PsiElement element, final String newName, final Map allRenames) { - if (element instanceof PsiField) { + if (element instanceof PsiField && StdLanguages.JAVA.equals(element.getLanguage())) { prepareFieldRenaming((PsiField)element, newName, allRenames); } } From 36ca1c7dc795bb9e4bb9e5b75a27db49de275d6c Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 13 Jun 2010 19:47:30 +0400 Subject: [PATCH 13/81] IDEA-54521: Groovy: Introduce Variable on an array expression puts array type at end --- .../api/statements/GrVariableDeclaration.java | 7 ++- .../psi/impl/GroovyPsiElementFactoryImpl.java | 9 +-- .../impl/statements/GrVariableBaseImpl.java | 62 +++++-------------- .../statements/GrVariableDeclarationImpl.java | 41 +++++++++++- .../GroovyIntroduceVariableBase.java | 30 +++------ .../IntroduceVariableTest.java | 20 ++++-- .../introduceVariable/charArray.test | 3 + 7 files changed, 89 insertions(+), 83 deletions(-) create mode 100644 plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrVariableDeclaration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrVariableDeclaration.java index 3e9edd3e0a19..bd4808a00f5d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrVariableDeclaration.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrVariableDeclaration.java @@ -4,12 +4,11 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; -import com.intellij.util.IncorrectOperationException; + /** * @author: Dmitry.Krasilschikov @@ -20,4 +19,6 @@ public interface GrVariableDeclaration extends GrStatement, GrMembersDeclaration GrTypeElement getTypeElementGroovy(); GrVariable[] getVariables(); + + void setType(@Nullable PsiType type); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 5605528578de..a8b2061ec49d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -59,7 +59,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrConstructorImpl; -import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.ArrayList; @@ -148,13 +147,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { text.append("def "); } else { - char c = typeText.charAt(idx); - if (!Character.isLetter(c) || Character.isLowerCase(c) && !GroovyNamesUtil.isKeyword(typeText)) { //primitive type - text.append("def "); - } - else { - text.append(typeText).append(" "); - } + text.append(typeText).append(" "); } } else { text.append("def "); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java index 8e81d5f7cb0a..fc36499e095b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java @@ -32,9 +32,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyIcons; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTupleDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -186,44 +184,8 @@ public abstract class GrVariableBaseImpl extends GroovyBa } public void setType(@Nullable PsiType type) { - final GrTypeElement typeElement = getTypeElementGroovy(); - if (type == null) { - if (typeElement == null) return; - final ASTNode typeElementNode = typeElement.getNode(); - final ASTNode parent = typeElementNode.getTreeParent(); - parent.addLeaf(GroovyTokenTypes.kDEF, GrModifier.DEF, typeElementNode); - parent.removeChild(typeElementNode); - } else { - type = TypesUtil.unboxPrimitiveTypeWrapper(type); - GrTypeElement newTypeElement; - try { - newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(type); - } - catch (IncorrectOperationException e) { - LOG.error(e); - return; - } - - final ASTNode newTypeElementNode = newTypeElement.getNode(); - if (typeElement == null) { - final PsiElement defKeyword = findChildByType(GroovyTokenTypes.kDEF); - if (defKeyword != null) { - final ASTNode defKeywordNode = defKeyword.getNode(); - assert defKeywordNode != null; - defKeywordNode.getTreeParent().removeChild(defKeywordNode); - } - final PsiElement nameID = getNameIdentifierGroovy(); - final ASTNode nameIdNode = nameID.getNode(); - assert nameIdNode != null; - nameIdNode.getTreeParent().addChild(newTypeElementNode); - } else { - final ASTNode typeElementNode = typeElement.getNode(); - final ASTNode parent = typeElementNode.getTreeParent(); - parent.replaceChild(typeElementNode, newTypeElementNode); - } - - PsiUtil.shortenReferences(newTypeElement); - } + final GrVariableDeclaration variableDeclaration = getDeclaration(); + if (variableDeclaration != null) variableDeclaration.setType(type); } @NotNull @@ -281,12 +243,8 @@ public abstract class GrVariableBaseImpl extends GroovyBa @Nullable public GrModifierList getModifierList() { - PsiElement parent = getParent(); - if (parent instanceof GrVariableDeclaration) { - return ((GrVariableDeclaration)parent).getModifierList(); - } else if (parent instanceof GrTupleDeclaration) { - return ((GrVariableDeclaration)parent.getParent()).getModifierList(); - } + final GrVariableDeclaration variableDeclaration = getDeclaration(); + if (variableDeclaration!=null) return variableDeclaration.getModifierList(); return null; } @@ -299,4 +257,16 @@ public abstract class GrVariableBaseImpl extends GroovyBa return getType(); } + + @Nullable + private GrVariableDeclaration getDeclaration() { + PsiElement parent = getParent(); + if (parent instanceof GrTupleDeclaration) { + parent = parent.getParent(); + } + if (parent instanceof GrVariableDeclaration) { + return (GrVariableDeclaration)parent; + } + return null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java index c3396f6fcec2..c0f5f8d8c4b5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java @@ -5,14 +5,19 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements; import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; import com.intellij.psi.ResolveState; import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -22,15 +27,17 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; /** * @author: Dmitry.Krasilschikov * @date: 27.03.2007 */ public class GrVariableDeclarationImpl extends GroovyPsiElementImpl implements GrVariableDeclaration { + private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl"); + public GrVariableDeclarationImpl(@NotNull ASTNode node) { super(node); } @@ -64,6 +71,38 @@ public class GrVariableDeclarationImpl extends GroovyPsiElementImpl implements G return findChildrenByClass(GrVariable.class); } + public void setType(@Nullable PsiType type) { + final GrTypeElement typeElement = getTypeElementGroovy(); + if (type == null) { + if (typeElement == null) return; + getModifierList().setModifierProperty(GrModifier.DEF, true); + typeElement.delete(); + return; + } + + type = TypesUtil.unboxPrimitiveTypeWrapper(type); + GrTypeElement newTypeElement; + try { + newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(type); + } + catch (IncorrectOperationException e) { + LOG.error(e); + return; + } + + if (typeElement == null) { + getModifierList().setModifierProperty(GrModifier.DEF, false); + final GrVariable[] variables = getVariables(); + if (variables.length == 0) return; + newTypeElement = (GrTypeElement)addBefore(newTypeElement, variables[0]); + } + else { + newTypeElement = (GrTypeElement)typeElement.replace(newTypeElement); + } + + PsiUtil.shortenReferences(newTypeElement); + } + @Nullable public GrTypeElement getTypeElementGroovy() { return findChildByClass(GrTypeElement.class); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java index 11bec12564b9..4b44eb03a117 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java @@ -283,7 +283,7 @@ public abstract class GroovyIntroduceVariableBase implements RefactoringActionHa }, REFACTORING_NAME, null); } - private void resolveLocalConflicts(PsiElement tempContainer, GrVariable varDef) { + private static void resolveLocalConflicts(PsiElement tempContainer, GrVariable varDef) { for (PsiElement child : tempContainer.getChildren()) { if (child instanceof GrReferenceExpression && !child.getText().contains(".")) { @@ -305,7 +305,8 @@ public abstract class GroovyIntroduceVariableBase implements RefactoringActionHa } } - private String getFieldName(PsiElement element) { + @Nullable + private static String getFieldName(PsiElement element) { if (element instanceof GrAccessorMethod) element = ((GrAccessorMethod) element).getProperty(); return element instanceof GrField ? ((GrField) element).getName() : null; } @@ -336,40 +337,26 @@ public abstract class GroovyIntroduceVariableBase implements RefactoringActionHa varDecl = (GrVariableDeclaration) block.addStatementBefore(varDecl, (GrStatement) anchorElement); } } else { - GrStatement tempStatement = anchorElement; // To replace branch body correctly - boolean inThenIfBranch = realContainer instanceof GrIfStatement && - anchorElement.equals(((GrIfStatement) realContainer).getThenBranch()); String refId = varDecl.getVariables()[0].getName(); GrBlockStatement newBody; - if (tempStatement.equals(selectedExpr)) { + if (anchorElement.equals(selectedExpr)) { newBody = factory.createBlockStatement(varDecl); } else { - replaceExpressionOccurrencesInStatement(tempStatement, selectedExpr, refId, replaceAllOccurrences); - newBody = factory.createBlockStatement(varDecl, tempStatement); + replaceExpressionOccurrencesInStatement(anchorElement, selectedExpr, refId, replaceAllOccurrences); + newBody = factory.createBlockStatement(varDecl, anchorElement); } varDecl = (GrVariableDeclaration) newBody.getBlock().getStatements()[0]; - GrCodeBlock tempBlock = newBody.getBlock(); - if (realContainer instanceof GrLoopStatement) { - tempBlock = ((GrBlockStatement) ((GrLoopStatement) realContainer).replaceBody(newBody)).getBlock(); - } else if (realContainer instanceof GrIfStatement) { - GrIfStatement ifStatement = ((GrIfStatement) realContainer); - if (inThenIfBranch) { - tempBlock = ((GrBlockStatement) ifStatement.replaceThenBranch(newBody)).getBlock(); - } else { - tempBlock = ((GrBlockStatement) ifStatement.replaceElseBranch(newBody)).getBlock(); - } - } - + GrCodeBlock tempBlock = ((GrBlockStatement) ((GrLoopStatement) realContainer).replaceBody(newBody)).getBlock(); refreshPositionMarker(tempBlock.getStatements()[tempBlock.getStatements().length - 1]); } return varDecl.getVariables()[0]; } - private void replaceExpressionOccurrencesInStatement(GrStatement stmt, GrExpression expr, String refText, boolean replaceAllOccurrences) + private static void replaceExpressionOccurrencesInStatement(GrStatement stmt, GrExpression expr, String refText, boolean replaceAllOccurrences) throws IncorrectOperationException { GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(stmt.getProject()); GrReferenceExpression refExpr = factory.createReferenceExpressionFromText(refText); @@ -392,6 +379,7 @@ public abstract class GroovyIntroduceVariableBase implements RefactoringActionHa /** * Replaces an expression occurrence by appropriate variable declaration */ + @Nullable private GrVariable replaceOnlyExpression(@NotNull GrExpression expr, GrExpression selectedExpr, @NotNull PsiElement context, diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java index 9f4c2c98f107..32f21961505f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.java @@ -71,11 +71,13 @@ public class IntroduceVariableTest extends LightCodeInsightFixtureTestCase { public void testDuplicatesInsideIf() throws Throwable { doTest(); } public void testFromGString() throws Throwable { doTest(); } + public void testCharArray() throws Exception {doTest(true);} + protected static final String ALL_MARKER = ""; protected boolean replaceAllOccurences = false; - private String processFile(String fileText) throws IncorrectOperationException, InvalidDataException, IOException { + private String processFile(String fileText, boolean explicitType) throws IncorrectOperationException, InvalidDataException, IOException { String result = ""; int startOffset = fileText.indexOf(TestUtils.BEGIN_MARKER); if (startOffset < 0) { @@ -106,7 +108,13 @@ public class IntroduceVariableTest extends LightCodeInsightFixtureTestCase { PsiElement[] occurences = GroovyRefactoringUtil.getExpressionOccurrences(GroovyRefactoringUtil.getUnparenthesizedExpr(selectedExpr), tempContainer); String varName = "preved"; - final PsiType varType = null; + final PsiType varType; + if (explicitType) { + varType = selectedExpr.getType(); + } + else { + varType = null; + } final GrVariableDeclaration varDecl = GroovyPsiElementFactory.getInstance(getProject()).createVariableDeclaration(new String[0], GroovyRefactoringUtil.getUnparenthesizedExpr(selectedExpr), varType, varName); @@ -121,9 +129,13 @@ public class IntroduceVariableTest extends LightCodeInsightFixtureTestCase { return result; } - public void doTest() throws Exception { + public void doTest(boolean explicitType) throws Exception { final List data = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); - assertEquals(data.get(1), processFile(data.get(0))); + assertEquals(data.get(1), processFile(data.get(0), explicitType)); + } + + public void doTest() throws Exception { + doTest(false); } protected static String removeAllMarker(String text) { diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test new file mode 100644 index 000000000000..0cd31e2f26ca --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test @@ -0,0 +1,3 @@ +"abc".toCharArray() +----- +char[] array = "abc".toCharArray() \ No newline at end of file From 5a63866f4b521e5889cf30a2bbdc82b3d51b72d9 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Sun, 13 Jun 2010 20:01:01 +0400 Subject: [PATCH 14/81] IDEA-55722 NPE throws if Show Implementations Action calls on virtual PSI element. --- .../codeInsight/hint/ImplementationViewComponent.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java index 0f1baeb1cdec..8d2503d63a00 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java @@ -128,7 +128,15 @@ public class ImplementationViewComponent extends JPanel { myEditor = factory.createEditor(doc, project); PsiFile psiFile = getContainingFile(myElements[myIndex]); - EditorHighlighter highlighter = HighlighterFactory.createHighlighter(project, psiFile.getVirtualFile()); + VirtualFile virtualFile = psiFile.getVirtualFile(); + EditorHighlighter highlighter; + if (virtualFile != null) + highlighter = HighlighterFactory.createHighlighter(project, virtualFile); + else { + String fileName = psiFile.getName(); // some artificial psi file, lets do best we can + highlighter = HighlighterFactory.createHighlighter(project, fileName); + } + ((EditorEx)myEditor).setHighlighter(highlighter); ((EditorEx)myEditor).setBackgroundColor(EditorFragmentComponent.getBackgroundColor(myEditor)); From 4c024ef9fdf4de477950e53dcecae86d5d805cc7 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 14 Jun 2010 16:48:59 +0400 Subject: [PATCH 15/81] mapping parameters to arguments in groovy calls. fix for closures --- .../statements/blocks/GrClosableBlock.java | 2 ++ .../impl/types/GrClosureSignatureUtil.java | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java index 7290c337b988..1a11d3775c5f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java @@ -28,6 +28,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterLi * @author ilyas */ public interface GrClosableBlock extends GrExpression, GrCodeBlock, GrParametersOwner { + GrClosableBlock[] EMPTY_ARRAY = new GrClosableBlock[0]; + String GROOVY_LANG_CLOSURE = "groovy.lang.Closure"; String OWNER_NAME = "owner"; String IT_PARAMETER_NAME = "it"; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index eb6147bad105..2f81bd1d5604 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -21,6 +21,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -204,19 +205,32 @@ public class GrClosureSignatureUtil { @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { + return mapParametersToArguments(signature, list, GrClosableBlock.EMPTY_ARRAY, manager, scope); + } - ArgInfo[] map = map(signature, list, manager, scope); + @Nullable + public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, + @NotNull GrArgumentList list, + @NotNull GrClosableBlock[] closureArguments, + PsiManager manager, + GlobalSearchScope scope) { + ArgInfo[] map = map(signature, list, closureArguments, manager, scope); if (map != null) return map; if (signature.isVarargs()) { - return new ApplicabilityMapperForVararg(manager, scope, list, signature).map(); + return new ApplicabilityMapperForVararg(manager, scope, list, closureArguments, signature).map(); } return null; } @Nullable - private static ArgInfo[] map(@NotNull GrClosureSignature signature, @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { - final GrExpression[] args = list.getExpressionArguments(); + private static ArgInfo[] map(@NotNull GrClosureSignature signature, + @NotNull GrArgumentList list, + GrClosableBlock[] closureArguments, + PsiManager manager, + GlobalSearchScope scope) { + final GrExpression[] args = ArrayUtil.mergeArrays(list.getExpressionArguments(), closureArguments, GrExpression.class); + final GrNamedArgument[] namedArgs = list.getNamedArguments(); boolean hasNamedArgs = namedArgs.length > 0; @@ -275,10 +289,14 @@ public class GrClosureSignatureUtil { private GrClosureParameter[] params; private PsiType vararg; - public ApplicabilityMapperForVararg(PsiManager manager, GlobalSearchScope scope, GrArgumentList list, GrClosureSignature signature) { + public ApplicabilityMapperForVararg(PsiManager manager, + GlobalSearchScope scope, + GrArgumentList list, + GrClosableBlock[] closureArguments, + GrClosureSignature signature) { this.manager = manager; this.scope = scope; - args = list.getExpressionArguments(); + args = ArrayUtil.mergeArrays(list.getExpressionArguments(), closureArguments, GrExpression.class); namedArgs = list.getNamedArguments(); params = signature.getParameters(); paramLength = params.length - 1; From d92f9c54a1a184b2ffc21cdabbfb4a6dca2e6dab Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 14 Jun 2010 16:58:30 +0400 Subject: [PATCH 16/81] IDEA-50932: Groovy: "Convert parameter to map entry" intention called for varargs parameter produces wrong code --- .../plugins/groovy/GroovyBundle.properties | 2 + .../ConvertParameterToMapEntryIntention.java | 134 ++++++++++-------- .../plugins/groovy/lang/lexer/TokenSets.java | 3 +- .../parsing/auxiliary/modifiers/Modifier.java | 2 +- .../auxiliary/modifiers/Modifiers.java | 4 +- .../members/ConstructorDefinition.java | 2 +- .../psi/impl/GroovyPsiElementFactoryImpl.java | 33 ++--- .../modifiers/GrModifierListImpl.java | 3 - .../arguments/GrArgumentListImpl.java | 17 +-- .../path/GrCallExpressionImpl.java | 3 +- .../params/GrParameterListImpl.java | 39 +++-- .../ParameterToMapEntryTest.java | 33 ++++- .../refactoring/inlineMethod/case1.test | 3 +- .../introduceVariable/charArray.test | 2 +- .../testdata/paramToMap/closure1/A.groovy | 2 +- .../testdata/paramToMap/closure1/A.test | 2 +- .../testdata/paramToMap/closureAtEnd/A.test | 2 +- .../testdata/paramToMap/formatter/A.test | 2 +- .../groovy/testdata/paramToMap/newMap/A.test | 2 +- .../testdata/paramToMap/param1/A.groovy | 4 +- .../groovy/testdata/paramToMap/param1/A.test | 2 +- .../testdata/paramToMap/secondClosure/A.test | 4 +- .../testdata/paramToMap/testError/A.test | 4 +- .../testdata/paramToMap/varArgs/A.groovy | 5 + .../groovy/testdata/paramToMap/varArgs/A.test | 5 + 25 files changed, 191 insertions(+), 123 deletions(-) create mode 100644 plugins/groovy/testdata/paramToMap/varArgs/A.groovy create mode 100644 plugins/groovy/testdata/paramToMap/varArgs/A.test diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index 9278c82be7a4..3e5f565cab0a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -201,6 +201,8 @@ strictfp.visibility.presentation=strictfp transient.visibility.presentation=transient # suppress inspection "UnusedProperty" volatile.visibility.presentation=volatile +# suppress inspection "UnusedProperty" +def.visibility.presentation=def diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java index a9ee6b700a15..cadbbb1da1f9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java @@ -22,10 +22,9 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; @@ -45,6 +44,7 @@ import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -53,15 +53,18 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; 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.GrCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyValidationUtil; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import static org.jetbrains.plugins.groovy.intentions.style.parameterToEntry.ConvertParameterToMapEntryIntention.FIRST_PARAMETER_KIND.*; @@ -139,7 +142,7 @@ public class ConvertParameterToMapEntryIntention extends Intention { else { //todo add statictics manager performRefactoring(element, owner, occurrences, true, - (new GroovyValidationUtil.ParameterNameSuggester("attrs", firstParam)).generateName(), false); + (new GroovyValidationUtil.ParameterNameSuggester("attrs", firstParam)).generateName(), true); } break; } @@ -170,14 +173,60 @@ public class ConvertParameterToMapEntryIntention extends Intention { final Runnable runnable = new Runnable() { public void run() { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); + final GrParameterList list = owner.getParameterList(); assert list != null; final int index = list.getParameterNumber(param); - final int newIndex = createNewFirstParam ? index : index - 1; if (!createNewFirstParam && index <= 0) { // bad undo return; } + //Remove old arguments from occurrences + //final List calls = getCallOccurrences(occurrences); + try { + for (PsiElement occurrence : occurrences) { + if (occurrence instanceof GrReferenceExpression && occurrence.getParent() instanceof GrCall) { + final GrReferenceExpression refExpr = (GrReferenceExpression)occurrence; + final GrClosureSignature signature = generateSignature(owner, refExpr); + if (signature == null) continue; + final GrCall call = (GrCall)refExpr.getParent(); + final GrArgumentList argumentList = call.getArgumentList(); + final GrClosableBlock[] closureArguments = + call instanceof GrCallExpression ? ((GrCallExpression)call).getClosureArguments() : GrClosableBlock.EMPTY_ARRAY; + + final GrClosureSignatureUtil.ArgInfo[] argInfos = + GrClosureSignatureUtil.mapParametersToArguments(signature, argumentList, closureArguments, occurrence.getManager(), owner.getResolveScope()); + if (argInfos == null) continue; + final GrClosureSignatureUtil.ArgInfo argInfo = argInfos[index]; + + final GrNamedArgument namedArg; + if (argInfo.isMultiArg) { + if (argInfo.args.size() == 0) continue; + String arg = "[" + StringUtil.join(ContainerUtil.map(argInfo.args, new Function() { + public String fun(PsiElement element) { + return element.getText(); + } + }), ", ") + "]"; + for (PsiElement psiElement : argInfo.args) { + psiElement.delete(); + } + namedArg = factory.createNamedArgument(paramName, factory.createExpressionFromText(arg)); + } + else { + if (argInfo.args.size() == 0) continue; + final PsiElement argument = argInfo.args.iterator().next(); + assert argument instanceof GrExpression; + namedArg = factory.createNamedArgument(paramName, (GrExpression)argument); + argument.delete(); + } + ((GrCall)refExpr.getParent()).addNamedArgument(namedArg); + } + } + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + //Replace of occurrences of old parameter in closure/method final Collection references = ReferencesSearch.search(param).findAll(); for (PsiReference ref : references) { @@ -202,35 +251,6 @@ public class ConvertParameterToMapEntryIntention extends Intention { //Eliminate obsolete parameter from parameter list param.delete(); - - - //Remove old arguments from occurrences - final List calls = getCallOccurrences(occurrences); - try { - for (final GrCall call : calls) { - GrExpression expr = call.removeArgument(newIndex); - if (expr != null) { - GrNamedArgument argument = factory.createNamedArgument(paramName, expr); - call.addNamedArgument(argument); - } - } - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - - //reformat code - PsiDocumentManager.getInstance(project).commitAllDocuments(); - try { - for (GrCall call : calls) { - reformatOwner(call.getArgumentList()); - } - reformatOwner(owner.getParameterList()); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - //owner.putUserData(hasFirstMapParameter, true); } }; @@ -242,20 +262,6 @@ public class ConvertParameterToMapEntryIntention extends Intention { } - private static List getCallOccurrences(final Collection occurrences) { - final List elementList = ContainerUtil.findAll(occurrences, new Condition() { - public boolean value(final PsiElement psiElement) { - return psiElement instanceof GrReferenceExpression && psiElement.getParent() instanceof GrCall; - } - }); - return ContainerUtil.map(elementList, new Function() { - public GrCall fun(final PsiElement psiElement) { - return ((GrCall)psiElement.getParent()); - } - }); - } - - @Nullable private static GrParameter getAppropriateParameter(final PsiElement element) { if (element instanceof GrParameter) { @@ -271,6 +277,18 @@ public class ConvertParameterToMapEntryIntention extends Intention { return null; } + @Nullable + private static GrClosureSignature generateSignature(GrParametersOwner owner, GrReferenceExpression refExpr) { + if (owner instanceof PsiMethod) { + final GroovyResolveResult resolveResult = refExpr.advancedResolve(); + final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); + return GrClosureSignatureUtil.createSignature((PsiMethod)owner, substitutor); + } + else if (owner instanceof GrClosableBlock) { + return GrClosureSignatureUtil.createSignature((GrClosableBlock)owner); + } + return null; + } /** * @param owner Method or closure @@ -388,18 +406,23 @@ public class ConvertParameterToMapEntryIntention extends Intention { private static class MyPsiElementPredicate implements PsiElementPredicate { public boolean satisfiedBy(final PsiElement element) { - GrParametersOwner owner = null; + GrParameter parameter = null; if (element instanceof GrParameter) { - owner = PsiTreeUtil.getParentOfType(element, GrParametersOwner.class); + parameter = (GrParameter)element; } else if (element instanceof GrReferenceExpression) { GrReferenceExpression expr = (GrReferenceExpression)element; if (expr.getQualifierExpression() != null) return false; final PsiElement resolved = expr.resolve(); - if (!(resolved instanceof GrParameter)) return false; - owner = PsiTreeUtil.getParentOfType(resolved, GrParametersOwner.class); + if (resolved instanceof GrParameter) { + parameter = (GrParameter)resolved; + } } - if (!(owner instanceof GrClosableBlock || owner instanceof GrMethodImpl)) return false; + if (parameter == null) return false; + if (parameter.isOptional()) return false; + + GrParametersOwner owner = PsiTreeUtil.getParentOfType(element, GrParametersOwner.class); + if (!(owner instanceof GrClosableBlock || owner instanceof GrMethod)) return false; return checkForMapParameters(owner); } } @@ -420,11 +443,6 @@ public class ConvertParameterToMapEntryIntention extends Intention { CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, null, project); } - private static void reformatOwner(PsiElement owner) throws IncorrectOperationException { - if (owner == null) return; - CodeStyleManager.getInstance(owner.getProject()).reformat(owner); - } - private static boolean reportConflicts(final MultiMap conflicts, final Project project) { if (conflicts.size() == 0) return true; ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java index 862fc65b25f3..93a97bb3302f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java @@ -118,7 +118,8 @@ public abstract class TokenSets implements GroovyTokenTypes { kSYNCHRONIZED, kSTRICTFP, kVOLATILE, - kSTRICTFP + kSTRICTFP, + kDEF ); public static TokenSet STRING_LITERALS = TokenSet.create( diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifier.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifier.java index a1a7c9739194..03942f8d3499 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifier.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifier.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers; import com.intellij.lang.PsiBuilder; -import com.intellij.psi.tree.IElementType; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; @@ -38,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; * | synchronized * | volatile * | srtictfp + * | def */ public class Modifier implements GroovyElementTypes { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java index 6a4d15fb6471..ae3de880f0d9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java @@ -38,7 +38,7 @@ public class Modifiers implements GroovyElementTypes { boolean endsWithNewLine; PsiBuilder.Marker modifiersMarker = builder.mark(); - if (!Annotation.parse(builder, parser) && !Modifier.parse(builder) && !ParserUtils.getToken(builder, kDEF)) { + if (!Annotation.parse(builder, parser) && !Modifier.parse(builder)) { modifiersMarker.done(MODIFIERS); return false; } @@ -49,7 +49,7 @@ public class Modifiers implements GroovyElementTypes { newLineMarker = builder.mark(); endsWithNewLine = ParserUtils.getToken(builder, mNLS); - if (!Annotation.parse(builder, parser) && !Modifier.parse(builder) && !ParserUtils.getToken(builder, kDEF)) break; + if (!Annotation.parse(builder, parser) && !Modifier.parse(builder)) break; } // Do not include last newline diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/ConstructorDefinition.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/ConstructorDefinition.java index 4b518768c64a..7326ad1d10ce 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/ConstructorDefinition.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/ConstructorDefinition.java @@ -88,7 +88,7 @@ public class ConstructorDefinition implements GroovyElementTypes { return false; } ParserUtils.getToken(builder, mNLS); - } while(Annotation.parse(builder, parser) || Modifier.parse(builder) || ParserUtils.getToken(builder, kDEF)); + } while(Annotation.parse(builder, parser) || Modifier.parse(builder)); modifiersMarker.done(MODIFIERS); return true; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index a8b2061ec49d..5e1a9da3c021 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.*; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -135,22 +136,16 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return (GrExpression) ((GroovyFileBase) file).getTopStatements()[0]; } - public GrVariableDeclaration createVariableDeclaration(String[] modifiers, GrExpression initializer, PsiType type, String... identifiers) { + public GrVariableDeclaration createVariableDeclaration(String[] modifiers, + GrExpression initializer, + PsiType type, + String... identifiers) { StringBuffer text = writeModifiers(modifiers); - + text.append("def "); if (type != null) { type = TypesUtil.unboxPrimitiveTypeWrapper(type); final String typeText = getTypeText(type); - int lastDot = typeText.lastIndexOf('.'); - int idx = 0 < lastDot && lastDot < typeText.length() - 1 ? lastDot + 1 : 0; - if (typeText.length() == 0) { - text.append("def "); - } - else { - text.append(typeText).append(" "); - } - } else { - text.append("def "); + text.append(typeText).append(" "); } for (int i = 0; i < identifiers.length; i++) { @@ -162,19 +157,25 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { if (initializer != null) { if (initializer instanceof GrApplicationStatement) { - expr = createMethodCallByAppCall(((GrApplicationStatement) initializer)); - } else { + expr = createMethodCallByAppCall(((GrApplicationStatement)initializer)); + } + else { expr = initializer; } text.append(" = ").append(expr.getText()); } PsiFile file = createGroovyFile(text.toString()); - GrTopStatement[] topStatements = ((GroovyFileBase) file).getTopStatements(); + GrTopStatement[] topStatements = ((GroovyFileBase)file).getTopStatements(); if (topStatements.length == 0 || !(topStatements[0] instanceof GrVariableDeclaration)) { throw new RuntimeException("Invalid arguments, text = " + text.toString()); } - return (GrVariableDeclaration) topStatements[0]; + + final GrVariableDeclaration declaration = (GrVariableDeclaration)topStatements[0]; + if (declaration.getTypeElementGroovy() != null) { + declaration.getModifierList().setModifierProperty(GrModifier.DEF, false); + } + return declaration; } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java index 4e5986dcf369..d8d3c690e5e9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java @@ -92,14 +92,11 @@ public class GrModifierListImpl extends GroovyBaseElementImpl modifiers = new ArrayList(); PsiElement[] modifiersKeywords = findChildrenByType(TokenSets.MODIFIERS, PsiElement.class); GrAnnotation[] modifiersAnnotations = findChildrenByClass(GrAnnotation.class); - PsiElement defKeyword = findChildByType(GroovyTokenTypes.kDEF); if (modifiersKeywords.length != 0) modifiers.addAll(Arrays.asList(modifiersKeywords)); if (modifiersAnnotations.length != 0) modifiers.addAll(Arrays.asList(modifiersAnnotations)); - if (defKeyword != null) modifiers.add(defKeyword); - return modifiers.toArray(new PsiElement[modifiers.size()]); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java index 1e38bfc5e137..81c3d8e8ae0c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java @@ -115,7 +115,6 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume public GrNamedArgument addNamedArgument(final GrNamedArgument namedArgument) { final GrNamedArgument[] namedArguments = getNamedArguments(); final GrExpression[] args = getExpressionArguments(); - final ASTNode newNode = namedArgument.getNode(); PsiElement anchor = null; final int namedCount = namedArguments.length; final int exprCount = args.length; @@ -133,24 +132,14 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume anchor = getRightParen(); } - if (anchor != null) { - final ASTNode astNode = anchor.getNode(); - getNode().addChild(newNode, astNode); - } - else { - getNode().addChild(newNode); - } - - if (namedCount + exprCount > 0) { - getNode().addLeaf(mCOMMA, ",", newNode); - } + addBefore(namedArgument, anchor); return namedArgument; } @Override public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { if (element instanceof GrNamedArgument || element instanceof GrExpression) { - if (anchor == null) anchor=getLastChild(); + if (anchor == null) anchor = getLastChild(); if (anchor == null) { return super.addBefore(element, anchor); } @@ -182,9 +171,9 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume else { astNode.addLeaf(mCOMMA, ",", result.getNode()); } + CodeStyleManager.getInstance(getManager().getProject()).reformat(this); } - CodeStyleManager.getInstance(getManager().getProject()).reformat(this); return result; } return super.addAfter(element, anchor); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrCallExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrCallExpressionImpl.java index ebdaf8d2e131..f4966c734073 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrCallExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrCallExpressionImpl.java @@ -79,8 +79,7 @@ public abstract class GrCallExpressionImpl extends GrExpressionImpl implements G if (list.getText().trim().length() == 0) { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(getProject()); final GrArgumentList newList = factory.createExpressionArgumentList(); - getNode().replaceChild(list.getNode(), newList.getNode()); - list = newList; + list = (GrArgumentList)list.replace(newList); } return list.addNamedArgument(namedArgument); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java index 40f1e1f805ce..265e72c8d89d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiParameter; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -64,29 +65,23 @@ public class GrParameterListImpl extends GroovyPsiElementImpl implements GrParam public void addParameterToEnd(GrParameter parameter) { GrParameter[] params = getParameters(); - final ASTNode astNode = getNode(); if (params.length == 0) { - astNode.addChild(parameter.getNode()); + add(parameter); } else { GrParameter last = params[params.length - 1]; - astNode.addChild(parameter.getNode(), last.getNode()); - astNode.addLeaf(mCOMMA, ",", last.getNode()); + addAfter(parameter, last); } } public void addParameterToHead(GrParameter parameter) { GrParameter[] params = getParameters(); - final ASTNode astNode = getNode(); - final ASTNode paramNode = parameter.getNode(); - assert paramNode != null; if (params.length == 0) { - astNode.addChild(paramNode); + add(parameter); } else { GrParameter first = params[0]; - astNode.addChild(paramNode, first.getNode()); - astNode.addLeaf(mCOMMA, ",", first.getNode()); + addBefore(parameter, first); } } @@ -116,8 +111,32 @@ public class GrParameterListImpl extends GroovyPsiElementImpl implements GrParam else { astNode.addLeaf(mCOMMA, ",", element.getNextSibling().getNode()); } + CodeStyleManager.getInstance(getManager().getProject()).reformat(this); } return element; } + + @Override + public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + GrParameter[] params = getParameters(); + + if (params.length == 0) { + add(element); + } + else { + element = super.addBefore(element, anchor); + final ASTNode astNode = getNode(); + if (anchor != null) { + astNode.addLeaf(mCOMMA, ",", anchor.getNode()); + } + else { + astNode.addLeaf(mCOMMA, ",", element.getNode()); + } + CodeStyleManager.getInstance(getManager().getProject()).reformat(this); + } + + return element; + } + } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ParameterToMapEntryTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ParameterToMapEntryTest.java index 3838072f1023..f8692a9da4c8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ParameterToMapEntryTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ParameterToMapEntryTest.java @@ -1,10 +1,20 @@ package org.jetbrains.plugins.groovy.intentions.style.parameterToEntry; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; import org.jetbrains.plugins.groovy.lang.formatter.GroovyFormatterTestCase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; @@ -22,6 +32,23 @@ public class ParameterToMapEntryTest extends GroovyFormatterTestCase { return TestUtils.getTestDataPath() + "paramToMap/" + getTestName(true) + "/"; } + public static final DefaultLightProjectDescriptor GROOVY_17_PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() { + @Override + public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { + final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel(); + final VirtualFile groovyJar = + JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_7LibraryName()+"!/"); + modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES); + modifiableModel.commit(); + } + }; + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return GROOVY_17_PROJECT_DESCRIPTOR; + } + /* @Override protected CodeStyleSettings getCurrentCodeStyleSettings() { @@ -57,6 +84,10 @@ public class ParameterToMapEntryTest extends GroovyFormatterTestCase { doTestImpl("A.groovy"); } + public void testVarArgs() throws Throwable { + doTestImpl("A.groovy"); + } + private void doTestImpl(String filePath) throws Throwable { myFixture.configureByFile(filePath); int offset = myFixture.getEditor().getCaretModel().getOffset(); @@ -79,7 +110,7 @@ public class ParameterToMapEntryTest extends GroovyFormatterTestCase { final String result = file.getText(); //System.out.println(result); String expected = getExpectedResult(filePath); - Assert.assertEquals(result, expected); + Assert.assertEquals(expected, result); } private String getExpectedResult(final String filePath) { diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineMethod/case1.test b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/case1.test index 9ccdc58c34f3..e7b713c34659 100644 --- a/plugins/groovy/testdata/groovy/refactoring/inlineMethod/case1.test +++ b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/case1.test @@ -18,7 +18,8 @@ int fact(int n) { def foo(int i) { switch (i) { - case 42: int result + case 42: + int result if (5 > 0) result = 5 * fact(5 - 1); else result = 1 return result diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test index 0cd31e2f26ca..04861f676d47 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test @@ -1,3 +1,3 @@ "abc".toCharArray() ----- -char[] array = "abc".toCharArray() \ No newline at end of file +char[] preved = "abc".toCharArray() \ No newline at end of file diff --git a/plugins/groovy/testdata/paramToMap/closure1/A.groovy b/plugins/groovy/testdata/paramToMap/closure1/A.groovy index f2fc3c16a1a1..50b0f827798c 100644 --- a/plugins/groovy/testdata/paramToMap/closure1/A.groovy +++ b/plugins/groovy/testdata/paramToMap/closure1/A.groovy @@ -1,4 +1,4 @@ -def foo = { params, iii, jjj -> +def foo = {Map params, iii, jjj -> println iii } diff --git a/plugins/groovy/testdata/paramToMap/closure1/A.test b/plugins/groovy/testdata/paramToMap/closure1/A.test index 404d298e0637..de99aa1b077e 100644 --- a/plugins/groovy/testdata/paramToMap/closure1/A.test +++ b/plugins/groovy/testdata/paramToMap/closure1/A.test @@ -1,4 +1,4 @@ -def foo = { params, jjj -> +def foo = {Map params, jjj -> println params.iii } diff --git a/plugins/groovy/testdata/paramToMap/closureAtEnd/A.test b/plugins/groovy/testdata/paramToMap/closureAtEnd/A.test index 32a5372e9337..e000ffc6e5c4 100644 --- a/plugins/groovy/testdata/paramToMap/closureAtEnd/A.test +++ b/plugins/groovy/testdata/paramToMap/closureAtEnd/A.test @@ -1,4 +1,4 @@ -def test = {attrs, x -> +def test = {Map attrs, x -> attrs.cl.call() } diff --git a/plugins/groovy/testdata/paramToMap/formatter/A.test b/plugins/groovy/testdata/paramToMap/formatter/A.test index ea43b6a7d598..9e8fc2f9b2ab 100644 --- a/plugins/groovy/testdata/paramToMap/formatter/A.test +++ b/plugins/groovy/testdata/paramToMap/formatter/A.test @@ -1,4 +1,4 @@ -def foo(attrs, int aaa, String sss) { +def foo(Map attrs, int aaa, String sss) { println(aaa + attrs.bbb + sss) } diff --git a/plugins/groovy/testdata/paramToMap/newMap/A.test b/plugins/groovy/testdata/paramToMap/newMap/A.test index 82160511d388..96fa6395cee0 100644 --- a/plugins/groovy/testdata/paramToMap/newMap/A.test +++ b/plugins/groovy/testdata/paramToMap/newMap/A.test @@ -1,4 +1,4 @@ -def foo = {attrs, a -> +def foo = {Map attrs, a -> a + attrs.b } diff --git a/plugins/groovy/testdata/paramToMap/param1/A.groovy b/plugins/groovy/testdata/paramToMap/param1/A.groovy index ed6a87a0026f..1015cca501b9 100644 --- a/plugins/groovy/testdata/paramToMap/param1/A.groovy +++ b/plugins/groovy/testdata/paramToMap/param1/A.groovy @@ -1,6 +1,6 @@ -def foo(params, iii, jjj) { +def foo(Map params, iii, jjj) { println iii } -foo(a:1, "abc", "def") \ No newline at end of file +foo(a: 1, "abc", "def") \ No newline at end of file diff --git a/plugins/groovy/testdata/paramToMap/param1/A.test b/plugins/groovy/testdata/paramToMap/param1/A.test index 99f2bbf47871..df58c4e4bc88 100644 --- a/plugins/groovy/testdata/paramToMap/param1/A.test +++ b/plugins/groovy/testdata/paramToMap/param1/A.test @@ -1,4 +1,4 @@ -def foo(params, jjj) { +def foo(Map params, jjj) { println params.iii } diff --git a/plugins/groovy/testdata/paramToMap/secondClosure/A.test b/plugins/groovy/testdata/paramToMap/secondClosure/A.test index 23f8e1963451..8d7c37ab7949 100644 --- a/plugins/groovy/testdata/paramToMap/secondClosure/A.test +++ b/plugins/groovy/testdata/paramToMap/secondClosure/A.test @@ -1,6 +1,6 @@ -def foo = {attrs, cl1 -> +def foo = {Map attrs, cl1 -> cl1.call() attrs.cl2.call() } -foo(cl2: {y -> y}){x->x} \ No newline at end of file +foo(cl2: {y -> y}) {x->x} \ No newline at end of file diff --git a/plugins/groovy/testdata/paramToMap/testError/A.test b/plugins/groovy/testdata/paramToMap/testError/A.test index edcce06368da..707be9e58180 100644 --- a/plugins/groovy/testdata/paramToMap/testError/A.test +++ b/plugins/groovy/testdata/paramToMap/testError/A.test @@ -1,9 +1,9 @@ -def foo(attrs, aaa, b) { +def foo(Map attrs, aaa, b) { println(attrs.ccc) } foo(1, 2, ccc: 3) -foo(2, 4) +foo(2,4) foo(0) \ No newline at end of file diff --git a/plugins/groovy/testdata/paramToMap/varArgs/A.groovy b/plugins/groovy/testdata/paramToMap/varArgs/A.groovy new file mode 100644 index 000000000000..7ad90a924d9f --- /dev/null +++ b/plugins/groovy/testdata/paramToMap/varArgs/A.groovy @@ -0,0 +1,5 @@ +def foo(String s, int x = 5, String... vars) { + print s + x + vars; +} + +foo("a", "b", "c") \ No newline at end of file diff --git a/plugins/groovy/testdata/paramToMap/varArgs/A.test b/plugins/groovy/testdata/paramToMap/varArgs/A.test new file mode 100644 index 000000000000..234d37da9f8b --- /dev/null +++ b/plugins/groovy/testdata/paramToMap/varArgs/A.test @@ -0,0 +1,5 @@ +def foo(Map attrs, String s, int x = 5) { + print s + x + attrs.vars; +} + +foo("a", vars: ["b", "c"]) \ No newline at end of file From 69a7ff9fb33a06cc96d02752dc564f45ebe01f75 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 14 Jun 2010 17:26:30 +0400 Subject: [PATCH 17/81] IDEA-55607: Failed to move static field to another class --- .../groovy/lang/psi/impl/statements/GrFieldImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java index 6272020c9293..433319e032c4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java @@ -48,7 +48,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import javax.swing.*; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * User: Dmitry.Krasilschikov @@ -121,7 +124,6 @@ public class GrFieldImpl extends GrVariableBaseImpl implements GrFi return ((GroovyFileBase)file).getScriptClass(); } - assert false; return null; } From 9fd71742f575b4fce3b2aea83e557e1d316ebb23 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 14 Jun 2010 18:43:13 +0400 Subject: [PATCH 18/81] IDEA-54597: bug on renaming fields --- .../rename/RenameGroovyPropertyProcessor.java | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGroovyPropertyProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGroovyPropertyProcessor.java index 771b16e6195a..d1ac11d79540 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGroovyPropertyProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGroovyPropertyProcessor.java @@ -19,12 +19,14 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; 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.PsiReference; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.rename.RenameJavaVariableProcessor; @@ -32,12 +34,18 @@ import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +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.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; /** @@ -83,27 +91,32 @@ public class RenameGroovyPropertyProcessor extends RenameJavaVariableProcessor { final PsiElement element = usage.getElement(); if (element == null) { continue; - } else { - PsiReference ref = element.getReference(); - if (ref != null) { - PsiElement resolved = ref.resolve(); - if (resolved instanceof GrAccessorMethod) { - GrAccessorMethod method = (GrAccessorMethod)resolved; - if (method == getter) { + } - ref.handleElementRename(newGetterName); - } else { - if (method == setter) { - ref.handleElementRename(newSetterName); - } - else { - ref.handleElementRename(newName); - } - } - } else { + PsiReference ref = element.getReference(); + if (ref == null) continue; + + PsiElement resolved = ref.resolve(); + if (resolved instanceof GrAccessorMethod) { + GrAccessorMethod method = (GrAccessorMethod)resolved; + if (method == getter) { + + ref.handleElementRename(newGetterName); + } + else { + if (method == setter) { + ref.handleElementRename(newSetterName); + } + else { ref.handleElementRename(newName); } - + } + } + else { + final PsiElement renamed = ref.handleElementRename(newName); + final PsiElement newly_resolved = ref.resolve(); + if (!field.getManager().areElementsEquivalent(newly_resolved, field)) { + qualify(field, renamed, newName); } } } @@ -112,6 +125,35 @@ public class RenameGroovyPropertyProcessor extends RenameJavaVariableProcessor { listener.elementRenamed(field); } + private static void qualify(GrField field, PsiElement renamed, String name) { + if (!(renamed instanceof GrReferenceExpression)) return; + + final PsiClass clazz = field.getContainingClass(); + if (clazz == null) return; + + final GrReferenceExpression refExpr = (GrReferenceExpression)renamed; + final PsiElement replaced; + if (field.hasModifierProperty(GrModifier.STATIC)) { + final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(field.getProject()) + .createReferenceExpressionFromText(clazz.getQualifiedName() + "." + name); + replaced = refExpr.replace(newRefExpr); + } + else { + final PsiClass containingClass = PsiTreeUtil.getParentOfType(renamed, PsiClass.class); + if (field.getManager().areElementsEquivalent(containingClass, clazz)) { + final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(field.getProject()) + .createReferenceExpressionFromText("this." + name); + replaced = refExpr.replace(newRefExpr); + } + else { + final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(field.getProject()) + .createReferenceExpressionFromText(clazz.getQualifiedName() + ".this." + name); + replaced = refExpr.replace(newRefExpr); + } + } + PsiUtil.shortenReferences((GroovyPsiElement)replaced); + } + @Override public boolean canProcessElement(final PsiElement element) { return element instanceof GrField && ((GrField)element).isProperty(); @@ -141,5 +183,14 @@ public class RenameGroovyPropertyProcessor extends RenameJavaVariableProcessor { return Messages.showYesNoDialog(project, text, RefactoringBundle.message("rename.title"), Messages.getQuestionIcon()) == 0; } + @Override + public void findCollisions(PsiElement element, + String newName, + Map allRenames, + List result) { + super + .findCollisions(element, newName, allRenames, result); //To change body of overridden methods use File | Settings | File Templates. + } + } From e8a86897b6440c15537d7c23a003f6fcf70921c4 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 15 Jun 2010 00:57:10 +0400 Subject: [PATCH 19/81] VCS: background task queue test (singleton executor, where execution is wrapped into backgroundable task). tests it's singleton --- .../openapi/progress/BackgroundTaskQueue.java | 39 ++++++++---- .../intellij/testFramework/UnitTestMode.java | 62 +++++++++++++++++++ .../src/componentSets/Platform.xml | 4 ++ 3 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java diff --git a/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 611e93cf740b..11a821e962e4 100644 --- a/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -16,9 +16,11 @@ package com.intellij.openapi.progress; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; +import com.intellij.testFramework.UnitTestMode; import org.jetbrains.annotations.NotNull; import java.util.LinkedList; @@ -74,7 +76,7 @@ public class BackgroundTaskQueue { } public void run(Task.Backgroundable task) { - if (ApplicationManager.getApplication().isUnitTestMode()) { + if (UnitTestMode.getInstance(myProject).isInUnitTestMode(BackgroundTaskQueue.class.getName())) { task.run(new EmptyProgressIndicator()); task.onSuccess(); } @@ -88,19 +90,32 @@ public class BackgroundTaskQueue { myQueue.offer(task); myHasActiveTask = true; } - if (!hadActiveTask) { - if (ApplicationManager.getApplication().isDispatchThread()) { - ProgressManager.getInstance().run(myRunnerTask); + if (! hadActiveTask) { + runRunner(); + } + } + } + + private void runRunner() { + final Application application = ApplicationManager.getApplication(); + if (application.isUnitTestMode()) { + application.executeOnPooledThread(new Runnable() { + public void run() { + myRunnerTask.run(new EmptyProgressIndicator()); } - else { - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - if (myProject == null || !myProject.isDisposed()) { - ProgressManager.getInstance().run(myRunnerTask); - } + }); + } else { + if (application.isDispatchThread()) { + ProgressManager.getInstance().run(myRunnerTask); + } + else { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + if (myProject == null || !myProject.isDisposed()) { + ProgressManager.getInstance().run(myRunnerTask); } - }); - } + } + }); } } } diff --git a/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java b/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java new file mode 100644 index 000000000000..01160687b1fa --- /dev/null +++ b/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java @@ -0,0 +1,62 @@ +/* + * 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 com.intellij.testFramework; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Set; + +public class UnitTestMode implements ProjectComponent { + private final Set myNotInUnitTestMode; + + public UnitTestMode() { + myNotInUnitTestMode = new HashSet(); + } + + public static UnitTestMode getInstance(final Project project) { + return project.getComponent(UnitTestMode.class); + } + + public void register(final Object obj) { + myNotInUnitTestMode.add(obj); + } + + public boolean isInUnitTestMode(final Object key) { + if (myNotInUnitTestMode.contains(key)) return false; + return ApplicationManager.getApplication().isUnitTestMode(); + } + + public void projectClosed() { + } + + public void projectOpened() { + } + + @NotNull + public String getComponentName() { + return getClass().getName(); + } + + public void initComponent() { + } + + public void disposeComponent() { + } +} diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml index a137d898aaf0..95d147f7c49b 100644 --- a/platform/platform-resources/src/componentSets/Platform.xml +++ b/platform/platform-resources/src/componentSets/Platform.xml @@ -166,5 +166,9 @@ + + com.intellij.testFramework.UnitTestMode + + From c6eeaa8a6d127b06fbb565ed5b81614806e2642b Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 10 Jun 2010 11:37:31 +0400 Subject: [PATCH 20/81] jdk 1.6. build script --- build/scripts/utils.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index f05aeb16070e..58628589ac90 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -65,7 +65,7 @@ binding.setVariable("guessHome", { }) binding.setVariable("loadProject", { - requireProperty("jdk", requireProperty("jdk15.home", guessJdk())) + requireProperty("jdk", requireProperty("jdk16.home", guessJdk())) new IdeaProjectLoader().loadFromPath(project, "${home}") binding.ant.patternset(id: "idea.compiler.resources") { From 4cf2a14cebdd09d037a16d621445a70d4b8067aa Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 16:57:25 +0100 Subject: [PATCH 21/81] merged usage search initial --- .../findUsages/JavaFindUsagesHandler.java | 33 ++- .../psi/impl/search/MethodUsagesSearcher.java | 161 +++++++------- .../intellij/psi/search/PsiSearchHelper.java | 2 + .../intellij/psi/search/PsiSearchRequest.java | 77 +++++++ .../find/findUsages/FindUsagesHandler.java | 44 ++-- .../find/findUsages/FindUsagesManager.java | 5 + .../find/findUsages/FindUsagesOptions.java | 6 + .../cache/impl/IndexCacheManagerImpl.java | 27 ++- .../impl/search/CachesBasedRefSearcher.java | 145 +++++++------ .../psi/impl/search/PsiSearchHelperImpl.java | 200 ++++++++++++++++-- .../intellij/psi/search/SearchRequestor.java | 31 +++ .../src/META-INF/LangExtensionPoints.xml | 2 + .../src/META-INF/LangExtensions.xml | 1 + 13 files changed, 540 insertions(+), 194 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java create mode 100644 platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index f28ab0552830..55be4edd7c03 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -31,6 +31,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.impl.search.MethodUsagesSearcher; import com.intellij.psi.impl.search.ThrowSearchUtil; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; @@ -585,11 +586,18 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ addMethodUsages((PsiMethod)element, results, options, options.searchScope); } else { - ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor() { + final ReadActionProcessor consumer = new ReadActionProcessor() { public boolean processInReadAction(final PsiReference ref) { return addResult(results, ref, options, element); } - }); + }; + + if (options.fastTrack != null) { + SearchRequestor.contributeTargets(element, options, options.fastTrack, consumer); + return; + } + + ReferencesSearch.search(element, options.searchScope, false).forEach(consumer); } } @@ -605,12 +613,23 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } } else { - boolean strictSignatureSearch = !options.isIncludeOverloadUsages; - MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() { - public boolean execute(PsiReference ref) { - return addResult(result, ref, options, method); + final boolean strictSignatureSearch = !options.isIncludeOverloadUsages; + final PsiReferenceProcessorAdapter processor = new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() { + public boolean execute(PsiReference ref) { + return addResult(result, ref, options, method); + } + }); + if (options.fastTrack != null) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + MethodUsagesSearcher.contributeSearchTargets(method, options, options.fastTrack, processor, strictSignatureSearch, true); } - })); + }); + + return; + } + + MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(processor); } } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index 5404edf9de36..245ea910408c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -3,16 +3,14 @@ */ package com.intellij.psi.impl.search; +import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadActionProcessor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.*; import com.intellij.psi.search.searches.MethodReferencesSearch; -import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PropertyUtil; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; @@ -22,102 +20,101 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class MethodUsagesSearcher implements QueryExecutor { + private static final ThreadLocal ourProcessing = new ThreadLocal(); + public boolean execute(final MethodReferencesSearch.SearchParameters p, final Processor consumer) { - final PsiMethod method = p.getMethod(); - final SearchScope searchScope = p.getScope(); - final PsiManager psiManager = PsiManager.getInstance(method.getProject()); - final boolean isStrictSignatureSearch = p.isStrictSignatureSearch(); - - final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiClass compute() { - return method.getContainingClass(); - } - }); - if (aClass == null) return true; - - if (method.isConstructor()) { - final ConstructorReferencesSearchHelper helper = new ConstructorReferencesSearchHelper(psiManager); - if (!helper.processConstructorReferences(consumer, method, searchScope, !isStrictSignatureSearch, isStrictSignatureSearch)) { - return false; - } + if (ourProcessing.get() != null) { + return true; } - boolean needStrictSignatureSearch = ApplicationManager.getApplication().runReadAction(new Computable() { - public Boolean compute() { - return method.isValid() && isStrictSignatureSearch && (aClass instanceof PsiAnonymousClass - || aClass.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.STATIC) - || method.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.PRIVATE)); + final PsiSearchRequest.ComplexRequest collector = PsiSearchRequest.composite(); + final PsiMethod method = p.getMethod(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); + options.isUsages = true; + contributeSearchTargets(method, options, collector, consumer, p.isStrictSignatureSearch(), false); } - }).booleanValue(); - if (needStrictSignatureSearch) { - return ReferencesSearch.search(method, searchScope, false).forEach(new ReadActionProcessor() { - public boolean processInReadAction(final PsiReference psiReference) { - return consumer.process(psiReference); + }); + + return method.getManager().getSearchHelper().processRequest(collector); + } + + public static void contributeSearchTargets(@NotNull final PsiMethod method, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer, final boolean strictSignatureSearch, boolean callOtherSearchers) { + final SearchScope searchScope = options.searchScope; + + if (callOtherSearchers) { + collector.addRequest(PsiSearchRequest.custom(new Runnable() { + public void run() { + ourProcessing.set(true); + try { + MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(consumer); + } + finally { + ourProcessing.set(null); + } } - }); + })); + + } + + final PsiManager psiManager = PsiManager.getInstance(method.getProject()); + + final PsiClass aClass = method.getContainingClass(); + if (aClass == null) return; + + if (method.isConstructor()) { + collector.addRequest(PsiSearchRequest.custom(new Runnable() { + public void run() { + new ConstructorReferencesSearchHelper(psiManager). + processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch); + } + })); + } + + boolean needStrictSignatureSearch = method.isValid() && strictSignatureSearch && (aClass instanceof PsiAnonymousClass + || aClass.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.STATIC) + || method.hasModifierProperty(PsiModifier.FINAL) + || method.hasModifierProperty(PsiModifier.PRIVATE)); + + if (needStrictSignatureSearch) { + SearchRequestor.contributeTargets(method, options, collector, consumer); + return; } final String textToSearch = method.getName(); - final PsiMethod[] methods = isStrictSignatureSearch ? new PsiMethod[]{method} : getOverloads(method); + final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false); - SearchScope accessScope = ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - if (!method.isValid()) return searchScope; - SearchScope accessScope = methods[0].getUseScope(); - for (int i = 1; i < methods.length; i++) { - PsiMethod method1 = methods[i]; - accessScope = accessScope.union(method1.getUseScope()); - } - return accessScope; - } - }); + SearchScope accessScope = methods[0].getUseScope(); + for (int i = 1; i < methods.length; i++) { + PsiMethod method1 = methods[i]; + accessScope = accessScope.union(method1.getUseScope()); + } - final TextOccurenceProcessor processor1 = new MethodTextOccurenceProcessor(consumer, aClass, isStrictSignatureSearch, methods); + final TextOccurenceProcessor processor1 = new MethodTextOccurenceProcessor(consumer, aClass, strictSignatureSearch, methods); final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope); short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES; - PsiSearchHelper helper = psiManager.getSearchHelper(); - if (!helper.processElementsWithWord(processor1, restrictedByAccess, textToSearch, searchContext, true)) return false; + collector.addRequest(PsiSearchRequest.elementsWithWord(restrictedByAccess, textToSearch, searchContext, true, processor1)); - final String propertyName = ApplicationManager.getApplication().runReadAction(new Computable(){ - public String compute() { - if (!method.isValid()) return null; - return PropertyUtil.getPropertyName(method); + final String propertyName = PropertyUtil.getPropertyName(method); + if (StringUtil.isNotEmpty(propertyName)) { + SearchScope additional = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(psiManager.getProject()), + StdFileTypes.JSP, StdFileTypes.JSPX, + StdFileTypes.XML, StdFileTypes.XHTML); + + for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) { + additional = additional.union(provider.getScope(psiManager.getProject())); } - }); - if (StringUtil.isEmpty(propertyName)) { - return true; + assert propertyName != null; + final SearchScope propScope = restrictedByAccess.intersectWith(additional); + collector.addRequest(PsiSearchRequest.elementsWithWord(propScope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, processor1)); } - final SearchScope scope = ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - SearchScope additional = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(psiManager.getProject()), - StdFileTypes.JSP, StdFileTypes.JSPX, - StdFileTypes.XML, StdFileTypes.XHTML); - - for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) { - SearchScope s = provider.getScope(psiManager.getProject()); - additional = additional.union(s); - } - - return restrictedByAccess.intersectWith(additional); - } - }); - return helper.processElementsWithWord(processor1, scope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, true); - } - - @NotNull - private static PsiMethod[] getOverloads(final PsiMethod method) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiMethod[] compute() { - if (!method.isValid()) return PsiMethod.EMPTY_ARRAY; - PsiClass aClass = method.getContainingClass(); - if (aClass == null) return new PsiMethod[]{method}; - return aClass.findMethodsByName(method.getName(), false); - } - }); } } diff --git a/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java b/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java index b50e67181ab3..4a14051e0eca 100644 --- a/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java +++ b/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java @@ -175,6 +175,8 @@ public interface PsiSearchHelper { */ void processAllFilesWithWordInLiterals(@NotNull String word, @NotNull GlobalSearchScope scope, @NotNull Processor processor); + boolean processRequest(@NotNull PsiSearchRequest request); + boolean processElementsWithWord(@NotNull TextOccurenceProcessor processor, @NotNull SearchScope searchScope, @NotNull String text, diff --git a/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java new file mode 100644 index 000000000000..65ddc53296f1 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java @@ -0,0 +1,77 @@ +package com.intellij.psi.search; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author peter + */ +public class PsiSearchRequest { + + public static SingleRequest elementsWithWord(@NotNull SearchScope searchScope, + @NotNull String word, + short searchContext, + boolean caseSensitive, @NotNull TextOccurenceProcessor processor) { + return new SingleRequest(searchScope, word, searchContext, caseSensitive, processor); + } + + public static ComplexRequest composite() { + return new ComplexRequest(); + } + + public static CustomRequest custom(Runnable searchAction) { + return new CustomRequest(searchAction); + } + + public static class SingleRequest extends PsiSearchRequest { + public final SearchScope searchScope; + public final String word; + public final short searchContext; + public final boolean caseSensitive; + public final TextOccurenceProcessor processor; + + private SingleRequest(@NotNull SearchScope searchScope, + @NotNull String word, + short searchContext, + boolean caseSensitive, + @NotNull TextOccurenceProcessor processor) { + + this.searchScope = searchScope; + this.word = word; + this.searchContext = searchContext; + this.caseSensitive = caseSensitive; + this.processor = processor; + } + } + + public static class ComplexRequest extends PsiSearchRequest { + private final List myComponents = new ArrayList(); + + private ComplexRequest() { + } + + public void addRequest(PsiSearchRequest request) { + if (request instanceof ComplexRequest) { + myComponents.addAll(((ComplexRequest)request).getConstituents()); + } else { + myComponents.add(request); + } + } + + public List getConstituents() { + return myComponents; + } + } + + public static class CustomRequest extends PsiSearchRequest { + public final Runnable searchAction; + + private CustomRequest(Runnable searchAction) { + this.searchAction = searchAction; + } + } + + +} diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java index 169a73bf03c4..ad1017bd71fc 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java @@ -23,10 +23,9 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.util.PsiUtilBase; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.*; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiUtilBase; import com.intellij.refactoring.util.TextOccurrencesUtil; import com.intellij.usageView.UsageInfo; import com.intellij.util.Processor; @@ -90,18 +89,39 @@ public abstract class FindUsagesHandler { return options; } - public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor processor, @NotNull FindUsagesOptions options) { - if (options.isUsages) { - ReferencesSearch.search(element, options.searchScope, false).forEach(new ReadActionProcessor() { - public boolean processInReadAction(final PsiReference ref) { - TextRange rangeInElement = ref.getRangeInElement(); - return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); + public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor processor, @NotNull final FindUsagesOptions options) { + final ReadActionProcessor refProcessor = new ReadActionProcessor() { + public boolean processInReadAction(final PsiReference ref) { + TextRange rangeInElement = ref.getRangeInElement(); + return processor + .process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); + } + }; + + final SearchScope scope = options.searchScope; + + final boolean searchText = options.isSearchForTextOccurences && scope instanceof GlobalSearchScope; + if (options.fastTrack != null) { + SearchRequestor.contributeTargets(element, options, options.fastTrack, refProcessor); + + // todo special kind of request for that + options.fastTrack.addRequest(PsiSearchRequest.custom(new Runnable() { + public void run() { + if (searchText) { + processUsagesInText(element, processor, (GlobalSearchScope)scope); + } } - }); + })); + + return; } - if (options.isSearchForTextOccurences && options.searchScope instanceof GlobalSearchScope) { - processUsagesInText(element, processor, (GlobalSearchScope)options.searchScope); + if (options.isUsages) { + ReferencesSearch.search(element, scope, false).forEach(refProcessor); + } + + if (searchText) { + processUsagesInText(element, processor, (GlobalSearchScope)scope); } } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index f1a7fb42c057..547c1a108c43 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -349,6 +349,9 @@ public class FindUsagesManager implements JDOMExternalizable { return descriptor.getAllElements(); } }); + + options.fastTrack = PsiSearchRequest.composite(); + for (final PsiElement element : elements) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { @@ -357,6 +360,8 @@ public class FindUsagesManager implements JDOMExternalizable { }); handler.processElementUsages(element, usageInfoProcessorToUsageProcessorAdapter, options); } + + PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequest(options.fastTrack); } }; } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java index 7cf569e17e0a..e0b4cdcd5c92 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.search.ProjectScope; +import com.intellij.psi.search.PsiSearchRequest; import com.intellij.psi.search.SearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -55,6 +56,7 @@ public class FindUsagesOptions extends UserDataHolderBase implements Cloneable { public boolean isWriteAccess = false; public boolean isIncludeOverloadUsages = false; public boolean isThrowUsages = false; + public PsiSearchRequest.ComplexRequest fastTrack = null; public FindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) { String defaultScopeName = FindSettings.getInstance().getDefaultScopeName(); @@ -70,6 +72,10 @@ public class FindUsagesOptions extends UserDataHolderBase implements Cloneable { } } + public FindUsagesOptions(SearchScope searchScope) { + this.searchScope = searchScope; + } + public Object clone() { return super.clone(); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java index 17c8b6dafdba..5273de0e288e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java @@ -19,12 +19,12 @@ package com.intellij.psi.impl.cache.impl; import com.intellij.ide.caches.CacheUpdater; import com.intellij.injected.editor.VirtualFileWindow; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadActionProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -78,6 +78,10 @@ public class IndexCacheManagerImpl implements CacheManager{ return processor.getResults().isEmpty() ? PsiFile.EMPTY_ARRAY : processor.toArray(PsiFile.EMPTY_ARRAY); } + public static boolean shouldBeFound(VirtualFile virtualFile, ProjectFileIndex index) { + return (index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary(); + } + public boolean processFilesWithWord(@NotNull final Processor psiFileProcessor, @NotNull final String word, final short occurrenceMask, @NotNull final GlobalSearchScope scope, final boolean caseSensitively) { final Set vFiles = new THashSet(); final GlobalSearchScope projectScope = GlobalSearchScope.allScope(myProject); @@ -100,20 +104,15 @@ public class IndexCacheManagerImpl implements CacheManager{ final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); - final Processor virtualFileProcessor = new Processor() { - public boolean process(final VirtualFile virtualFile) { + final Processor virtualFileProcessor = new ReadActionProcessor() { + @Override + public boolean processInReadAction(VirtualFile virtualFile) { LOG.assertTrue(virtualFile.isValid()); - return ApplicationManager.getApplication().runReadAction(new Computable() { - public Boolean compute() { - if (virtualFile.isValid() && scope.contains(virtualFile) && (index.isInContent(virtualFile) || index.isInLibrarySource(virtualFile))) { - if (virtualFile.getFileType().isBinary()) return Boolean.TRUE; - - final PsiFile psiFile = myPsiManager.findFile(virtualFile); - return psiFile == null || psiFileProcessor.process(psiFile); - } - return Boolean.TRUE; - } - }).booleanValue(); + if (virtualFile.isValid() && scope.contains(virtualFile) && shouldBeFound(virtualFile, index)) { + final PsiFile psiFile = myPsiManager.findFile(virtualFile); + return psiFile == null || psiFileProcessor.process(psiFile); + } + return true; } }; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index b7511856409a..5db0103fbd6e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -3,9 +3,9 @@ */ package com.intellij.psi.impl.search; +import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -15,82 +15,107 @@ import com.intellij.psi.search.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; +import org.jetbrains.annotations.NotNull; /** * @author max */ -public class CachesBasedRefSearcher implements QueryExecutor { - public static boolean DEBUG = false; +public class CachesBasedRefSearcher extends SearchRequestor implements QueryExecutor { + private static final ThreadLocal ourProcessing = new ThreadLocal(); public boolean execute(final ReferencesSearch.SearchParameters p, final Processor consumer) { + if (ourProcessing.get() != null) { + return true; + } + final PsiElement refElement = p.getElementToSearch(); + final PsiSearchRequest.ComplexRequest collector = PsiSearchRequest.composite(); - String text = ApplicationManager.getApplication().runReadAction(new Computable() { - public String compute() { - String text = null; - if (refElement instanceof PsiFile) { - final VirtualFile vFile = ((PsiFile)refElement).getVirtualFile(); - if (vFile != null) { - text = vFile.getNameWithoutExtension(); - } - } - else if (refElement instanceof PsiNamedElement) { - text = ((PsiNamedElement)refElement).getName(); - if (refElement instanceof PsiMetaOwner) { - final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData(); - if (metaData != null) text = metaData.getName(); - } - } - - if (text == null && refElement instanceof PsiMetaOwner) { - final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData(); - if (metaData != null) text = metaData.getName(); - } - return text; + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); + options.isUsages = true; + contributeSearchTargets(refElement, options, collector, consumer, p.isIgnoreAccessScope(), false, options.searchScope); } }); - if (StringUtil.isEmpty(text)) return true; - if (DEBUG) System.out.println("Searching for :" + text); + return refElement.getManager().getSearchHelper().processRequest(collector); + } - SearchScope searchScope = ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - return p.getEffectiveSearchScope(); - } - }); - final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi(); + @Override + public void contributeSearchTargets(@NotNull final PsiElement refElement, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer) { + contributeSearchTargets(refElement, options, collector, consumer, false, true, options.searchScope); + } - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { - ProgressManager.checkCanceled(); - if (DEBUG) { - System.out.println("!!! About to check " + element); - } - if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true; - final PsiReference[] refs = element.getReferences(); - for (PsiReference ref : refs) { - if (DEBUG) { - System.out.println("!!!!!!!!!!!!!! Ref " + ref); + private static void contributeSearchTargets(@NotNull final PsiElement refElement, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer, + final boolean ignoreAccessScope, + final boolean callOtherSearchers, + final SearchScope scope) { + if (!options.isUsages) { + return; + } + + if (callOtherSearchers) { + collector.addRequest(PsiSearchRequest.custom(new Runnable() { + public void run() { + ourProcessing.set(true); + try { + ReferencesSearch.search(refElement, scope, ignoreAccessScope).forEach(consumer); } - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - if (DEBUG) { - System.out.println("!!!!!!!!!!!!!!!!!!!!! Ref " + ref + " contains"); - } - if (ref.isReferenceTo(refElement)) { - if (DEBUG) { - System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Found ref " + ref); + finally { + ourProcessing.set(null); + } + } + })); + } + + String text = null; + if (refElement instanceof PsiFile) { + final VirtualFile vFile = ((PsiFile)refElement).getVirtualFile(); + if (vFile != null) { + text = vFile.getNameWithoutExtension(); + } + } + else if (refElement instanceof PsiNamedElement) { + text = ((PsiNamedElement)refElement).getName(); + if (refElement instanceof PsiMetaOwner) { + final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData(); + if (metaData != null) text = metaData.getName(); + } + } + + if (text == null && refElement instanceof PsiMetaOwner) { + final PsiMetaData metaData = ((PsiMetaOwner)refElement).getMetaData(); + if (metaData != null) text = metaData.getName(); + } + if (StringUtil.isNotEmpty(text)) { + final SearchScope searchScope = ignoreAccessScope ? scope : refElement.getUseScope().intersectWith(scope); + final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi(); + + final TextOccurenceProcessor processor = new TextOccurenceProcessor() { + public boolean execute(PsiElement element, int offsetInElement) { + ProgressManager.checkCanceled(); + if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true; + final PsiReference[] refs = element.getReferences(); + for (PsiReference ref : refs) { + if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { + if (ref.isReferenceTo(refElement)) { + return consumer.process(ref); } - return consumer.process(ref); } } + return true; } - return true; - } - }; + }; - short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS; - - final PsiSearchHelper helper = PsiManager.getInstance(refElement.getProject()).getSearchHelper(); - return helper.processElementsWithWord(processor, searchScope, text, searchContext, - refElement.getLanguage().isCaseSensitive()); + assert text != null; + final short mask = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS; + collector.addRequest(PsiSearchRequest.elementsWithWord(searchScope, text, mask, refElement.getLanguage().isCaseSensitive(), processor)); + } } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 91bc2f046286..70309af9ec53 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -25,16 +25,22 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.PsiManagerEx; +import com.intellij.psi.impl.cache.impl.IndexCacheManagerImpl; +import com.intellij.psi.impl.cache.impl.id.IdIndex; +import com.intellij.psi.impl.cache.impl.id.IdIndexEntry; import com.intellij.psi.search.*; import com.intellij.psi.search.searches.IndexPatternSearch; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; +import com.intellij.util.containers.MultiMap; +import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.text.StringSearcher; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -213,24 +219,39 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { progress.pushState(); progress.setText(PsiBundle.message("psi.scanning.files.progress")); } - myManager.startBatchFilesProcessingMode(); - try { - String text = searcher.getPattern(); - List fileSet = getFilesWithText(scope, searchContext, caseSensitively, text, progress); + String text = searcher.getPattern(); + List fileSet = getFilesWithText(scope, searchContext, caseSensitively, text, progress); - if (progress != null) { - progress.setText(PsiBundle.message("psi.search.for.word.progress", text)); + if (progress != null) { + progress.setText(PsiBundle.message("psi.search.for.word.progress", text)); + } + + return processPsiFileRoots(progress, fileSet, new Processor() { + public boolean process(PsiElement psiRoot) { + return LowLevelSearchUtil.processElementsContainingWordInElement(processor, psiRoot, searcher, false, progress); } + }); + } + private boolean processPsiFileRoots(final ProgressIndicator progress, + List files, + final Processor psiRootProcessor) { + myManager.startBatchFilesProcessingMode(); + try { final AtomicInteger counter = new AtomicInteger(0); final AtomicBoolean canceled = new AtomicBoolean(false); final AtomicBoolean pceThrown = new AtomicBoolean(false); - final int size = fileSet.size(); - boolean completed = JobUtil.invokeConcurrentlyUnderMyProgress(fileSet, new Processor() { - public boolean process(final PsiFile file) { - if (!(file instanceof PsiBinaryFile)) { + final int size = files.size(); + boolean completed = JobUtil.invokeConcurrentlyUnderMyProgress(files, new Processor() { + public boolean process(final VirtualFile vfile) { + final PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile compute() { + return myManager.findFile(vfile); + } + }); + if (file != null && !(file instanceof PsiBinaryFile)) { file.getViewProvider().getContents(); // load contents outside readaction ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { @@ -240,7 +261,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { for (PsiElement psiRoot : psiRoots) { if (progress != null) progress.checkCanceled(); if (!processed.add(psiRoot)) continue; - if (!LowLevelSearchUtil.processElementsContainingWordInElement(processor, psiRoot, searcher, false, progress)) { + if (!psiRootProcessor.process(psiRoot)) { canceled.set(true); return; } @@ -276,16 +297,27 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } } - private List getFilesWithText(@NotNull GlobalSearchScope scope, + private List getFilesWithText(@NotNull GlobalSearchScope scope, final short searchContext, final boolean caseSensitively, @NotNull String text, ProgressIndicator progress) { - List result = new ArrayList(); - if (!processFilesWithText(scope, searchContext, caseSensitively, text, new CommonProcessors.CollectProcessor(result), progress)) { - return Collections.emptyList(); + myManager.startBatchFilesProcessingMode(); + try { + final List result = new ArrayList(); + if (!processFilesWithText(scope, searchContext, caseSensitively, text, new Processor() { + public boolean process(PsiFile file) { + result.add(file.getViewProvider().getVirtualFile()); + return true; + } + }, progress)) { + return Collections.emptyList(); + } + return result; + } + finally { + myManager.finishBatchFilesProcessingMode(); } - return result; } private boolean processFilesWithText(@NotNull final GlobalSearchScope scope, @@ -447,6 +479,136 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { myManager.getCacheManager().processFilesWithWord(processor, word, UsageSearchContext.IN_STRINGS, scope, true); } + public boolean processRequest(@NotNull PsiSearchRequest request) { + if (request instanceof PsiSearchRequest.SingleRequest) { + return processSingleRequest((PsiSearchRequest.SingleRequest)request); + } + else if (request instanceof PsiSearchRequest.CustomRequest) { + ((PsiSearchRequest.CustomRequest)request).searchAction.run(); + return true; + } + else if (request instanceof PsiSearchRequest.ComplexRequest) { + final MultiMap singles = new MultiMap(); + final List customs = new ArrayList(); + distributePrimitives((PsiSearchRequest.ComplexRequest)request, singles, customs); + + if (processRequestsOptimized(singles)) { + for (PsiSearchRequest.CustomRequest custom : customs) { + custom.searchAction.run(); + } + return true; + } + + return false; + } else { + LOG.error("Unknown request: " + request); + return true; + } + } + + private boolean processRequestsOptimized(MultiMap singles) { + if (singles.isEmpty()) { + return true; + } + + if (singles.size() == 1) { + final Collection requests = singles.get(singles.keySet().iterator().next()); + if (requests.size() == 1) { + return processSingleRequest(requests.iterator().next()); + } + } + + final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); + if (progress != null) { + progress.pushState(); + progress.setText(PsiBundle.message("psi.scanning.files.progress")); + } + + final MultiMap candidateFiles = collectFiles(singles); + + final Map searchers = new HashMap(); + final Set allWords = new TreeSet(); + for (PsiSearchRequest.SingleRequest singleRequest : candidateFiles.values()) { + searchers.put(singleRequest, new StringSearcher(singleRequest.word, singleRequest.caseSensitive, true)); + allWords.add(singleRequest.word); + } + + if (progress != null) { + progress.setText(PsiBundle.message("psi.search.for.word.progress", StringUtil.join(allWords, ", "))); + } + + return processPsiFileRoots(progress, new ArrayList(candidateFiles.keySet()), new Processor() { + public boolean process(PsiElement psiRoot) { + final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile(); + for (PsiSearchRequest.SingleRequest singleRequest : candidateFiles.get(vfile)) { + StringSearcher searcher = searchers.get(singleRequest); + if (!LowLevelSearchUtil.processElementsContainingWordInElement(singleRequest.processor, psiRoot, searcher, false, progress)) { + return false; + } + } + return true; + } + }); + } + + private MultiMap collectFiles(MultiMap singles) { + final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex(); + final MultiMap candidateFiles = new MultiMap(); + for (IdIndexEntry key : singles.keySet()) { + final Collection data = singles.get(key); + GlobalSearchScope commonScope = null; + for (PsiSearchRequest.SingleRequest r : data) { + final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope; + commonScope = commonScope == null ? scope : commonScope.uniteWith(scope); + } + assert commonScope != null; + + + FileBasedIndex.getInstance().processValues(IdIndex.NAME, key, null, new FileBasedIndex.ValueProcessor() { + public boolean process(VirtualFile file, Integer value) { + if (!IndexCacheManagerImpl.shouldBeFound(file, index)) { + return true; + } + int mask = value.intValue(); + for (PsiSearchRequest.SingleRequest single : data) { + if ((mask & single.searchContext) != 0) { + candidateFiles.putValue(file, single); + } + } + return true; + } + }, commonScope); + } + return candidateFiles; + } + + private void distributePrimitives(PsiSearchRequest.ComplexRequest request, + MultiMap singles, + List customs) { + for (PsiSearchRequest primitive : request.getConstituents()) { + if (primitive instanceof PsiSearchRequest.CustomRequest) { + customs.add((PsiSearchRequest.CustomRequest)primitive); + } else { + final PsiSearchRequest.SingleRequest single = (PsiSearchRequest.SingleRequest) primitive; + final SearchScope scope = single.searchScope; + if (scope instanceof LocalSearchScope) { + customs.add(PsiSearchRequest.custom(new Runnable() { + public void run() { + processSingleRequest(single); + } + })); + } else { + singles.putValue(new IdIndexEntry(single.word, single.caseSensitive), single); + } + + } + } + } + + private boolean processSingleRequest(PsiSearchRequest.SingleRequest single) { + return processElementsWithWord(single.processor, single.searchScope, single.word, single.searchContext, single.caseSensitive); + } + public SearchCostResult isCheapEnoughToSearch(@NotNull String name, @NotNull GlobalSearchScope scope, @Nullable final PsiFile fileToIgnoreOccurencesIn, diff --git a/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java b/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java new file mode 100644 index 000000000000..b75b25ffbabe --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java @@ -0,0 +1,31 @@ +package com.intellij.psi.search; + +import com.intellij.find.findUsages.FindUsagesOptions; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public abstract class SearchRequestor { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.searchRequestor"); + + public static void contributeTargets(final PsiElement element, + final FindUsagesOptions options, + final PsiSearchRequest.ComplexRequest collector, final Processor processor) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + for (SearchRequestor searcher : EP_NAME.getExtensions()) { + searcher.contributeSearchTargets(element, options, collector, processor); + } + } + }); + } + + public abstract void contributeSearchTargets(@NotNull PsiElement target, @NotNull FindUsagesOptions options, @NotNull PsiSearchRequest.ComplexRequest collector, Processor processor); + +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 1efa96bc041b..f705afae1875 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -128,6 +128,8 @@ + + + From 7a25419da30364d4e0cac1527fd7322cafcadb82 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 19:19:45 +0100 Subject: [PATCH 22/81] kill method usage duplicates --- .../searches/MethodReferencesSearch.java | 4 +- .../search/searches/ReferenceDescriptor.java | 42 +++++++++++++++++++ .../psi/search/searches/ReferencesSearch.java | 38 +---------------- 3 files changed, 46 insertions(+), 38 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/psi/search/searches/ReferenceDescriptor.java diff --git a/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java b/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java index bfa2b88a9947..c66605b7da69 100644 --- a/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java +++ b/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java @@ -20,6 +20,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.Query; +import gnu.trove.TObjectHashingStrategy; /** * @author max @@ -54,7 +55,8 @@ public class MethodReferencesSearch extends ExtensibleQueryFactory search(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch) { - return INSTANCE.createUniqueResultsQuery(new SearchParameters(method, scope, strictSignatureSearch)); + //noinspection unchecked + return INSTANCE.createUniqueResultsQuery(new SearchParameters(method, scope, strictSignatureSearch), TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER); } public static Query search(final PsiMethod method, final boolean strictSignatureSearch) { diff --git a/platform/lang-api/src/com/intellij/psi/search/searches/ReferenceDescriptor.java b/platform/lang-api/src/com/intellij/psi/search/searches/ReferenceDescriptor.java new file mode 100644 index 000000000000..7621f4d6f16e --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/searches/ReferenceDescriptor.java @@ -0,0 +1,42 @@ +package com.intellij.psi.search.searches; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReference; +import com.intellij.util.Function; + +/** +* @author max +*/ +public class ReferenceDescriptor { + public static final Function MAPPER = new Function() { + public ReferenceDescriptor fun(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + final PsiFile file = element.getContainingFile(); + return new ReferenceDescriptor(file, element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset()); + } + }; + private final PsiFile file; + private final int offset; + + ReferenceDescriptor(PsiFile file, int offset) { + this.file = file; + this.offset = offset; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ReferenceDescriptor)) return false; + + ReferenceDescriptor that = (ReferenceDescriptor)o; + + if (offset != that.offset) return false; + return file.equals(that.file); + } + + @Override + public int hashCode() { + return 31 * file.hashCode() + offset; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/search/searches/ReferencesSearch.java b/platform/lang-api/src/com/intellij/psi/search/searches/ReferencesSearch.java index 1d1e49dd4389..63f33c59a83d 100644 --- a/platform/lang-api/src/com/intellij/psi/search/searches/ReferencesSearch.java +++ b/platform/lang-api/src/com/intellij/psi/search/searches/ReferencesSearch.java @@ -16,11 +16,9 @@ package com.intellij.psi.search.searches; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; -import com.intellij.util.Function; import com.intellij.util.Query; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; @@ -31,40 +29,6 @@ import org.jetbrains.annotations.NotNull; public class ReferencesSearch extends ExtensibleQueryFactory { private static final ReferencesSearch INSTANCE = new ReferencesSearch(); - private static class ReferenceDescriptor { - private final PsiFile file; - private final int offset; - - private ReferenceDescriptor(PsiFile file, int offset) { - this.file = file; - this.offset = offset; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ReferenceDescriptor)) return false; - - ReferenceDescriptor that = (ReferenceDescriptor)o; - - if (offset != that.offset) return false; - return file.equals(that.file); - } - - @Override - public int hashCode() { - return 31 * file.hashCode() + offset; - } - } - - private static final Function MAPPER = new Function() { - public ReferenceDescriptor fun(PsiReference psiReference) { - final PsiElement element = psiReference.getElement(); - final PsiFile file = element.getContainingFile(); - return new ReferenceDescriptor(file, element.getTextRange().getStartOffset() + psiReference.getRangeInElement().getStartOffset()); - } - }; - private ReferencesSearch() { } @@ -116,6 +80,6 @@ public class ReferencesSearch extends ExtensibleQueryFactory search(@NotNull SearchParameters parameters) { //noinspection unchecked - return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, MAPPER); + return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER); } } From 72c97a5a5aeb5057f4d613cd72ff4433715dd348 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 12:59:36 +0400 Subject: [PATCH 23/81] eager PSI calculation, fix no PSI calculation --- .../com/intellij/find/findUsages/FindUsagesManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 547c1a108c43..7fa5b011011d 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -44,6 +44,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.StatusBar; import com.intellij.psi.*; import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.PsiSearchRequest; import com.intellij.psi.search.SearchScope; import com.intellij.ui.LightweightHint; import com.intellij.ui.content.Content; @@ -52,6 +53,7 @@ import com.intellij.usageView.UsageViewManager; import com.intellij.usageView.UsageViewUtil; import com.intellij.usages.*; import com.intellij.usages.impl.UsageViewManagerImpl; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; @@ -338,11 +340,11 @@ public class FindUsagesManager implements JDOMExternalizable { if (scopeFile != null) { options.searchScope = new LocalSearchScope(scopeFile); } - final Processor usageInfoProcessorToUsageProcessorAdapter = new Processor() { + final Processor usageInfoProcessor = new CommonProcessors.UniqueProcessor(new Processor() { public boolean process(UsageInfo usageInfo) { return processor.process(UsageInfoToUsageConverter.convert(descriptor, usageInfo)); } - }; + }); List elements = ApplicationManager.getApplication().runReadAction(new Computable>() { public List compute() { @@ -358,7 +360,7 @@ public class FindUsagesManager implements JDOMExternalizable { LOG.assertTrue(element.isValid()); } }); - handler.processElementUsages(element, usageInfoProcessorToUsageProcessorAdapter, options); + handler.processElementUsages(element, usageInfoProcessor, options); } PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequest(options.fastTrack); From 567fab512e357aad903ea10ca62a68d0d3621865 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 19:20:46 +0100 Subject: [PATCH 24/81] kill UsageInfo duplicates --- .../src/com/intellij/find/findUsages/FindUsagesManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 7fa5b011011d..e088b31d8169 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -368,6 +368,7 @@ public class FindUsagesManager implements JDOMExternalizable { }; } + private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(final List elementsToSearch) { final ArrayList targets = new ArrayList(elementsToSearch.size()); for (PsiElement element : elementsToSearch) { From 8efb96c8665467085c210f4ae6da9bb565351d59 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 21:59:52 +0100 Subject: [PATCH 25/81] a couple of useful MultiMap methods --- .../com/intellij/util/containers/MultiMap.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java index 371c0f5f5304..d8e5dcd4b838 100644 --- a/platform/util/src/com/intellij/util/containers/MultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MultiMap.java @@ -43,6 +43,22 @@ public class MultiMap { return Collections.emptyList(); } + public void putAllValues(MultiMap from) { + for (K k : from.keySet()) { + //noinspection unchecked + putValues(k, ((MultiMap)from).get(k)); + } + } + + public void putValues(K key, Collection values) { + Collection list = myMap.get(key); + if (list == null) { + list = createCollection(); + myMap.put(key, list); + } + list.addAll(values); + } + public void putValue(K key, V value) { Collection list = myMap.get(key); if (list == null) { From 9a9526ebddfc7749ab776fcbe57f448e9d9bfba4 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 22:18:58 +0100 Subject: [PATCH 26/81] correctly search for elements where the name contains several words custom requests should return boolean as the usual ones do --- .../intellij/psi/search/PsiSearchRequest.java | 7 +- .../psi/impl/search/PsiSearchHelperImpl.java | 97 +++++++++++++------ 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java index 65ddc53296f1..93d6c61933b7 100644 --- a/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java +++ b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java @@ -1,5 +1,6 @@ package com.intellij.psi.search; +import com.intellij.openapi.util.Computable; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -21,7 +22,7 @@ public class PsiSearchRequest { return new ComplexRequest(); } - public static CustomRequest custom(Runnable searchAction) { + public static CustomRequest custom(Computable searchAction) { return new CustomRequest(searchAction); } @@ -66,9 +67,9 @@ public class PsiSearchRequest { } public static class CustomRequest extends PsiSearchRequest { - public final Runnable searchAction; + public final Computable searchAction; - private CustomRequest(Runnable searchAction) { + private CustomRequest(Computable searchAction) { this.searchAction = searchAction; } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 70309af9ec53..6b9cd4ff52b6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -484,17 +484,18 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return processSingleRequest((PsiSearchRequest.SingleRequest)request); } else if (request instanceof PsiSearchRequest.CustomRequest) { - ((PsiSearchRequest.CustomRequest)request).searchAction.run(); - return true; + return ((PsiSearchRequest.CustomRequest)request).searchAction.compute(); } else if (request instanceof PsiSearchRequest.ComplexRequest) { - final MultiMap singles = new MultiMap(); + final MultiMap, PsiSearchRequest.SingleRequest> singles = new MultiMap, PsiSearchRequest.SingleRequest>(); final List customs = new ArrayList(); distributePrimitives((PsiSearchRequest.ComplexRequest)request, singles, customs); if (processRequestsOptimized(singles)) { for (PsiSearchRequest.CustomRequest custom : customs) { - custom.searchAction.run(); + if (!custom.searchAction.compute()) { + return false; + } } return true; } @@ -506,7 +507,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } } - private boolean processRequestsOptimized(MultiMap singles) { + private boolean processRequestsOptimized(MultiMap, PsiSearchRequest.SingleRequest> singles) { if (singles.isEmpty()) { return true; } @@ -551,39 +552,68 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { }); } - private MultiMap collectFiles(MultiMap singles) { + private MultiMap collectFiles(MultiMap, PsiSearchRequest.SingleRequest> singles) { final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex(); - final MultiMap candidateFiles = new MultiMap(); - for (IdIndexEntry key : singles.keySet()) { + final MultiMap result = new MultiMap(); + for (Set key : singles.keySet()) { final Collection data = singles.get(key); - GlobalSearchScope commonScope = null; - for (PsiSearchRequest.SingleRequest r : data) { - final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope; - commonScope = commonScope == null ? scope : commonScope.uniteWith(scope); - } - assert commonScope != null; + GlobalSearchScope commonScope = uniteScopes(data); + MultiMap intersection = null; - FileBasedIndex.getInstance().processValues(IdIndex.NAME, key, null, new FileBasedIndex.ValueProcessor() { - public boolean process(VirtualFile file, Integer value) { - if (!IndexCacheManagerImpl.shouldBeFound(file, index)) { - return true; - } - int mask = value.intValue(); - for (PsiSearchRequest.SingleRequest single : data) { - if ((mask & single.searchContext) != 0) { - candidateFiles.putValue(file, single); + boolean first = true; + for (IdIndexEntry entry : key) { + final MultiMap local = findFilesWithIndexEntry(entry, index, data, commonScope); + if (first) { + intersection = local; + first = false; + } else { + for (VirtualFile file : local.keySet()) { + if (intersection.containsKey(file)) { + intersection.putValues(file, local.get(file)); } } + } + } + result.putAllValues(intersection); + } + return result; + } + + private static GlobalSearchScope uniteScopes(Collection requests) { + GlobalSearchScope commonScope = null; + for (PsiSearchRequest.SingleRequest r : requests) { + final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope; + commonScope = commonScope == null ? scope : commonScope.uniteWith(scope); + } + assert commonScope != null; + return commonScope; + } + + private static MultiMap findFilesWithIndexEntry(IdIndexEntry entry, + final ProjectFileIndex index, + final Collection data, + GlobalSearchScope commonScope) { + final MultiMap local = new MultiMap(); + FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor() { + public boolean process(VirtualFile file, Integer value) { + if (!IndexCacheManagerImpl.shouldBeFound(file, index)) { return true; } - }, commonScope); - } - return candidateFiles; + int mask = value.intValue(); + for (PsiSearchRequest.SingleRequest single : data) { + if ((mask & single.searchContext) != 0) { + local.putValue(file, single); + } + } + return true; + } + }, commonScope); + return local; } private void distributePrimitives(PsiSearchRequest.ComplexRequest request, - MultiMap singles, + MultiMap, PsiSearchRequest.SingleRequest> singles, List customs) { for (PsiSearchRequest primitive : request.getConstituents()) { if (primitive instanceof PsiSearchRequest.CustomRequest) { @@ -592,13 +622,18 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { final PsiSearchRequest.SingleRequest single = (PsiSearchRequest.SingleRequest) primitive; final SearchScope scope = single.searchScope; if (scope instanceof LocalSearchScope) { - customs.add(PsiSearchRequest.custom(new Runnable() { - public void run() { - processSingleRequest(single); + customs.add(PsiSearchRequest.custom(new Computable() { + public Boolean compute() { + return processSingleRequest(single); } })); } else { - singles.putValue(new IdIndexEntry(single.word, single.caseSensitive), single); + final List words = StringUtil.getWordsIn(single.word); + final Set key = new HashSet(words.size()); + for (String word : words) { + key.add(new IdIndexEntry(word, single.caseSensitive)); + } + singles.putValue(key, single); } } From d8b3a9430f1f7101f184d4d9073334eca7e3cbec Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 22:19:34 +0100 Subject: [PATCH 27/81] use new API for java method & property access search --- .../findUsages/JavaFindUsagesHandler.java | 63 +++++--------- .../psi/impl/search/MethodUsagesSearcher.java | 69 +++++++--------- .../SimpleAccessorReferenceSearcher.java | 82 +++++++++---------- .../find/findUsages/FindUsagesHandler.java | 5 +- .../impl/search/CachesBasedRefSearcher.java | 36 ++++---- resources/src/META-INF/IdeaPlugin.xml | 5 +- 6 files changed, 114 insertions(+), 146 deletions(-) diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index 55be4edd7c03..449ebccff88e 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -31,7 +31,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.impl.search.MethodUsagesSearcher; import com.intellij.psi.impl.search.ThrowSearchUtil; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; @@ -440,7 +439,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } final PsiClass methodClass = method.getContainingClass(); if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)){ - addMethodUsages(methods[i], results, options, options.searchScope); + addElementUsages(methods[i], results, options); } else{ boolean strictSignatureSearch = !options.isIncludeOverloadUsages; @@ -454,9 +453,8 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } } else { - PsiMethod[] methods = aClass.getMethods(); - for (PsiMethod method : methods) { - addMethodUsages(method, results, options, options.searchScope); + for (PsiMethod method : aClass.getMethods()) { + addElementUsages(method, results, options); } } } @@ -581,28 +579,10 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } } - public static void addElementUsages(final PsiElement element, final Processor results, final FindUsagesOptions options) { - if (element instanceof PsiMethod){ - addMethodUsages((PsiMethod)element, results, options, options.searchScope); - } - else { - final ReadActionProcessor consumer = new ReadActionProcessor() { - public boolean processInReadAction(final PsiReference ref) { - return addResult(results, ref, options, element); - } - }; - - if (options.fastTrack != null) { - SearchRequestor.contributeTargets(element, options, options.fastTrack, consumer); - return; - } - - ReferencesSearch.search(element, options.searchScope, false).forEach(consumer); - } - } - - private static void addMethodUsages(final PsiMethod method, final Processor result, final FindUsagesOptions options, SearchScope searchScope) { - if (method.isConstructor()) { + public static void addElementUsages(final PsiElement element, final Processor result, final FindUsagesOptions options) { + final SearchScope searchScope = options.searchScope; + if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()){ + PsiMethod method = (PsiMethod)element; if (options.isIncludeOverloadUsages) { for (PsiMethod constructor : method.getContainingClass().getConstructors()) { addConstructorUsages(constructor, searchScope, result, options); @@ -611,25 +591,24 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ else { addConstructorUsages(method, searchScope, result, options); } + return; } - else { - final boolean strictSignatureSearch = !options.isIncludeOverloadUsages; - final PsiReferenceProcessorAdapter processor = new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() { - public boolean execute(PsiReference ref) { - return addResult(result, ref, options, method); - } - }); - if (options.fastTrack != null) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - MethodUsagesSearcher.contributeSearchTargets(method, options, options.fastTrack, processor, strictSignatureSearch, true); - } - }); - return; + final ReadActionProcessor consumer = new ReadActionProcessor() { + public boolean processInReadAction(final PsiReference ref) { + return addResult(result, ref, options, element); } + }; - MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(processor); + if (options.fastTrack != null) { + SearchRequestor.contributeTargets(element, options, options.fastTrack, consumer); + return; + } + + if (element instanceof PsiMethod) { + MethodReferencesSearch.search((PsiMethod)element, searchScope, !options.isIncludeOverloadUsages).forEach(consumer); + } else { + ReferencesSearch.search(element, searchScope, false).forEach(consumer); } } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index 245ea910408c..e06d65981575 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -5,13 +5,10 @@ package com.intellij.psi.impl.search; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.search.*; import com.intellij.psi.search.searches.MethodReferencesSearch; -import com.intellij.psi.util.PropertyUtil; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; @@ -19,7 +16,7 @@ import org.jetbrains.annotations.NotNull; /** * @author max */ -public class MethodUsagesSearcher implements QueryExecutor { +public class MethodUsagesSearcher extends SearchRequestor implements QueryExecutor { private static final ThreadLocal ourProcessing = new ThreadLocal(); public boolean execute(final MethodReferencesSearch.SearchParameters p, final Processor consumer) { @@ -29,37 +26,49 @@ public class MethodUsagesSearcher implements QueryExecutor consumer, final boolean strictSignatureSearch, boolean callOtherSearchers) { - final SearchScope searchScope = options.searchScope; - - if (callOtherSearchers) { - collector.addRequest(PsiSearchRequest.custom(new Runnable() { - public void run() { + final Processor processor) { + if (target instanceof PsiMethod) { + final boolean strictSignatureSearch = !options.isIncludeOverloadUsages; + final PsiMethod method = (PsiMethod)target; + contributeSearchTargets(method, options, collector, processor, strictSignatureSearch, false); + collector.addRequest(PsiSearchRequest.custom(new Computable() { + public Boolean compute() { ourProcessing.set(true); try { - MethodReferencesSearch.search(method, searchScope, strictSignatureSearch).forEach(consumer); + return MethodReferencesSearch.search(method, options.searchScope, strictSignatureSearch).forEach(processor); } finally { ourProcessing.set(null); } } })); - } + } + + private static void contributeSearchTargets(@NotNull final PsiMethod method, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer, final boolean strictSignatureSearch, final boolean fromSearcher) { + final SearchScope searchScope = options.searchScope; final PsiManager psiManager = PsiManager.getInstance(method.getProject()); @@ -67,9 +76,9 @@ public class MethodUsagesSearcher implements QueryExecutor() { + public Boolean compute() { + return new ConstructorReferencesSearchHelper(psiManager). processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch); } })); @@ -80,9 +89,8 @@ public class MethodUsagesSearcher implements QueryExecutor { - public boolean execute(final ReferencesSearch.SearchParameters queryParameters, final Processor consumer) { - final PsiElement refElement = queryParameters.getElementToSearch(); - if (!(refElement instanceof PsiMethod)) return true; - final PsiMethod method = (PsiMethod)refElement; - final String propertyName = ApplicationManager.getApplication().runReadAction(new Computable() { - public String compute() { - if (!method.isValid()) return null; - return PropertyUtil.getPropertyName(method); - } - }); - if (StringUtil.isEmptyOrSpaces(propertyName)) { - return true; - } - SearchScope searchScope = ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - SearchScope searchScope = queryParameters.getEffectiveSearchScope(); - if (searchScope instanceof GlobalSearchScope) { - searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)searchScope, - StdFileTypes.JSP, - StdFileTypes.JSPX, - StdFileTypes.XML, - StdFileTypes.XHTML); - } - return searchScope; - } - }); +public class SimpleAccessorReferenceSearcher extends SearchRequestor { - final PsiSearchHelper helper = PsiManager.getInstance(refElement.getProject()).getSearchHelper(); - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { - final PsiReference[] refs = element.getReferences(); - for (PsiReference ref : refs) { - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - if (ref.isReferenceTo(refElement)) { - return consumer.process(ref); + @Override + public void contributeSearchTargets(@NotNull final PsiElement refElement, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer) { + if (!(refElement instanceof PsiMethod)) return; + + final PsiMethod method = (PsiMethod)refElement; + + final String propertyName = PropertyUtil.getPropertyName(method); + if (StringUtil.isNotEmpty(propertyName)) { + SearchScope additional = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(method.getProject()), + StdFileTypes.JSP, StdFileTypes.JSPX, + StdFileTypes.XML, StdFileTypes.XHTML); + + for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) { + additional = additional.union(provider.getScope(method.getProject())); + } + assert propertyName != null; + final SearchScope propScope = options.searchScope.intersectWith(method.getUseScope()).intersectWith(additional); + collector.addRequest(PsiSearchRequest.elementsWithWord(propScope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, new TextOccurenceProcessor() { + public boolean execute(PsiElement element, int offsetInElement) { + for (PsiReference ref : element.getReferences()) { + if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { + if (ref.isReferenceTo(refElement)) { + return consumer.process(ref); + } } } + return true; } - return true; - } - }; + })); + } - return helper.processElementsWithWord(processor, searchScope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, false); } } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java index ad1017bd71fc..8cff0399098a 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java @@ -105,11 +105,12 @@ public abstract class FindUsagesHandler { SearchRequestor.contributeTargets(element, options, options.fastTrack, refProcessor); // todo special kind of request for that - options.fastTrack.addRequest(PsiSearchRequest.custom(new Runnable() { - public void run() { + options.fastTrack.addRequest(PsiSearchRequest.custom(new Computable() { + public Boolean compute() { if (searchText) { processUsagesInText(element, processor, (GlobalSearchScope)scope); } + return true; } })); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index 5db0103fbd6e..9e9334b7a34b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -5,7 +5,7 @@ package com.intellij.psi.impl.search; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -35,7 +35,8 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec public void run() { final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); options.isUsages = true; - contributeSearchTargets(refElement, options, collector, consumer, p.isIgnoreAccessScope(), false, options.searchScope); + contributeSearchTargets(refElement, options, collector, consumer, p.isIgnoreAccessScope(), options.searchScope); + SearchRequestor.contributeTargets(refElement, options, collector, consumer); } }); return refElement.getManager().getSearchHelper().processRequest(collector); @@ -46,7 +47,20 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec @NotNull FindUsagesOptions options, @NotNull PsiSearchRequest.ComplexRequest collector, final Processor consumer) { - contributeSearchTargets(refElement, options, collector, consumer, false, true, options.searchScope); + final boolean ignoreAccessScope = false; + final SearchScope scope = options.searchScope; + contributeSearchTargets(refElement, options, collector, consumer, ignoreAccessScope, scope); + collector.addRequest(PsiSearchRequest.custom(new Computable() { + public Boolean compute() { + ourProcessing.set(true); + try { + return ReferencesSearch.search(refElement, scope, ignoreAccessScope).forEach(consumer); + } + finally { + ourProcessing.set(null); + } + } + })); } private static void contributeSearchTargets(@NotNull final PsiElement refElement, @@ -54,26 +68,11 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec @NotNull PsiSearchRequest.ComplexRequest collector, final Processor consumer, final boolean ignoreAccessScope, - final boolean callOtherSearchers, final SearchScope scope) { if (!options.isUsages) { return; } - if (callOtherSearchers) { - collector.addRequest(PsiSearchRequest.custom(new Runnable() { - public void run() { - ourProcessing.set(true); - try { - ReferencesSearch.search(refElement, scope, ignoreAccessScope).forEach(consumer); - } - finally { - ourProcessing.set(null); - } - } - })); - } - String text = null; if (refElement instanceof PsiFile) { final VirtualFile vFile = ((PsiFile)refElement).getVirtualFile(); @@ -99,7 +98,6 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec final TextOccurenceProcessor processor = new TextOccurenceProcessor() { public boolean execute(PsiElement element, int offsetInElement) { - ProgressManager.checkCanceled(); if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true; final PsiReference[] refs = element.getReferences(); for (PsiReference ref : refs) { diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e52fd725d200..cf90ef229719 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -202,9 +202,10 @@ - + + @@ -214,6 +215,8 @@ + + From f62b85c672c8fd27d119c65d72c19062bda9b5a2 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 2 Jun 2010 22:19:59 +0100 Subject: [PATCH 28/81] faster groovy accessor and dynamic usages search --- plugins/groovy/src/META-INF/plugin.xml | 4 +- .../AccessorReferencesSearcher.java | 44 ++++++------- .../MethodLateBoundReferencesSearcher.java | 61 ++++++++----------- .../plugins/groovy/lang/psi/util/PsiUtil.java | 16 ++--- 4 files changed, 56 insertions(+), 69 deletions(-) diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 9cc9d2b1bb2e..2361d170b424 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -178,8 +178,8 @@ - - + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java index 4c245a70493b..69b35fef6e58 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java @@ -28,26 +28,37 @@ import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.Nullable; +import com.intellij.find.findUsages.FindUsagesOptions; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; +import com.intellij.psi.ReferenceRange; +import com.intellij.psi.search.*; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; /** * author ven */ -public class AccessorReferencesSearcher implements QueryExecutor { +public class AccessorReferencesSearcher extends SearchRequestor { + @Override + public void contributeSearchTargets(@NotNull PsiElement target, + @NotNull final FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + final Processor consumer) { + if (!(target instanceof PsiMethod)) { + return; + } - public boolean execute(final MethodReferencesSearch.SearchParameters searchParameters, final Processor consumer) { - final PsiMethod method = searchParameters.getMethod(); - final String propertyName = getPropertyName(method); - if (propertyName == null) return true; + final PsiMethod method = (PsiMethod)target; - SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { - public SearchScope compute() { - return searchParameters.getScope(); - } - }); + final String propertyName = GroovyPropertyUtils.getPropertyName(method); + if (propertyName == null) return; + + SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope); - final PsiSearchHelper helper = PsiManager.getInstance(method.getProject()).getSearchHelper(); final TextOccurenceProcessor processor = new TextOccurenceProcessor() { public boolean execute(PsiElement element, int offsetInElement) { final PsiReference[] refs = element.getReferences(); @@ -62,16 +73,7 @@ public class AccessorReferencesSearcher implements QueryExecutor() { - @Nullable - public String compute() { - return GroovyPropertyUtils.getPropertyName(method); - } - }); - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java index 12707c5f340b..2ff03aff2fe4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java @@ -16,21 +16,18 @@ package org.jetbrains.plugins.groovy.findUsages; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; -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.MethodReferencesSearch; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.*; import com.intellij.psi.util.PropertyUtil; import com.intellij.util.Processor; -import com.intellij.util.QueryExecutor; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.search.GrSourceFilterScope; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -38,25 +35,25 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; /** * @author ven */ -public class MethodLateBoundReferencesSearcher implements QueryExecutor { - public boolean execute(final MethodReferencesSearch.SearchParameters params, final Processor consumer) { - final PsiMethod method = params.getMethod(); - SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { - public SearchScope compute() { - return params.getScope().intersectWith(getUseScope(method)); - } - }); +public class MethodLateBoundReferencesSearcher extends SearchRequestor { + @Override + public void contributeSearchTargets(@NotNull PsiElement target, + @NotNull FindUsagesOptions options, + @NotNull PsiSearchRequest.ComplexRequest collector, + Processor consumer) { + if (!(target instanceof PsiMethod)) { + return; + } - final String name = method.getName(); + final PsiMethod method = (PsiMethod)target; + SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope.intersectWith(getUseScope(method))); - final Project project = method.getProject(); - if (!processTextOccurrences(searchScope, name, consumer, project)) return false; + orderSearching(searchScope, method.getName(), consumer, collector); - final String propName = getPropertyName(method); + final String propName = PropertyUtil.getPropertyName(method); if (propName != null) { - if (!processTextOccurrences(searchScope, propName, consumer, project)) return false; + orderSearching(searchScope, propName, consumer, collector); } - return true; } private static SearchScope getUseScope(final PsiMethod method) { @@ -72,16 +69,11 @@ public class MethodLateBoundReferencesSearcher implements QueryExecutor(){ - @Nullable - public String compute() { - return PropertyUtil.getPropertyName(method); - } - }); - } - private static boolean processTextOccurrences(SearchScope searchScope, final String name, final Processor consumer, Project project) { + private static void orderSearching(SearchScope searchScope, + final String name, + final Processor consumer, + @NotNull PsiSearchRequest.ComplexRequest collector) { final TextOccurenceProcessor processor = new TextOccurenceProcessor() { public boolean execute(PsiElement element, int offsetInElement) { if (!(element instanceof GrReferenceExpression)) { @@ -97,8 +89,7 @@ public class MethodLateBoundReferencesSearcher implements QueryExecutor originalScopeComputation) { //important to compute originalSearchScope in read action! - return ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - final SearchScope originalScope = originalScopeComputation.compute(); - if (originalScope instanceof GlobalSearchScope) { - return GlobalSearchScope - .getScopeRestrictedByFileTypes((GlobalSearchScope)originalScope, GroovyFileTypeLoader.getGroovyEnabledFileTypes()); - } - return originalScope; - } - }); + public static SearchScope restrictScopeToGroovyFiles(SearchScope originalScope) { + if (originalScope instanceof GlobalSearchScope) { + return GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)originalScope, GroovyFileTypeLoader.getGroovyEnabledFileTypes()); + } + return originalScope; } @Nullable From a6ca957865c691a6305f25ce95deb69a87a52b9a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 7 Jun 2010 15:30:08 +0400 Subject: [PATCH 29/81] control for scope --- .../src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 6b9cd4ff52b6..69c1c184361e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -602,7 +602,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } int mask = value.intValue(); for (PsiSearchRequest.SingleRequest single : data) { - if ((mask & single.searchContext) != 0) { + if ((mask & single.searchContext) != 0 && ((GlobalSearchScope)single.searchScope).contains(file)) { local.putValue(file, single); } } From fda891ea9a07ebad1a099078bdb4fe6902a06eb3 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 8 Jun 2010 17:31:14 +0400 Subject: [PATCH 30/81] eager PSI calculation after the tree has been created by parser --- .../com/intellij/psi/impl/source/tree/LazyParseableElement.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index 85e43cb63632..ebe2c993b5ef 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -169,14 +169,12 @@ public class LazyParseableElement extends CompositeElement { rawAddChildren((TreeElement)parsedNode); //ensure PSI is created all at once, to reduce contention of PsiLock in CompositeElement.getPsi() - /* synchronized (PsiLock.LOCK) { while (parsedNode != null) { ((TreeElement)parsedNode).acceptTree(CREATE_PSI); parsedNode = parsedNode.getTreeNext(); } } - */ } } From 82e751896c27de8760bb966d2d325361081b6aaa Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 9 Jun 2010 20:42:50 +0400 Subject: [PATCH 31/81] a bit nicer API for optimized find usages --- .../findUsages/JavaFindUsagesHandler.java | 2 +- .../search/MethodTextOccurenceProcessor.java | 75 +++++----- .../psi/impl/search/MethodUsagesSearcher.java | 39 +++--- .../SimpleAccessorReferenceSearcher.java | 21 +-- .../intellij/psi/search/PsiSearchHelper.java | 3 +- .../intellij/psi/search/PsiSearchRequest.java | 82 +++-------- .../psi/search/RequestResultProcessor.java | 24 ++++ .../psi/search/SearchRequestCollector.java | 51 +++++++ .../SingleTargetRequestResultProcessor.java | 25 ++++ .../find/findUsages/FindUsagesHandler.java | 15 +- .../find/findUsages/FindUsagesManager.java | 12 +- .../find/findUsages/FindUsagesOptions.java | 4 +- .../impl/search/CachesBasedRefSearcher.java | 54 +++----- .../psi/impl/search/LowLevelSearchUtil.java | 9 +- .../psi/impl/search/PsiSearchHelperImpl.java | 131 +++++++++--------- .../intellij/psi/search/SearchRequestor.java | 10 +- .../AccessorReferencesSearcher.java | 38 ++--- .../MethodLateBoundReferencesSearcher.java | 23 ++- 18 files changed, 303 insertions(+), 315 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java create mode 100644 platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java create mode 100644 platform/lang-api/src/com/intellij/psi/search/SingleTargetRequestResultProcessor.java diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index 449ebccff88e..79e37f578cce 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -601,7 +601,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ }; if (options.fastTrack != null) { - SearchRequestor.contributeTargets(element, options, options.fastTrack, consumer); + SearchRequestor.collectRequests(element, options, options.fastTrack); return; } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodTextOccurenceProcessor.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodTextOccurenceProcessor.java index 651ddf81cf6c..e9dc0a5b75e3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodTextOccurenceProcessor.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodTextOccurenceProcessor.java @@ -16,7 +16,7 @@ package com.intellij.psi.impl.search; import com.intellij.psi.*; -import com.intellij.psi.search.TextOccurenceProcessor; +import com.intellij.psi.search.RequestResultProcessor; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -26,62 +26,53 @@ import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class MethodTextOccurenceProcessor implements TextOccurenceProcessor { +public class MethodTextOccurenceProcessor extends RequestResultProcessor { private final PsiMethod[] myMethods; - private final Processor myConsumer; private final PsiClass myContainingClass; private final boolean myStrictSignatureSearch; - public MethodTextOccurenceProcessor(final Processor consumer, - @NotNull final PsiClass aClass, - final boolean strictSignatureSearch, - final PsiMethod... methods) { + public MethodTextOccurenceProcessor(@NotNull final PsiClass aClass, final boolean strictSignatureSearch, final PsiMethod... methods) { myMethods = methods; - myConsumer = consumer; myContainingClass = aClass; myStrictSignatureSearch = strictSignatureSearch; } - public boolean execute(PsiElement element, int offsetInElement) { - final PsiReference[] refs = element.getReferences(); - for (PsiReference ref : refs) { - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - for (PsiMethod method : myMethods) { - if (!method.isValid()) { - continue; - } + @Override + protected boolean processReference(Processor consumer, PsiReference ref) { + for (PsiMethod method : myMethods) { + if (!method.isValid()) { + continue; + } - if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(method)) { - return true; - } - if (ref.isReferenceTo(method)) { - return myConsumer.process(ref); - } - PsiElement refElement = ref.resolve(); + if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(method)) { + return true; + } + if (ref.isReferenceTo(method)) { + return consumer.process(ref); + } + PsiElement refElement = ref.resolve(); - if (refElement instanceof PsiMethod) { - PsiMethod refMethod = (PsiMethod)refElement; - PsiClass refMethodClass = refMethod.getContainingClass(); - if (refMethodClass == null) continue; + if (refElement instanceof PsiMethod) { + PsiMethod refMethod = (PsiMethod)refElement; + PsiClass refMethodClass = refMethod.getContainingClass(); + if (refMethodClass == null) continue; - if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) { - PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY); - if (substitutor != null) { - MethodSignature superSignature = method.getSignature(substitutor); - MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY); + if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) { + PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY); + if (substitutor != null) { + MethodSignature superSignature = method.getSignature(substitutor); + MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY); - if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) { - if (!myConsumer.process(ref)) return false; - } - } + if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) { + if (!consumer.process(ref)) return false; } + } + } - if (!myStrictSignatureSearch) { - PsiManager manager = method.getManager(); - if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) { - if (!myConsumer.process(ref)) return false; - } - } + if (!myStrictSignatureSearch) { + PsiManager manager = method.getManager(); + if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) { + if (!consumer.process(ref)) return false; } } } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index e06d65981575..410d2353deb1 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -5,7 +5,6 @@ package com.intellij.psi.impl.search; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.search.*; import com.intellij.psi.search.searches.MethodReferencesSearch; @@ -24,34 +23,31 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut return true; } - final PsiSearchRequest.ComplexRequest collector = PsiSearchRequest.composite(); final PsiMethod method = p.getMethod(); + final SearchRequestCollector collector = new SearchRequestCollector(method); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); options.isUsages = true; - contributeSearchTargets(method, options, collector, consumer, p.isStrictSignatureSearch(), true); - SearchRequestor.contributeTargets(method, options, collector, consumer); + contributeSearchTargets(method, options, collector, p.isStrictSignatureSearch()); + SearchRequestor.collectRequests(method, options, collector); } }); - - - return method.getManager().getSearchHelper().processRequest(collector); + return method.getManager().getSearchHelper().processRequests(collector, consumer); } @Override - public void contributeSearchTargets(@NotNull PsiElement target, + public void contributeRequests(@NotNull PsiElement target, @NotNull final FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor processor) { + @NotNull SearchRequestCollector collector) { if (target instanceof PsiMethod) { final boolean strictSignatureSearch = !options.isIncludeOverloadUsages; final PsiMethod method = (PsiMethod)target; - contributeSearchTargets(method, options, collector, processor, strictSignatureSearch, false); - collector.addRequest(PsiSearchRequest.custom(new Computable() { - public Boolean compute() { + contributeSearchTargets(method, options, collector, strictSignatureSearch); + collector.searchCustom(new Processor>() { + public boolean process(Processor processor) { ourProcessing.set(true); try { return MethodReferencesSearch.search(method, options.searchScope, strictSignatureSearch).forEach(processor); @@ -60,14 +56,14 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut ourProcessing.set(null); } } - })); + }); } } private static void contributeSearchTargets(@NotNull final PsiMethod method, - @NotNull FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor consumer, final boolean strictSignatureSearch, final boolean fromSearcher) { + @NotNull FindUsagesOptions options, + @NotNull SearchRequestCollector collector, + final boolean strictSignatureSearch) { final SearchScope searchScope = options.searchScope; final PsiManager psiManager = PsiManager.getInstance(method.getProject()); @@ -76,12 +72,12 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut if (aClass == null) return; if (method.isConstructor()) { - collector.addRequest(PsiSearchRequest.custom(new Computable() { - public Boolean compute() { + collector.searchCustom(new Processor>() { + public boolean process(Processor consumer) { return new ConstructorReferencesSearchHelper(psiManager). processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch); } - })); + }); } boolean needStrictSignatureSearch = method.isValid() && strictSignatureSearch && (aClass instanceof PsiAnonymousClass @@ -106,8 +102,7 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope); short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES; - collector.addRequest(PsiSearchRequest.elementsWithWord(restrictedByAccess, textToSearch, searchContext, true, - new MethodTextOccurenceProcessor(consumer, aClass, strictSignatureSearch, methods))); + collector.searchWord(textToSearch, restrictedByAccess, searchContext, true, new MethodTextOccurenceProcessor(aClass, strictSignatureSearch, methods)); } } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java index 905f1565f512..c19234554b98 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java @@ -21,11 +21,8 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; -import com.intellij.psi.ReferenceRange; import com.intellij.psi.search.*; import com.intellij.psi.util.PropertyUtil; -import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; /** @@ -34,10 +31,9 @@ import org.jetbrains.annotations.NotNull; public class SimpleAccessorReferenceSearcher extends SearchRequestor { @Override - public void contributeSearchTargets(@NotNull final PsiElement refElement, + public void contributeRequests(@NotNull final PsiElement refElement, @NotNull FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor consumer) { + @NotNull SearchRequestCollector collector) { if (!(refElement instanceof PsiMethod)) return; final PsiMethod method = (PsiMethod)refElement; @@ -53,18 +49,7 @@ public class SimpleAccessorReferenceSearcher extends SearchRequestor { } assert propertyName != null; final SearchScope propScope = options.searchScope.intersectWith(method.getUseScope()).intersectWith(additional); - collector.addRequest(PsiSearchRequest.elementsWithWord(propScope, propertyName, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { - for (PsiReference ref : element.getReferences()) { - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - if (ref.isReferenceTo(refElement)) { - return consumer.process(ref); - } - } - } - return true; - } - })); + collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true); } } diff --git a/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java b/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java index 4a14051e0eca..f8eb7efcf7e9 100644 --- a/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java +++ b/platform/lang-api/src/com/intellij/psi/search/PsiSearchHelper.java @@ -18,6 +18,7 @@ package com.intellij.psi.search; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReference; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -175,7 +176,7 @@ public interface PsiSearchHelper { */ void processAllFilesWithWordInLiterals(@NotNull String word, @NotNull GlobalSearchScope scope, @NotNull Processor processor); - boolean processRequest(@NotNull PsiSearchRequest request); + boolean processRequests(@NotNull SearchRequestCollector request, Processor processor); boolean processElementsWithWord(@NotNull TextOccurenceProcessor processor, @NotNull SearchScope searchScope, diff --git a/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java index 93d6c61933b7..5e16c40b8c91 100644 --- a/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java +++ b/platform/lang-api/src/com/intellij/psi/search/PsiSearchRequest.java @@ -1,78 +1,28 @@ package com.intellij.psi.search; -import com.intellij.openapi.util.Computable; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; - /** * @author peter */ public class PsiSearchRequest { + public final SearchScope searchScope; + public final String word; + public final short searchContext; + public final boolean caseSensitive; + public final RequestResultProcessor processor; - public static SingleRequest elementsWithWord(@NotNull SearchScope searchScope, - @NotNull String word, - short searchContext, - boolean caseSensitive, @NotNull TextOccurenceProcessor processor) { - return new SingleRequest(searchScope, word, searchContext, caseSensitive, processor); + public PsiSearchRequest(@NotNull SearchScope searchScope, + @NotNull String word, + short searchContext, + boolean caseSensitive, + @NotNull RequestResultProcessor processor) { + + this.searchScope = searchScope; + this.word = word; + this.searchContext = searchContext; + this.caseSensitive = caseSensitive; + this.processor = processor; } - public static ComplexRequest composite() { - return new ComplexRequest(); - } - - public static CustomRequest custom(Computable searchAction) { - return new CustomRequest(searchAction); - } - - public static class SingleRequest extends PsiSearchRequest { - public final SearchScope searchScope; - public final String word; - public final short searchContext; - public final boolean caseSensitive; - public final TextOccurenceProcessor processor; - - private SingleRequest(@NotNull SearchScope searchScope, - @NotNull String word, - short searchContext, - boolean caseSensitive, - @NotNull TextOccurenceProcessor processor) { - - this.searchScope = searchScope; - this.word = word; - this.searchContext = searchContext; - this.caseSensitive = caseSensitive; - this.processor = processor; - } - } - - public static class ComplexRequest extends PsiSearchRequest { - private final List myComponents = new ArrayList(); - - private ComplexRequest() { - } - - public void addRequest(PsiSearchRequest request) { - if (request instanceof ComplexRequest) { - myComponents.addAll(((ComplexRequest)request).getConstituents()); - } else { - myComponents.add(request); - } - } - - public List getConstituents() { - return myComponents; - } - } - - public static class CustomRequest extends PsiSearchRequest { - public final Computable searchAction; - - private CustomRequest(Computable searchAction) { - this.searchAction = searchAction; - } - } - - } diff --git a/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java b/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java new file mode 100644 index 000000000000..28cb9580a8f7 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java @@ -0,0 +1,24 @@ +package com.intellij.psi.search; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.ReferenceRange; +import com.intellij.util.Processor; + +/** + * @author peter + */ +public abstract class RequestResultProcessor { + + public boolean execute(PsiElement element, int offsetInElement, final Processor consumer) { + for (PsiReference ref : element.getReferences()) { + if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { + return processReference(consumer, ref); + } + } + return true; + } + + protected abstract boolean processReference(Processor consumer, PsiReference ref); + +} diff --git a/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java b/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java new file mode 100644 index 000000000000..826e040ad694 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java @@ -0,0 +1,51 @@ +package com.intellij.psi.search; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** +* @author peter +*/ +public class SearchRequestCollector { + private final List myRequests = new ArrayList(); + private final List>> myCustomSearchActions = new ArrayList>>(); + private final PsiElement myTarget; + + public SearchRequestCollector(PsiElement target) { + myTarget = target; + } + + public PsiElement getTarget() { + return myTarget; + } + + public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, boolean caseSensitive) { + final short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS; + searchWord(word, searchScope, searchContext, caseSensitive); + } + + public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive) { + searchWord(word, searchScope, searchContext, caseSensitive, new SingleTargetRequestResultProcessor(myTarget)); + } + + public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive, @NotNull RequestResultProcessor processor) { + myRequests.add(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, processor)); + } + + public void searchCustom(Processor> searchAction) { + myCustomSearchActions.add(searchAction); + } + + public List getSearchRequests() { + return myRequests; + } + + public List>> getCustomSearchActions() { + return myCustomSearchActions; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/search/SingleTargetRequestResultProcessor.java b/platform/lang-api/src/com/intellij/psi/search/SingleTargetRequestResultProcessor.java new file mode 100644 index 000000000000..2f356959b21f --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/SingleTargetRequestResultProcessor.java @@ -0,0 +1,25 @@ +package com.intellij.psi.search; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class SingleTargetRequestResultProcessor extends RequestResultProcessor { + private final PsiElement myTarget; + + public SingleTargetRequestResultProcessor(@NotNull PsiElement target) { + myTarget = target; + } + + protected boolean processReference(Processor consumer, PsiReference ref) { + if (ref.isReferenceTo(myTarget)) { + return consumer.process(ref); + } + return true; + } + +} diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java index 8cff0399098a..6e0d6772fdcf 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java @@ -102,17 +102,16 @@ public abstract class FindUsagesHandler { final boolean searchText = options.isSearchForTextOccurences && scope instanceof GlobalSearchScope; if (options.fastTrack != null) { - SearchRequestor.contributeTargets(element, options, options.fastTrack, refProcessor); + SearchRequestor.collectRequests(element, options, options.fastTrack); - // todo special kind of request for that - options.fastTrack.addRequest(PsiSearchRequest.custom(new Computable() { - public Boolean compute() { - if (searchText) { + if (searchText) { + options.fastTrack.searchCustom(new Processor>() { + public boolean process(Processor consumer) { processUsagesInText(element, processor, (GlobalSearchScope)scope); + return true; } - return true; - } - })); + }); + } return; } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index e088b31d8169..12d4c9e1c914 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadActionProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -44,7 +45,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.StatusBar; import com.intellij.psi.*; import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.PsiSearchRequest; +import com.intellij.psi.search.SearchRequestCollector; import com.intellij.psi.search.SearchScope; import com.intellij.ui.LightweightHint; import com.intellij.ui.content.Content; @@ -352,7 +353,7 @@ public class FindUsagesManager implements JDOMExternalizable { } }); - options.fastTrack = PsiSearchRequest.composite(); + options.fastTrack = new SearchRequestCollector(scopeFile); for (final PsiElement element : elements) { ApplicationManager.getApplication().runReadAction(new Runnable() { @@ -363,7 +364,12 @@ public class FindUsagesManager implements JDOMExternalizable { handler.processElementUsages(element, usageInfoProcessor, options); } - PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequest(options.fastTrack); + PsiManager.getInstance(handler.getProject()).getSearchHelper().processRequests(options.fastTrack, new ReadActionProcessor() { + public boolean processInReadAction(final PsiReference ref) { + TextRange rangeInElement = ref.getRangeInElement(); + return usageInfoProcessor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); + } + }); } }; } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java index e0b4cdcd5c92..376eaf6eb95f 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java @@ -23,7 +23,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.search.ProjectScope; -import com.intellij.psi.search.PsiSearchRequest; +import com.intellij.psi.search.SearchRequestCollector; import com.intellij.psi.search.SearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,7 +56,7 @@ public class FindUsagesOptions extends UserDataHolderBase implements Cloneable { public boolean isWriteAccess = false; public boolean isIncludeOverloadUsages = false; public boolean isThrowUsages = false; - public PsiSearchRequest.ComplexRequest fastTrack = null; + public SearchRequestCollector fastTrack = null; public FindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) { String defaultScopeName = FindSettings.getInstance().getDefaultScopeName(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index 9e9334b7a34b..82468490213c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -5,13 +5,17 @@ package com.intellij.psi.impl.search; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.PsiReference; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; -import com.intellij.psi.search.*; +import com.intellij.psi.search.SearchRequestCollector; +import com.intellij.psi.search.SearchRequestor; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; @@ -29,29 +33,28 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec } final PsiElement refElement = p.getElementToSearch(); - final PsiSearchRequest.ComplexRequest collector = PsiSearchRequest.composite(); + final SearchRequestCollector collector = new SearchRequestCollector(refElement); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); options.isUsages = true; - contributeSearchTargets(refElement, options, collector, consumer, p.isIgnoreAccessScope(), options.searchScope); - SearchRequestor.contributeTargets(refElement, options, collector, consumer); + contributeSearchTargets(refElement, options, collector, p.isIgnoreAccessScope(), options.searchScope); + SearchRequestor.collectRequests(refElement, options, collector); } }); - return refElement.getManager().getSearchHelper().processRequest(collector); + return refElement.getManager().getSearchHelper().processRequests(collector, consumer); } @Override - public void contributeSearchTargets(@NotNull final PsiElement refElement, + public void contributeRequests(@NotNull final PsiElement refElement, @NotNull FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor consumer) { + @NotNull SearchRequestCollector collector) { final boolean ignoreAccessScope = false; final SearchScope scope = options.searchScope; - contributeSearchTargets(refElement, options, collector, consumer, ignoreAccessScope, scope); - collector.addRequest(PsiSearchRequest.custom(new Computable() { - public Boolean compute() { + contributeSearchTargets(refElement, options, collector, ignoreAccessScope, scope); + collector.searchCustom(new Processor>() { + public boolean process(Processor consumer) { ourProcessing.set(true); try { return ReferencesSearch.search(refElement, scope, ignoreAccessScope).forEach(consumer); @@ -60,13 +63,12 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec ourProcessing.set(null); } } - })); + }); } private static void contributeSearchTargets(@NotNull final PsiElement refElement, @NotNull FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor consumer, + @NotNull SearchRequestCollector collector, final boolean ignoreAccessScope, final SearchScope scope) { if (!options.isUsages) { @@ -94,26 +96,8 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec } if (StringUtil.isNotEmpty(text)) { final SearchScope searchScope = ignoreAccessScope ? scope : refElement.getUseScope().intersectWith(scope); - final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi(); - - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { - if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true; - final PsiReference[] refs = element.getReferences(); - for (PsiReference ref : refs) { - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - if (ref.isReferenceTo(refElement)) { - return consumer.process(ref); - } - } - } - return true; - } - }; - assert text != null; - final short mask = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS; - collector.addRequest(PsiSearchRequest.elementsWithWord(searchScope, text, mask, refElement.getLanguage().isCaseSensitive(), processor)); + collector.searchWord(text, searchScope, refElement.getLanguage().isCaseSensitive()); } } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java index 9b89e95838b6..eed20ecf37ce 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java @@ -108,9 +108,14 @@ public class LowLevelSearchUtil { if (contains) { if (!ignoreInjectedPsi) { Boolean result = processInjectedFile(run, processor, searcher, progress); - if (result != null) return result.booleanValue(); + if (result != null) { + return result.booleanValue(); + } + } + if (!processor.execute(run, start)) { + processor.execute(run, start); + return false; } - if (!processor.execute(run, start)) return false; } if (useTree) { leafNode = leafNode.getTreeParent(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 69c1c184361e..ee9d8b5d3613 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -479,43 +479,34 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { myManager.getCacheManager().processFilesWithWord(processor, word, UsageSearchContext.IN_STRINGS, scope, true); } - public boolean processRequest(@NotNull PsiSearchRequest request) { - if (request instanceof PsiSearchRequest.SingleRequest) { - return processSingleRequest((PsiSearchRequest.SingleRequest)request); - } - else if (request instanceof PsiSearchRequest.CustomRequest) { - return ((PsiSearchRequest.CustomRequest)request).searchAction.compute(); - } - else if (request instanceof PsiSearchRequest.ComplexRequest) { - final MultiMap, PsiSearchRequest.SingleRequest> singles = new MultiMap, PsiSearchRequest.SingleRequest>(); - final List customs = new ArrayList(); - distributePrimitives((PsiSearchRequest.ComplexRequest)request, singles, customs); - - if (processRequestsOptimized(singles)) { - for (PsiSearchRequest.CustomRequest custom : customs) { - if (!custom.searchAction.compute()) { - return false; - } - } - return true; - } + public boolean processRequests(@NotNull SearchRequestCollector request, Processor processor) { + final MultiMap, PsiSearchRequest> singles = new MultiMap, PsiSearchRequest>(); + final List>> customs = new ArrayList>>(); + distributePrimitives(request, singles, customs); + if (!processRequestsOptimized(singles, processor)) { return false; - } else { - LOG.error("Unknown request: " + request); - return true; } + + for (Processor> custom : customs) { + if (!custom.process(processor)) { + return false; + } + } + + return true; + } - private boolean processRequestsOptimized(MultiMap, PsiSearchRequest.SingleRequest> singles) { + private boolean processRequestsOptimized(MultiMap, PsiSearchRequest> singles, final Processor consumer) { if (singles.isEmpty()) { return true; } if (singles.size() == 1) { - final Collection requests = singles.get(singles.keySet().iterator().next()); + final Collection requests = singles.get(singles.keySet().iterator().next()); if (requests.size() == 1) { - return processSingleRequest(requests.iterator().next()); + return processSingleRequest(requests.iterator().next(), consumer); } } @@ -525,11 +516,11 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { progress.setText(PsiBundle.message("psi.scanning.files.progress")); } - final MultiMap candidateFiles = collectFiles(singles); + final MultiMap candidateFiles = collectFiles(singles); - final Map searchers = new HashMap(); + final Map searchers = new HashMap(); final Set allWords = new TreeSet(); - for (PsiSearchRequest.SingleRequest singleRequest : candidateFiles.values()) { + for (PsiSearchRequest singleRequest : candidateFiles.values()) { searchers.put(singleRequest, new StringSearcher(singleRequest.word, singleRequest.caseSensitive, true)); allWords.add(singleRequest.word); } @@ -541,9 +532,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return processPsiFileRoots(progress, new ArrayList(candidateFiles.keySet()), new Processor() { public boolean process(PsiElement psiRoot) { final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile(); - for (PsiSearchRequest.SingleRequest singleRequest : candidateFiles.get(vfile)) { + for (final PsiSearchRequest singleRequest : candidateFiles.get(vfile)) { StringSearcher searcher = searchers.get(singleRequest); - if (!LowLevelSearchUtil.processElementsContainingWordInElement(singleRequest.processor, psiRoot, searcher, false, progress)) { + if (!LowLevelSearchUtil.processElementsContainingWordInElement(adaptProcessor(singleRequest, consumer), psiRoot, searcher, false, progress)) { return false; } } @@ -552,18 +543,31 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { }); } - private MultiMap collectFiles(MultiMap, PsiSearchRequest.SingleRequest> singles) { + private static TextOccurenceProcessor adaptProcessor(final PsiSearchRequest singleRequest, + final Processor consumer) { + final SearchScope searchScope = singleRequest.searchScope; + final boolean ignoreInjectedPsi = searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).isIgnoreInjectedPsi(); + return new TextOccurenceProcessor() { + public boolean execute(PsiElement element, int offsetInElement) { + if (ignoreInjectedPsi && element instanceof PsiLanguageInjectionHost) return true; + + return singleRequest.processor.execute(element, offsetInElement, consumer); + } + }; + } + + private MultiMap collectFiles(MultiMap, PsiSearchRequest> singles) { final ProjectFileIndex index = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex(); - final MultiMap result = new MultiMap(); + final MultiMap result = new MultiMap(); for (Set key : singles.keySet()) { - final Collection data = singles.get(key); + final Collection data = singles.get(key); GlobalSearchScope commonScope = uniteScopes(data); - MultiMap intersection = null; + MultiMap intersection = null; boolean first = true; for (IdIndexEntry entry : key) { - final MultiMap local = findFilesWithIndexEntry(entry, index, data, commonScope); + final MultiMap local = findFilesWithIndexEntry(entry, index, data, commonScope); if (first) { intersection = local; first = false; @@ -580,9 +584,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return result; } - private static GlobalSearchScope uniteScopes(Collection requests) { + private static GlobalSearchScope uniteScopes(Collection requests) { GlobalSearchScope commonScope = null; - for (PsiSearchRequest.SingleRequest r : requests) { + for (PsiSearchRequest r : requests) { final GlobalSearchScope scope = (GlobalSearchScope)r.searchScope; commonScope = commonScope == null ? scope : commonScope.uniteWith(scope); } @@ -590,18 +594,18 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return commonScope; } - private static MultiMap findFilesWithIndexEntry(IdIndexEntry entry, + private static MultiMap findFilesWithIndexEntry(IdIndexEntry entry, final ProjectFileIndex index, - final Collection data, + final Collection data, GlobalSearchScope commonScope) { - final MultiMap local = new MultiMap(); + final MultiMap local = new MultiMap(); FileBasedIndex.getInstance().processValues(IdIndex.NAME, entry, null, new FileBasedIndex.ValueProcessor() { public boolean process(VirtualFile file, Integer value) { if (!IndexCacheManagerImpl.shouldBeFound(file, index)) { return true; } int mask = value.intValue(); - for (PsiSearchRequest.SingleRequest single : data) { + for (PsiSearchRequest single : data) { if ((mask & single.searchContext) != 0 && ((GlobalSearchScope)single.searchScope).contains(file)) { local.putValue(file, single); } @@ -612,36 +616,31 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return local; } - private void distributePrimitives(PsiSearchRequest.ComplexRequest request, - MultiMap, PsiSearchRequest.SingleRequest> singles, - List customs) { - for (PsiSearchRequest primitive : request.getConstituents()) { - if (primitive instanceof PsiSearchRequest.CustomRequest) { - customs.add((PsiSearchRequest.CustomRequest)primitive); - } else { - final PsiSearchRequest.SingleRequest single = (PsiSearchRequest.SingleRequest) primitive; - final SearchScope scope = single.searchScope; - if (scope instanceof LocalSearchScope) { - customs.add(PsiSearchRequest.custom(new Computable() { - public Boolean compute() { - return processSingleRequest(single); - } - })); - } else { - final List words = StringUtil.getWordsIn(single.word); - final Set key = new HashSet(words.size()); - for (String word : words) { - key.add(new IdIndexEntry(word, single.caseSensitive)); + private void distributePrimitives(SearchRequestCollector request, + MultiMap, PsiSearchRequest> singles, + List>> customs) { + for (final PsiSearchRequest primitive : request.getSearchRequests()) { + final SearchScope scope = primitive.searchScope; + if (scope instanceof LocalSearchScope) { + customs.add(new Processor>() { + public boolean process(Processor processor) { + return processSingleRequest(primitive, processor); } - singles.putValue(key, single); + }); + } else { + final List words = StringUtil.getWordsIn(primitive.word); + final Set key = new HashSet(words.size()); + for (String word : words) { + key.add(new IdIndexEntry(word, primitive.caseSensitive)); } - + singles.putValue(key, primitive); } } + customs.addAll(request.getCustomSearchActions()); } - private boolean processSingleRequest(PsiSearchRequest.SingleRequest single) { - return processElementsWithWord(single.processor, single.searchScope, single.word, single.searchContext, single.caseSensitive); + private boolean processSingleRequest(PsiSearchRequest single, Processor consumer) { + return processElementsWithWord(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext, single.caseSensitive); } public SearchCostResult isCheapEnoughToSearch(@NotNull String name, diff --git a/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java b/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java index b75b25ffbabe..495cf90aa670 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java +++ b/platform/lang-impl/src/com/intellij/psi/search/SearchRequestor.java @@ -4,8 +4,6 @@ import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; /** @@ -14,18 +12,16 @@ import org.jetbrains.annotations.NotNull; public abstract class SearchRequestor { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.searchRequestor"); - public static void contributeTargets(final PsiElement element, - final FindUsagesOptions options, - final PsiSearchRequest.ComplexRequest collector, final Processor processor) { + public static void collectRequests(final PsiElement element, final FindUsagesOptions options, final SearchRequestCollector collector) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { for (SearchRequestor searcher : EP_NAME.getExtensions()) { - searcher.contributeSearchTargets(element, options, collector, processor); + searcher.contributeRequests(element, options, collector); } } }); } - public abstract void contributeSearchTargets(@NotNull PsiElement target, @NotNull FindUsagesOptions options, @NotNull PsiSearchRequest.ComplexRequest collector, Processor processor); + public abstract void contributeRequests(@NotNull PsiElement target, @NotNull FindUsagesOptions options, @NotNull SearchRequestCollector collector); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java index 69b35fef6e58..64c19d9732f7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java @@ -31,10 +31,9 @@ import org.jetbrains.annotations.Nullable; import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; -import com.intellij.psi.ReferenceRange; -import com.intellij.psi.search.*; -import com.intellij.util.Processor; +import com.intellij.psi.search.SearchRequestCollector; +import com.intellij.psi.search.SearchRequestor; +import com.intellij.psi.search.UsageSearchContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -44,36 +43,17 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; */ public class AccessorReferencesSearcher extends SearchRequestor { @Override - public void contributeSearchTargets(@NotNull PsiElement target, + public void contributeRequests(@NotNull PsiElement target, @NotNull final FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - final Processor consumer) { + @NotNull SearchRequestCollector collector) { if (!(target instanceof PsiMethod)) { return; } - final PsiMethod method = (PsiMethod)target; - - final String propertyName = GroovyPropertyUtils.getPropertyName(method); - if (propertyName == null) return; - - SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope); - - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { - final PsiReference[] refs = element.getReferences(); - for (PsiReference ref : refs) { - if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - if (ref.isReferenceTo(method)) { - return consumer.process(ref); - } - } - } - return true; - } - }; - - collector.addRequest(PsiSearchRequest.elementsWithWord(searchScope, propertyName, UsageSearchContext.IN_CODE, true, processor)); + final String propertyName = GroovyPropertyUtils.getPropertyName((PsiMethod)target); + if (propertyName != null) { + collector.searchWord(propertyName, PsiUtil.restrictScopeToGroovyFiles(options.searchScope), UsageSearchContext.IN_CODE, true); + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java index 2ff03aff2fe4..d594c60381d8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java @@ -37,10 +37,9 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; */ public class MethodLateBoundReferencesSearcher extends SearchRequestor { @Override - public void contributeSearchTargets(@NotNull PsiElement target, + public void contributeRequests(@NotNull PsiElement target, @NotNull FindUsagesOptions options, - @NotNull PsiSearchRequest.ComplexRequest collector, - Processor consumer) { + @NotNull SearchRequestCollector collector) { if (!(target instanceof PsiMethod)) { return; } @@ -48,11 +47,11 @@ public class MethodLateBoundReferencesSearcher extends SearchRequestor { final PsiMethod method = (PsiMethod)target; SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope.intersectWith(getUseScope(method))); - orderSearching(searchScope, method.getName(), consumer, collector); + orderSearching(searchScope, method.getName(), collector); final String propName = PropertyUtil.getPropertyName(method); if (propName != null) { - orderSearching(searchScope, propName, consumer, collector); + orderSearching(searchScope, propName, collector); } } @@ -71,11 +70,11 @@ public class MethodLateBoundReferencesSearcher extends SearchRequestor { private static void orderSearching(SearchScope searchScope, - final String name, - final Processor consumer, - @NotNull PsiSearchRequest.ComplexRequest collector) { - final TextOccurenceProcessor processor = new TextOccurenceProcessor() { - public boolean execute(PsiElement element, int offsetInElement) { + final String name, + @NotNull SearchRequestCollector collector) { + collector.searchWord(name, searchScope, UsageSearchContext.IN_CODE, true, new SingleTargetRequestResultProcessor(collector.getTarget()) { + @Override + public boolean execute(PsiElement element, int offsetInElement, Processor consumer) { if (!(element instanceof GrReferenceExpression)) { return true; } @@ -87,9 +86,7 @@ public class MethodLateBoundReferencesSearcher extends SearchRequestor { return consumer.process((PsiReference)element); } - }; - - collector.addRequest(PsiSearchRequest.elementsWithWord(searchScope, name, UsageSearchContext.IN_CODE, true, processor)); + }); } } \ No newline at end of file From fbcd6af2d7600ce4045c95e80a20518338e61e3c Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 11 Jun 2010 21:55:17 +0400 Subject: [PATCH 32/81] fix NPE --- .../psi/impl/search/MethodUsagesSearcher.java | 2 +- .../search/SimpleAccessorReferenceSearcher.java | 2 +- .../psi/search/SearchRequestCollector.java | 17 ++++------------- .../find/findUsages/FindUsagesManager.java | 2 +- .../psi/impl/search/CachesBasedRefSearcher.java | 4 ++-- .../findUsages/AccessorReferencesSearcher.java | 2 +- .../MethodLateBoundReferencesSearcher.java | 8 ++++---- 7 files changed, 14 insertions(+), 23 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index 410d2353deb1..d972dc8aaf2c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -24,7 +24,7 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut } final PsiMethod method = p.getMethod(); - final SearchRequestCollector collector = new SearchRequestCollector(method); + final SearchRequestCollector collector = new SearchRequestCollector(); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { diff --git a/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java index c19234554b98..be7594cdc0d1 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java @@ -49,7 +49,7 @@ public class SimpleAccessorReferenceSearcher extends SearchRequestor { } assert propertyName != null; final SearchScope propScope = options.searchScope.intersectWith(method.getUseScope()).intersectWith(additional); - collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true); + collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, refElement); } } diff --git a/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java b/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java index 826e040ad694..8fb10bc42ab8 100644 --- a/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java +++ b/platform/lang-api/src/com/intellij/psi/search/SearchRequestCollector.java @@ -14,23 +14,14 @@ import java.util.List; public class SearchRequestCollector { private final List myRequests = new ArrayList(); private final List>> myCustomSearchActions = new ArrayList>>(); - private final PsiElement myTarget; - public SearchRequestCollector(PsiElement target) { - myTarget = target; - } - - public PsiElement getTarget() { - return myTarget; - } - - public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, boolean caseSensitive) { + public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, boolean caseSensitive, @NotNull PsiElement searchTarget) { final short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_FOREIGN_LANGUAGES | UsageSearchContext.IN_COMMENTS; - searchWord(word, searchScope, searchContext, caseSensitive); + searchWord(word, searchScope, searchContext, caseSensitive, searchTarget); } - public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive) { - searchWord(word, searchScope, searchContext, caseSensitive, new SingleTargetRequestResultProcessor(myTarget)); + public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive, @NotNull PsiElement searchTarget) { + searchWord(word, searchScope, searchContext, caseSensitive, new SingleTargetRequestResultProcessor(searchTarget)); } public void searchWord(@NotNull String word, @NotNull SearchScope searchScope, short searchContext, boolean caseSensitive, @NotNull RequestResultProcessor processor) { diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 12d4c9e1c914..09fce5ad0ff3 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -353,7 +353,7 @@ public class FindUsagesManager implements JDOMExternalizable { } }); - options.fastTrack = new SearchRequestCollector(scopeFile); + options.fastTrack = new SearchRequestCollector(); for (final PsiElement element : elements) { ApplicationManager.getApplication().runReadAction(new Runnable() { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index 82468490213c..0c488928610b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -33,7 +33,7 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec } final PsiElement refElement = p.getElementToSearch(); - final SearchRequestCollector collector = new SearchRequestCollector(refElement); + final SearchRequestCollector collector = new SearchRequestCollector(); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { @@ -97,7 +97,7 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec if (StringUtil.isNotEmpty(text)) { final SearchScope searchScope = ignoreAccessScope ? scope : refElement.getUseScope().intersectWith(scope); assert text != null; - collector.searchWord(text, searchScope, refElement.getLanguage().isCaseSensitive()); + collector.searchWord(text, searchScope, refElement.getLanguage().isCaseSensitive(), refElement); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java index 64c19d9732f7..f0a6f94d0583 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorReferencesSearcher.java @@ -52,7 +52,7 @@ public class AccessorReferencesSearcher extends SearchRequestor { final String propertyName = GroovyPropertyUtils.getPropertyName((PsiMethod)target); if (propertyName != null) { - collector.searchWord(propertyName, PsiUtil.restrictScopeToGroovyFiles(options.searchScope), UsageSearchContext.IN_CODE, true); + collector.searchWord(propertyName, PsiUtil.restrictScopeToGroovyFiles(options.searchScope), UsageSearchContext.IN_CODE, true, target); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java index d594c60381d8..745a08007cd4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java @@ -47,11 +47,11 @@ public class MethodLateBoundReferencesSearcher extends SearchRequestor { final PsiMethod method = (PsiMethod)target; SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(options.searchScope.intersectWith(getUseScope(method))); - orderSearching(searchScope, method.getName(), collector); + orderSearching(searchScope, method.getName(), collector, method); final String propName = PropertyUtil.getPropertyName(method); if (propName != null) { - orderSearching(searchScope, propName, collector); + orderSearching(searchScope, propName, collector, method); } } @@ -71,8 +71,8 @@ public class MethodLateBoundReferencesSearcher extends SearchRequestor { private static void orderSearching(SearchScope searchScope, final String name, - @NotNull SearchRequestCollector collector) { - collector.searchWord(name, searchScope, UsageSearchContext.IN_CODE, true, new SingleTargetRequestResultProcessor(collector.getTarget()) { + @NotNull SearchRequestCollector collector, PsiMethod method) { + collector.searchWord(name, searchScope, UsageSearchContext.IN_CODE, true, new SingleTargetRequestResultProcessor(method) { @Override public boolean execute(PsiElement element, int offsetInElement, Processor consumer) { if (!(element instanceof GrReferenceExpression)) { From d2f7c4edd46d5880e8bc3fddac0c0b0fa3340fdf Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 11 Jun 2010 21:55:47 +0400 Subject: [PATCH 33/81] eager PSI calculation --- .../impl/source/tree/CompositeElement.java | 29 +++++++++++-------- .../source/tree/LazyParseableElement.java | 20 +++++++------ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index b75cbe83a137..de80e0488b13 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -507,21 +507,26 @@ public class CompositeElement extends TreeElement { if (wrapper != null) return wrapper; synchronized (PsiLock.LOCK) { - wrapper = myWrapper; - if (wrapper != null) return wrapper; - - final Language lang = getElementType().getLanguage(); - final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang); - if (parserDefinition != null) { - myWrapper = wrapper = parserDefinition.createElement(this); - //noinspection ConstantConditions - LOG.assertTrue(wrapper != null, "ParserDefinition.createElement() may not return null"); - } - - return wrapper; + return getPsiNoLock(); } } + PsiElement getPsiNoLock() { + PsiElement wrapper = myWrapper; + if (wrapper != null) return wrapper; + + final Language lang = getElementType().getLanguage(); + final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang); + if (parserDefinition != null) { + myWrapper = wrapper = parserDefinition.createElement(this); + //noinspection ConstantConditions + LOG.assertTrue(wrapper != null, "ParserDefinition.createElement() may not return null"); + } + + //noinspection ConstantConditions + return wrapper; + } + public void setPsi(@NotNull PsiElement psi) { myWrapper = psi; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index ebe2c993b5ef..5d391508b997 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -21,7 +21,6 @@ package com.intellij.psi.impl.source.tree; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.psi.PsiLock; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.ILazyParseableElementType; import com.intellij.util.text.CharArrayUtil; @@ -30,10 +29,17 @@ import org.jetbrains.annotations.NotNull; public class LazyParseableElement extends CompositeElement { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.LazyParseableElement"); private static final RecursiveTreeElementWalkingVisitor CREATE_PSI = new RecursiveTreeElementWalkingVisitor(false) { + @Override - protected void visitNode(TreeElement element) { - element.getPsi(); + public void visitLeaf(LeafElement leaf) { } + + @Override + public void visitComposite(CompositeElement composite) { + composite.getPsiNoLock(); + super.visitComposite(composite); + } + }; private static class ChameleonLock { @@ -169,12 +175,8 @@ public class LazyParseableElement extends CompositeElement { rawAddChildren((TreeElement)parsedNode); //ensure PSI is created all at once, to reduce contention of PsiLock in CompositeElement.getPsi() - synchronized (PsiLock.LOCK) { - while (parsedNode != null) { - ((TreeElement)parsedNode).acceptTree(CREATE_PSI); - parsedNode = parsedNode.getTreeNext(); - } - } + ((TreeElement)parsedNode).acceptTree(CREATE_PSI); + parsedNode = parsedNode.getTreeNext(); } } From 37dec12dc52a7df0b1848521f3eba02fbebe69f3 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 12:24:59 +0400 Subject: [PATCH 34/81] eager PSI calculation, fix no PSI calculation --- .../impl/source/tree/CompositeElement.java | 21 ++++++++++--------- .../impl/source/tree/CompositePsiElement.java | 5 ++--- .../source/tree/LazyParseableElement.java | 2 +- .../source/tree/LazyParseablePsiElement.java | 5 ++--- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index de80e0488b13..8783791a4a6c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -20,6 +20,7 @@ import com.intellij.extapi.psi.ASTDelegatePsiElement; import com.intellij.lang.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.pom.tree.events.ChangeInfo; import com.intellij.pom.tree.events.TreeChangeEvent; import com.intellij.pom.tree.events.impl.ChangeInfoImpl; @@ -502,29 +503,29 @@ public class CompositeElement extends TreeElement { } } - public PsiElement getPsi() { + public final PsiElement getPsi() { + ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly + PsiElement wrapper = myWrapper; if (wrapper != null) return wrapper; synchronized (PsiLock.LOCK) { - return getPsiNoLock(); + wrapper = myWrapper; + if (wrapper != null) return wrapper; + + return myWrapper = createPsiNoLock(); } } - PsiElement getPsiNoLock() { - PsiElement wrapper = myWrapper; - if (wrapper != null) return wrapper; - + protected PsiElement createPsiNoLock() { final Language lang = getElementType().getLanguage(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang); if (parserDefinition != null) { - myWrapper = wrapper = parserDefinition.createElement(this); - //noinspection ConstantConditions - LOG.assertTrue(wrapper != null, "ParserDefinition.createElement() may not return null"); + return parserDefinition.createElement(this); } //noinspection ConstantConditions - return wrapper; + return null; } public void setPsi(@NotNull PsiElement psi) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java index e20262e14965..be77e8b228ed 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java @@ -22,7 +22,6 @@ import com.intellij.lang.Language; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; @@ -278,8 +277,8 @@ public abstract class CompositePsiElement extends CompositeElement implements Ps return this; } - public PsiElement getPsi() { - ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly + @Override + protected PsiElement createPsiNoLock() { return this; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index 5d391508b997..c77d34a7af46 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -36,7 +36,7 @@ public class LazyParseableElement extends CompositeElement { @Override public void visitComposite(CompositeElement composite) { - composite.getPsiNoLock(); + composite.createPsiNoLock(); super.visitComposite(composite); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java index 54e74c316ac3..7f7ade51a517 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java @@ -25,7 +25,6 @@ import com.intellij.lang.Language; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; @@ -282,8 +281,8 @@ public class LazyParseablePsiElement extends LazyParseableElement implements Psi return this; } - public PsiElement getPsi() { - ProgressManager.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly + @Override + protected PsiElement createPsiNoLock() { return this; } From 8f742f83ecee7d258dd09c53f3b86c955f0dcf5f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 13:08:02 +0400 Subject: [PATCH 35/81] restore removed method --- .../jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 73e738405b4d..5ae761fdca3f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -260,6 +260,14 @@ public class PsiUtil { return null; } + public static SearchScope restrictScopeToGroovyFiles(final Computable originalScopeComputation) { //important to compute originalSearchScope in read action! + return ApplicationManager.getApplication().runReadAction(new Computable() { + public SearchScope compute() { + return restrictScopeToGroovyFiles(originalScopeComputation.compute()); + } + }); + } + public static SearchScope restrictScopeToGroovyFiles(SearchScope originalScope) { if (originalScope instanceof GlobalSearchScope) { return GlobalSearchScope.getScopeRestrictedByFileTypes((GlobalSearchScope)originalScope, GroovyFileTypeLoader.getGroovyEnabledFileTypes()); From 098adf8247d552465409a106e816103faaf4bb24 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 10 Jun 2010 11:42:57 +0400 Subject: [PATCH 36/81] git: commit and push->commit and push... --- .../git4idea/src/git4idea/checkin/GitCommitAndPushExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/checkin/GitCommitAndPushExecutor.java b/plugins/git4idea/src/git4idea/checkin/GitCommitAndPushExecutor.java index 67b83ec2fccc..512ce1fab7e8 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCommitAndPushExecutor.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCommitAndPushExecutor.java @@ -32,7 +32,7 @@ public class GitCommitAndPushExecutor implements CommitExecutor { @Nls public String getActionText() { - return "Commit and &Push"; + return "Commit and &Push..."; } @NotNull From 009719537bb7b31798712b362cc8dc0d2db658ae Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 Jun 2010 14:03:10 +0400 Subject: [PATCH 37/81] [Mercurial] Listen to .hg/dirstate changes to watch external VCS operarations. --- .../hg4idea/HgDirStateChangeListener.java | 45 +++++++++++++++++++ .../hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 7 +++ .../hg4idea/provider/HgChangeProvider.java | 15 +++++++ 3 files changed, 67 insertions(+) create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/HgDirStateChangeListener.java diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgDirStateChangeListener.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgDirStateChangeListener.java new file mode 100644 index 000000000000..45b231b84279 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgDirStateChangeListener.java @@ -0,0 +1,45 @@ +/* + * 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.zmlx.hg4idea; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; +import com.intellij.openapi.vfs.VirtualFileAdapter; +import com.intellij.openapi.vfs.VirtualFileEvent; + +/** + * HgDirStateChangeListener listens to the changes of .hg/dirstate to catch external commits and other version control events. + * It updates file statuses of the files in the Changes view on each dirstate change. + * Other files need not to be updated. + * + * @author Kirill Likhodedov + */ +public class HgDirStateChangeListener extends VirtualFileAdapter { + + private final Project myProject; + + public HgDirStateChangeListener(Project project) { + myProject = project; + } + + @Override + public void contentsChanged(VirtualFileEvent event) { + if (event.getFile().getPath().endsWith(HgVcs.DIRSTATE_FILE_PATH)) { + VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty(); + } + } + +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index b245312417b0..ed5c4bb3110f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -56,6 +56,7 @@ public class HgVcs extends AbstractVcs { private static final Icon OUTGOING_ICON = IconLoader.getIcon("/actions/moveUp.png"); public static final String VCS_NAME = "hg4idea"; + public static final String DIRSTATE_FILE_PATH = ".hg/dirstate"; private final HgChangeProvider changeProvider; private final HgProjectConfigurable configurable; @@ -78,6 +79,7 @@ public class HgVcs extends AbstractVcs { private boolean started = false; private HgVFSListener myVFSListener; + private VirtualFileListener myDirStateChangeListener; public HgVcs(Project project, HgGlobalSettings globalSettings, HgProjectSettings projectSettings) { @@ -95,6 +97,7 @@ public class HgVcs extends AbstractVcs { integrateEnvironment = new HgIntegrateEnvironment(project); commitedChangesProvider = new HgCachingCommitedChangesProvider(project); commitExecutor = new HgCommitExecutor(project); + myDirStateChangeListener = new HgDirStateChangeListener(myProject); } public String getDisplayName() { @@ -276,6 +279,8 @@ public class HgVcs extends AbstractVcs { ); myVFSListener = new HgVFSListener(myProject, this); + + VirtualFileManager.getInstance().addVirtualFileListener(myDirStateChangeListener); } @Override @@ -301,6 +306,8 @@ public class HgVcs extends AbstractVcs { Disposer.dispose(myVFSListener); myVFSListener = null; } + + VirtualFileManager.getInstance().removeVirtualFileListener(myDirStateChangeListener); } public static HgVcs getInstance(Project project) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index 80d8cf53dd6b..b693c2c9ce27 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -17,13 +17,16 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import org.zmlx.hg4idea.HgContentRevision; import org.zmlx.hg4idea.HgFile; import org.zmlx.hg4idea.HgRevisionNumber; +import org.zmlx.hg4idea.HgVcs; import org.zmlx.hg4idea.command.*; +import java.io.File; import java.util.*; public class HgChangeProvider implements ChangeProvider { @@ -58,11 +61,23 @@ public class HgChangeProvider implements ChangeProvider { } for (FilePath filePath : dirtyScope.getDirtyFiles()) { process(builder, filePath, processedRoots); + loadDirstateFile(filePath); } processUnsavedChanges(builder, dirtyScope.getDirtyFilesNoExpand()); } + /** + * Watching the changes from .hg/dirstate to monitor external VCS + * @param filepath file which vcs root is to be monitored. + */ + private void loadDirstateFile(FilePath filepath) { + final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(myProject, filepath); + if (vcsRoot != null) { + LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(vcsRoot.getPath(), HgVcs.DIRSTATE_FILE_PATH)); + } + } + public boolean isModifiedDocumentTrackingRequired() { return true; } From d69fc86f09fc1fd5602dd4a72d70e3e2d44e326a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 Jun 2010 14:14:34 +0400 Subject: [PATCH 38/81] [Mercurial] Fix: don't handle unsaved files if they have already been processed by the change provider (like modified or else). --- .../hg4idea/provider/HgChangeProvider.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index b693c2c9ce27..cc52e25a3967 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -54,17 +54,18 @@ public class HgChangeProvider implements ChangeProvider { } public void getChanges(VcsDirtyScope dirtyScope, ChangelistBuilder builder, - ProgressIndicator progress, ChangeListManagerGate addGate) throws VcsException { - Set processedRoots = new LinkedHashSet(); + ProgressIndicator progress, ChangeListManagerGate addGate) throws VcsException { + final Set processedRoots = new LinkedHashSet(); + final Collection changes = new HashSet(); for (FilePath filePath : dirtyScope.getRecursivelyDirtyDirectories()) { - process(builder, filePath, processedRoots); + changes.addAll(process(builder, filePath, processedRoots)); } for (FilePath filePath : dirtyScope.getDirtyFiles()) { - process(builder, filePath, processedRoots); + changes.addAll(process(builder, filePath, processedRoots)); loadDirstateFile(filePath); } - processUnsavedChanges(builder, dirtyScope.getDirtyFilesNoExpand()); + processUnsavedChanges(builder, dirtyScope.getDirtyFilesNoExpand(), changes); } /** @@ -85,15 +86,15 @@ public class HgChangeProvider implements ChangeProvider { public void doCleanup(List files) { } - private void process(ChangelistBuilder builder, + private Collection process(ChangelistBuilder builder, FilePath filePath, Set processedRoots) { VirtualFile repo = VcsUtil.getVcsRootFor(myProject, filePath); if (repo == null || processedRoots.contains(repo)) { - return; + return new HashSet(); } Set hgChanges = new HgStatusCommand(myProject).execute(repo); if (hgChanges == null || hgChanges.isEmpty()) { - return; + return new HashSet(); } sendChanges(builder, hgChanges, new HgResolveCommand(myProject).list(repo), @@ -101,6 +102,7 @@ public class HgChangeProvider implements ChangeProvider { new HgWorkingCopyRevisionsCommand(myProject).firstParent(repo) ); processedRoots.add(repo); + return hgChanges; } private void sendChanges(ChangelistBuilder builder, Set changes, @@ -136,7 +138,7 @@ public class HgChangeProvider implements ChangeProvider { } } - private boolean isDeleteOfCopiedFile(HgChange change, Set changes) { + private static boolean isDeleteOfCopiedFile(HgChange change, Set changes) { if (change.getStatus().equals(HgFileStatusEnum.DELETED)) { for (HgChange otherChange : changes) { if (otherChange.getStatus().equals(HgFileStatusEnum.COPY) && @@ -151,8 +153,15 @@ public class HgChangeProvider implements ChangeProvider { /** * Finds modified but unsaved files in the given list of dirty files and notifies the builder about MODIFIED changes. + * Changes contained in alreadyProcessed are skipped - they have already been processed as modified, or else. */ - public void processUnsavedChanges(ChangelistBuilder builder, Set dirtyFiles) { + public void processUnsavedChanges(ChangelistBuilder builder, Set dirtyFiles, Collection alreadyProcessed) { + // exclude already processed + for (HgChange c : alreadyProcessed) { + dirtyFiles.remove(c.beforeFile().toFilePath()); + dirtyFiles.remove(c.afterFile().toFilePath()); + } + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); for (FilePath filePath : dirtyFiles) { From b2cb5825fdc8d20b2a7cc36ce8f062b460e457ec Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Tue, 15 Jun 2010 14:15:32 +0400 Subject: [PATCH 39/81] LanguageSelector uses EventDispatcher instead of a collection of listeners --- .../options/codeStyle/LanguageSelector.java | 11 ++++------- .../options/codeStyle/LanguageSelectorListener.java | 4 +++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java index db454e553d60..82603d4bf85f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java @@ -16,17 +16,16 @@ package com.intellij.application.options.codeStyle; import com.intellij.lang.Language; +import com.intellij.util.EventDispatcher; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; - /** * Maintains programming language selection for code style panels. */ public class LanguageSelector { private Language myLanguage; - private ArrayList listeners = new ArrayList(); + private final EventDispatcher myDispatcher = EventDispatcher.create(LanguageSelectorListener.class); private Language[] myLanguages = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings(); /** @@ -54,12 +53,10 @@ public class LanguageSelector { * @param l The listener to add. */ public void addListener(LanguageSelectorListener l) { - listeners.add(l); + myDispatcher.addListener(l); } private void notifyListeners(Language lang) { - for (LanguageSelectorListener l : listeners) { - l.languageChanged(lang); - } + myDispatcher.getMulticaster().languageChanged(lang); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelectorListener.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelectorListener.java index 6ea024c1e3fe..53f9bc9425ae 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelectorListener.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelectorListener.java @@ -17,11 +17,13 @@ package com.intellij.application.options.codeStyle; import com.intellij.lang.Language; +import java.util.EventListener; + /** * Must be implemented by components willing to be notified on current code style language * change. */ -public interface LanguageSelectorListener { +public interface LanguageSelectorListener extends EventListener { void languageChanged(Language lang); From 36e211ea489afebef99e56773c4395cd20edf8b0 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 15 Jun 2010 14:49:24 +0400 Subject: [PATCH 40/81] IDEA-55599: gwt: provide ClassName completion after @ in JSNi call expressions --- .../codeInsight/completion/AllClassesGetter.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index 0c30d28b266b..e7b76bbea611 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -146,6 +146,17 @@ public class AllClassesGetter { public void getClasses(final PsiElement context, final CompletionResultSet set, final int offset, final boolean filterByScope) { if (context == null || !context.isValid()) return; + final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(context); + getClasses(context, set, offset, filterByScope, lookingForAnnotations); + } + + public void getClasses(final PsiElement context, + final CompletionResultSet set, + final int offset, + final boolean filterByScope, + final boolean lookingForAnnotations) { + if (context == null || !context.isValid()) return; + final String packagePrefix = getPackagePrefix(context, offset); final Set qnames = new THashSet(); @@ -157,8 +168,6 @@ public class AllClassesGetter { }); final PrefixMatcher prefixMatcher = set.getPrefixMatcher(); - final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(context); - AllClassesSearch.search(scope, context.getProject(), new Condition() { public boolean value(String s) { return prefixMatcher.prefixMatches(s); From 2e5f8c84fd6a57be9bac1ca97dbee6bbcf855be0 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 15 Jun 2010 14:55:37 +0400 Subject: [PATCH 41/81] IDEA-55527 Idea 9.0.2 - Experiencing performance problems - hangs, window repainting glitches during normal use: refresh local changes only when something changed --- .../openapi/vcs/changes/ChangeListManagerImpl.java | 8 +++++--- .../intellij/openapi/vcs/changes/ChangeListWorker.java | 10 ++++++---- .../com/intellij/openapi/vcs/changes/ChangesDelta.java | 6 ++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index b872e1241358..8e47b21bb77e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -294,6 +294,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec final boolean wasEverythingDirty = invalidated.isEverythingDirty(); final List scopes = invalidated.getScopes(); + boolean somethingChangedInView = false; try { checkIfDisposed(); @@ -314,7 +315,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec if (wasEverythingDirty) { changeListWorker.notifyStartProcessingChanges(null); } - myChangesViewManager.scheduleRefresh(); final ChangeListManagerGate gate = changeListWorker.createSelfGate(); @@ -380,11 +380,12 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec myModifier.clearQueue(); // update member from copy if (takeChanges) { - myWorker.takeData(changeListWorker); + somethingChangedInView |= myWorker.takeData(changeListWorker); } if (takeChanges && updateUnversionedFiles) { boolean statusChanged = !myComposite.equals(composite); + somethingChangedInView |= statusChanged; myComposite = composite; if (statusChanged) { myDelayedNotificator.getProxyDispatcher().unchangedFileStatusChanged(); @@ -396,7 +397,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec } myShowLocalChangesInvalidated = false; } - myChangesViewManager.scheduleRefresh(); } catch (DisposedException e) { // OK, we're finishing all the stuff now. @@ -415,6 +415,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec synchronized (myDataLock) { myDelayedNotificator.getProxyDispatcher().changeListUpdateDone(); + } + if (somethingChangedInView) { myChangesViewManager.scheduleRefresh(); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java index 8a5fb2a2e8c3..bda1c6658d01 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java @@ -94,20 +94,22 @@ public class ChangeListWorker implements ChangeListsWriteOperations { myDefault = defaultList; } - public void takeData(@NotNull final ChangeListWorker worker) { + public boolean takeData(@NotNull final ChangeListWorker worker) { myMap.clear(); myMap.putAll(worker.myMap); myDefault = worker.myDefault; myListsToDisappear.clear(); myListsToDisappear.addAll(worker.myListsToDisappear); - - myDelta.step(myIdx, worker.myIdx); + + final boolean somethingChanged = myDelta.step(myIdx, worker.myIdx); myIdx = new ChangeListsIndexes(worker.myIdx); checkForMultipleCopiesNotMove(); - // todo +- + myLocallyDeleted.takeFrom(worker.myLocallyDeleted); mySwitchedHolder.takeFrom(worker.mySwitchedHolder); + + return somethingChanged; } private void checkForMultipleCopiesNotMove() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesDelta.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesDelta.java index 43a38faf00d4..be5e4611f6de 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesDelta.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesDelta.java @@ -36,12 +36,13 @@ public class ChangesDelta { myVcsManager = ProjectLevelVcsManager.getInstance(project); } - public void step(final ChangeListsIndexes was, final ChangeListsIndexes became) { + // true -> something changed + public boolean step(final ChangeListsIndexes was, final ChangeListsIndexes became) { List> wasAffected = was.getAffectedFilesUnderVcs(); if (! myInitialized) { sendPlus(wasAffected); myInitialized = true; - return; + return true; //+- } final List> becameAffected = became.getAffectedFilesUnderVcs(); @@ -54,6 +55,7 @@ public class ChangesDelta { } } sendPlus(toAdd); + return toRemove != null || toAdd != null; } private void sendPlus(final Collection> toAdd) { From 0768e4cc514ea16a5f89a373b93265e9c4705352 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 15 Jun 2010 14:37:26 +0400 Subject: [PATCH 42/81] findClass() added to Java code insight text fixture --- .../fixtures/JavaCodeInsightTestFixture.java | 3 +++ .../fixtures/impl/JavaCodeInsightTestFixtureImpl.java | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java index 6565e6ab8413..0e94b11d159f 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java @@ -29,4 +29,7 @@ public interface JavaCodeInsightTestFixture extends CodeInsightTestFixture { JavaPsiFacade getJavaFacade(); PsiClass addClass(@NotNull @NonNls final String classText) throws IOException; + + @NotNull + PsiClass findClass(@NotNull @NonNls String name); } diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java index 0b4f2d1180d9..32d51da7a14d 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java @@ -17,6 +17,7 @@ package com.intellij.testFramework.fixtures.impl; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.ProjectScope; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture; import com.intellij.testFramework.fixtures.TempDirTestFixture; @@ -54,5 +55,11 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i final PsiFile psiFile = addFileToProject(rootPath, qName.replace('.', '/') + ".java", classText); return ((PsiJavaFile)psiFile).getClasses()[0]; } -} + @NotNull + public PsiClass findClass(@NotNull @NonNls final String name) { + final PsiClass aClass = getJavaFacade().findClass(name, ProjectScope.getProjectScope(getProject())); + assertNotNull("Class " + name + " not found", aClass); + return aClass; + } +} From d009f8245dd329141b4edc7af7184b9ab98d0749 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 15 Jun 2010 14:48:34 +0400 Subject: [PATCH 43/81] fix PyMultiFileResolveTest --- .../src/com/intellij/psi/util/PsiTreeUtil.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java index 217679658281..121d83dc1ade 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.PsiElementProcessor; +import com.intellij.psi.stubs.StubBase; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; @@ -251,6 +252,19 @@ public class PsiTreeUtil { return getParentOfType(element, aClass, true); } + @Nullable + public static E getStubOrPsiParentOfType(@Nullable PsiElement element, final Class parentClass) { + if (element instanceof StubBasedPsiElement) { + StubBase stub = (StubBase)((StubBasedPsiElement) element).getStub(); + if (stub != null) { + //noinspection unchecked + return (E)stub.getParentStubOfType(parentClass); + } + + } + return getParentOfType(element, parentClass); + } + @Nullable public static T getContextOfType(@Nullable PsiElement element, @NotNull Class aClass, boolean strict) { if (element == null) return null; if (strict) { From f1a9db7d7381521a6585521b8b85610593c9625c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 15 Jun 2010 16:10:41 +0400 Subject: [PATCH 44/81] PsiDynaReferences support --- .../reference/impl/providers/FileReferenceUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceUtil.java index 938d8bed9781..f401c935a18e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.source.resolve.reference.impl.providers; +import com.intellij.openapi.paths.PsiDynaReference; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; @@ -52,7 +53,11 @@ public class FileReferenceUtil { @Nullable public static PsiFile findFile(PsiReference...references) { for (int i = references.length - 1; i >= 0; i--) { - if (references[i] instanceof FileReference) { + PsiReference ref = references[i]; + if (ref instanceof PsiDynaReference) { + ref = ((PsiDynaReference)ref).getLastFileReference(); + } + if (ref instanceof FileReference) { final PsiElement file = references[i].resolve(); return file instanceof PsiFile ? (PsiFile)file : null; } From 01e51ee0a70cf76d243def1b2587e92641e21195 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 16:55:57 +0400 Subject: [PATCH 45/81] give chance to all references --- .../src/com/intellij/psi/search/RequestResultProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java b/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java index 28cb9580a8f7..e73f4431a59c 100644 --- a/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java +++ b/platform/lang-api/src/com/intellij/psi/search/RequestResultProcessor.java @@ -13,7 +13,9 @@ public abstract class RequestResultProcessor { public boolean execute(PsiElement element, int offsetInElement, final Processor consumer) { for (PsiReference ref : element.getReferences()) { if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) { - return processReference(consumer, ref); + if (!processReference(consumer, ref)) { + return false; + } } } return true; From 480dc2ef2b20ecfcd6a2a148148621f8147723f1 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 16:56:28 +0400 Subject: [PATCH 46/81] allow reentrant ReferencesSearch & MethodReferencesSearch --- .../psi/impl/search/MethodUsagesSearcher.java | 16 +++++++------- .../searches/MethodReferencesSearch.java | 6 +++++- .../impl/search/CachesBasedRefSearcher.java | 21 +++++++++---------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index d972dc8aaf2c..61cf065ab86f 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -16,10 +16,9 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecutor { - private static final ThreadLocal ourProcessing = new ThreadLocal(); public boolean execute(final MethodReferencesSearch.SearchParameters p, final Processor consumer) { - if (ourProcessing.get() != null) { + if (p instanceof MySearchParameters) { return true; } @@ -48,13 +47,7 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut contributeSearchTargets(method, options, collector, strictSignatureSearch); collector.searchCustom(new Processor>() { public boolean process(Processor processor) { - ourProcessing.set(true); - try { - return MethodReferencesSearch.search(method, options.searchScope, strictSignatureSearch).forEach(processor); - } - finally { - ourProcessing.set(null); - } + return MethodReferencesSearch.search(new MySearchParameters(method, options, strictSignatureSearch)).forEach(processor); } }); } @@ -105,4 +98,9 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut collector.searchWord(textToSearch, restrictedByAccess, searchContext, true, new MethodTextOccurenceProcessor(aClass, strictSignatureSearch, methods)); } + private static class MySearchParameters extends MethodReferencesSearch.SearchParameters { + public MySearchParameters(PsiMethod method, FindUsagesOptions options, boolean strictSignatureSearch) { + super(method, options.searchScope, strictSignatureSearch); + } + } } diff --git a/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java b/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java index c66605b7da69..060dd0ffae5f 100644 --- a/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java +++ b/java/openapi/src/com/intellij/psi/search/searches/MethodReferencesSearch.java @@ -55,8 +55,12 @@ public class MethodReferencesSearch extends ExtensibleQueryFactory search(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch) { + return search(new SearchParameters(method, scope, strictSignatureSearch)); + } + + public static Query search(final SearchParameters parameters) { //noinspection unchecked - return INSTANCE.createUniqueResultsQuery(new SearchParameters(method, scope, strictSignatureSearch), TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER); + return INSTANCE.createUniqueResultsQuery(parameters, TObjectHashingStrategy.CANONICAL, ReferenceDescriptor.MAPPER); } public static Query search(final PsiMethod method, final boolean strictSignatureSearch) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index 0c488928610b..b0ed2764706c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -25,10 +25,9 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExecutor { - private static final ThreadLocal ourProcessing = new ThreadLocal(); public boolean execute(final ReferencesSearch.SearchParameters p, final Processor consumer) { - if (ourProcessing.get() != null) { + if (p instanceof MySearchParameters) { return true; } @@ -48,20 +47,14 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec @Override public void contributeRequests(@NotNull final PsiElement refElement, - @NotNull FindUsagesOptions options, - @NotNull SearchRequestCollector collector) { + @NotNull FindUsagesOptions options, + @NotNull SearchRequestCollector collector) { final boolean ignoreAccessScope = false; final SearchScope scope = options.searchScope; contributeSearchTargets(refElement, options, collector, ignoreAccessScope, scope); collector.searchCustom(new Processor>() { public boolean process(Processor consumer) { - ourProcessing.set(true); - try { - return ReferencesSearch.search(refElement, scope, ignoreAccessScope).forEach(consumer); - } - finally { - ourProcessing.set(null); - } + return ReferencesSearch.search(new MySearchParameters(refElement, scope, ignoreAccessScope)).forEach(consumer); } }); } @@ -100,4 +93,10 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec collector.searchWord(text, searchScope, refElement.getLanguage().isCaseSensitive(), refElement); } } + + private static class MySearchParameters extends ReferencesSearch.SearchParameters { + public MySearchParameters(PsiElement refElement, SearchScope scope, boolean ignoreAccessScope) { + super(refElement, scope, ignoreAccessScope); + } + } } From 95d504b63587dcd96636272269ea985691f946e7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 Jun 2010 17:09:55 +0400 Subject: [PATCH 47/81] [Mercurial] Fixed possible NPE. --- .../src/org/zmlx/hg4idea/provider/HgChangeProvider.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index cc52e25a3967..d25e69d3c96b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -170,8 +170,9 @@ public class HgChangeProvider implements ChangeProvider { final VirtualFile root = vcsManager.getVcsRootFor(vf); if (root != null) { final HgRevisionNumber beforeRevisionNumber = new HgWorkingCopyRevisionsCommand(myProject).identify(root); - builder.processChange(new Change(new HgContentRevision(myProject, new HgFile(myProject, vf), beforeRevisionNumber), - CurrentContentRevision.create(filePath), FileStatus.MODIFIED), myVcsKey); + final ContentRevision beforeRevision = (beforeRevisionNumber == null ? null : + new HgContentRevision(myProject, new HgFile(myProject, vf), beforeRevisionNumber)); + builder.processChange(new Change(beforeRevision, CurrentContentRevision.create(filePath), FileStatus.MODIFIED), myVcsKey); } } } From a45a8a7d085291e99c1bb9bb71ac2f8ccd61047f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 15 Jun 2010 18:46:57 +0400 Subject: [PATCH 48/81] again, allow reentrant searches (even hackier) --- .../psi/impl/search/MethodUsagesSearcher.java | 12 +++++++++++- .../psi/impl/search/CachesBasedRefSearcher.java | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java index 61cf065ab86f..b1afc09a7838 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java @@ -27,7 +27,7 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { - final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); + final FindUsagesOptions options = new MyFindUsagesOptions(p); options.isUsages = true; contributeSearchTargets(method, options, collector, p.isStrictSignatureSearch()); SearchRequestor.collectRequests(method, options, collector); @@ -41,6 +41,10 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut public void contributeRequests(@NotNull PsiElement target, @NotNull final FindUsagesOptions options, @NotNull SearchRequestCollector collector) { + if (options instanceof MyFindUsagesOptions) { + return; + } + if (target instanceof PsiMethod) { final boolean strictSignatureSearch = !options.isIncludeOverloadUsages; final PsiMethod method = (PsiMethod)target; @@ -103,4 +107,10 @@ public class MethodUsagesSearcher extends SearchRequestor implements QueryExecut super(method, options.searchScope, strictSignatureSearch); } } + + private static class MyFindUsagesOptions extends FindUsagesOptions { + public MyFindUsagesOptions(MethodReferencesSearch.SearchParameters p) { + super(p.getScope()); + } + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java index b0ed2764706c..3cad807eeb65 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/CachesBasedRefSearcher.java @@ -36,7 +36,7 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { - final FindUsagesOptions options = new FindUsagesOptions(p.getScope()); + final FindUsagesOptions options = new MyFindUsagesOptions(p); options.isUsages = true; contributeSearchTargets(refElement, options, collector, p.isIgnoreAccessScope(), options.searchScope); SearchRequestor.collectRequests(refElement, options, collector); @@ -49,6 +49,10 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec public void contributeRequests(@NotNull final PsiElement refElement, @NotNull FindUsagesOptions options, @NotNull SearchRequestCollector collector) { + if (options instanceof MyFindUsagesOptions) { + return; + } + final boolean ignoreAccessScope = false; final SearchScope scope = options.searchScope; contributeSearchTargets(refElement, options, collector, ignoreAccessScope, scope); @@ -99,4 +103,10 @@ public class CachesBasedRefSearcher extends SearchRequestor implements QueryExec super(refElement, scope, ignoreAccessScope); } } + + private static class MyFindUsagesOptions extends FindUsagesOptions { + public MyFindUsagesOptions(ReferencesSearch.SearchParameters p) { + super(p.getScope()); + } + } } From ff0b261b0b76fac3bc4002c1af72f40fe6adf8bf Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 15 Jun 2010 20:50:04 +0400 Subject: [PATCH 49/81] add hg4idea to PyCharm --- plugins/hg4idea/src/META-INF/plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 0406e1850618..f68e0a57d997 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -20,7 +20,7 @@ 10.0 Victor Iacoban and Willem Verstraeten com.intellij.modules.vcs - + From a16720edb92c8dec2c402bb6363b8f28ce627436 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 15 Jun 2010 21:03:32 +0400 Subject: [PATCH 50/81] EA-20703 - NPE: GlassLayer.getData --- .../intellij/uiDesigner/designSurface/GlassLayer.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java index 81db6370b426..51cafe4e9cd2 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.ui.popup.PopupOwner; import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.actions.*; +import com.intellij.uiDesigner.componentTree.ComponentTree; import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.radComponents.RadComponent; import org.jetbrains.annotations.NonNls; @@ -135,11 +136,12 @@ public final class GlassLayer extends JComponent implements DataProvider, PopupO */ public Object getData(final String dataId) { if(PlatformDataKeys.NAVIGATABLE.is(dataId)) { - return UIDesignerToolWindowManager.getInstance(myEditor.getProject()).getComponentTree().getData(dataId); - } - else{ - return null; + final ComponentTree componentTree = UIDesignerToolWindowManager.getInstance(myEditor.getProject()).getComponentTree(); + if (componentTree != null) { + return componentTree.getData(dataId); + } } + return null; } @Nullable From b32b9f06c6186cbc9d85164ed052c9dadb8f5cb6 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 15 Jun 2010 16:16:12 +0400 Subject: [PATCH 51/81] Merge alarm thread pool for own threads with one in Application. --- .../platform-api/src/com/intellij/util/Alarm.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java index 4aafb948aa95..9f4b1f78ddb6 100644 --- a/platform/platform-api/src/com/intellij/util/Alarm.java +++ b/platform/platform-api/src/com/intellij/util/Alarm.java @@ -43,8 +43,6 @@ public class Alarm implements Disposable { private final List myRequests = new ArrayList(); private final List myPendingRequests = new ArrayList(); - private final ThreadPoolExecutor myExecutorService; - private static final ThreadPoolExecutor ourSharedExecutorService = ConcurrencyUtil.newSingleThreadExecutor("Alarm pool(shared)", Thread.NORM_PRIORITY - 2); private final Object LOCK = new Object(); @@ -55,10 +53,6 @@ public class Alarm implements Disposable { public void dispose() { myDisposed = true; cancelAllRequests(); - if (myThreadToUse == ThreadToUse.OWN_THREAD) { - myExecutorService.getQueue().clear(); - myExecutorService.shutdown(); - } } public enum ThreadToUse { @@ -84,7 +78,6 @@ public class Alarm implements Disposable { } public Alarm(@NotNull ThreadToUse threadToUse, Disposable parentDisposable) { myThreadToUse = threadToUse; - myExecutorService = threadToUse == ThreadToUse.OWN_THREAD ? ConcurrencyUtil.newSingleThreadExecutor("Alarm pool(own)", Thread.NORM_PRIORITY - 2) : ourSharedExecutorService; if (parentDisposable != null) { Disposer.register(parentDisposable, this); @@ -243,7 +236,9 @@ public class Alarm implements Disposable { } } else { - myFuture = myExecutorService.submit(scheduledTask); + myFuture = (myThreadToUse == ThreadToUse.SHARED_THREAD) + ? ourSharedExecutorService.submit(scheduledTask) + : ApplicationManager.getApplication().executeOnPooledThread(scheduledTask); } } } From 60c4abae1fdfc71a53ec6838e1d749e1a220d864 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 15 Jun 2010 16:17:04 +0400 Subject: [PATCH 52/81] Allow threads to die earlier. 5 minutes is long enough for buffering. --- .../com/intellij/openapi/application/impl/ApplicationImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 8e2d5bc46a12..1e156a0ec12c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -107,7 +107,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application private final ExecutorService ourThreadExecutorsService = new ThreadPoolExecutor( 3, Integer.MAX_VALUE, - 30 * 60L, + 5 * 60L, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadFactory() { From 1201f4dae4a21703129b6c238a5c9cd796741fe7 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 15 Jun 2010 21:35:16 +0400 Subject: [PATCH 53/81] This kind of things seems to be over-engineered. --- .../openapi/progress/BackgroundTaskQueue.java | 14 ++++- .../intellij/testFramework/UnitTestMode.java | 62 ------------------- 2 files changed, 12 insertions(+), 64 deletions(-) delete mode 100644 platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java diff --git a/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 11a821e962e4..231f5cee68be 100644 --- a/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-api/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; -import com.intellij.testFramework.UnitTestMode; import org.jetbrains.annotations.NotNull; import java.util.LinkedList; @@ -35,6 +34,7 @@ public class BackgroundTaskQueue { private final Queue myQueue = new LinkedList(); private boolean myHasActiveTask = false; private Task.Backgroundable myRunnerTask; + private Boolean myForcedTestMode = null; public BackgroundTaskQueue(String title) { this(null, title); @@ -76,7 +76,7 @@ public class BackgroundTaskQueue { } public void run(Task.Backgroundable task) { - if (UnitTestMode.getInstance(myProject).isInUnitTestMode(BackgroundTaskQueue.class.getName())) { + if (isInTestMode()) { task.run(new EmptyProgressIndicator()); task.onSuccess(); } @@ -96,6 +96,7 @@ public class BackgroundTaskQueue { } } + private void runRunner() { final Application application = ApplicationManager.getApplication(); if (application.isUnitTestMode()) { @@ -119,4 +120,13 @@ public class BackgroundTaskQueue { } } } + + private boolean isInTestMode() { + if (myForcedTestMode != null) return myForcedTestMode.booleanValue(); + return ApplicationManager.getApplication().isUnitTestMode(); + } + + public void setTestMode(boolean forcedTestMode) { + myForcedTestMode = forcedTestMode; + } } diff --git a/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java b/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java deleted file mode 100644 index 01160687b1fa..000000000000 --- a/platform/platform-api/src/com/intellij/testFramework/UnitTestMode.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.intellij.testFramework; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ProjectComponent; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -import java.util.HashSet; -import java.util.Set; - -public class UnitTestMode implements ProjectComponent { - private final Set myNotInUnitTestMode; - - public UnitTestMode() { - myNotInUnitTestMode = new HashSet(); - } - - public static UnitTestMode getInstance(final Project project) { - return project.getComponent(UnitTestMode.class); - } - - public void register(final Object obj) { - myNotInUnitTestMode.add(obj); - } - - public boolean isInUnitTestMode(final Object key) { - if (myNotInUnitTestMode.contains(key)) return false; - return ApplicationManager.getApplication().isUnitTestMode(); - } - - public void projectClosed() { - } - - public void projectOpened() { - } - - @NotNull - public String getComponentName() { - return getClass().getName(); - } - - public void initComponent() { - } - - public void disposeComponent() { - } -} From 0ea5315af793831f81c98d51bc16f2349f0c4c12 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 15 Jun 2010 21:40:52 +0400 Subject: [PATCH 54/81] diagnostics for EA-20631 - UOE: PsiElementBase.delete --- .../src/com/intellij/extapi/psi/ASTDelegatePsiElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java b/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java index 308512ecd921..4c772793361e 100644 --- a/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java +++ b/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java @@ -293,7 +293,7 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase { getParent().deleteChildRange(this, this); } else { - super.delete(); + throw new UnsupportedOperationException(getClass().getName() + " under " + (getParent() == null ? "null" : getParent().getClass().getName())); } } From 410fdb43598206c718b7b0c7b09f39c5451aafaf Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 15 Jun 2010 22:01:43 +0400 Subject: [PATCH 55/81] remove incorrect started check from isVersionedDirectory() --- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index b245312417b0..37317bf0c782 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -193,13 +193,9 @@ public class HgVcs extends AbstractVcs { @Override public boolean isVersionedDirectory(VirtualFile dir) { - if (!started) { - return false; - } - VirtualFile currentDir = dir; while (currentDir != null) { - if (currentDir.findFileByRelativePath(".hg") != null) { + if (currentDir.findChild(".hg") != null) { return true; } currentDir = currentDir.getParent(); From 2ef857b24de87e783dded9a3296a2cbfffab3185 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Tue, 15 Jun 2010 23:34:55 +0400 Subject: [PATCH 56/81] tests fix --- platform/platform-resources/src/componentSets/Platform.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml index 95d147f7c49b..a137d898aaf0 100644 --- a/platform/platform-resources/src/componentSets/Platform.xml +++ b/platform/platform-resources/src/componentSets/Platform.xml @@ -166,9 +166,5 @@ - - com.intellij.testFramework.UnitTestMode - - From 6b19e0119cba96af38678232bcc6ebe77b9ff185 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 14 Jun 2010 17:51:53 +0400 Subject: [PATCH 57/81] Small optimization of GroovyNamesUtil. --- .../groovy/refactoring/GroovyNamesUtil.java | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java index 2ccb9743a608..6155c6134561 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNamesUtil.java @@ -17,9 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring; import com.intellij.lexer.Lexer; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.Function; import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; @@ -33,8 +31,12 @@ import java.util.regex.Pattern; */ public class GroovyNamesUtil { + private static final Pattern PATTERN = Pattern.compile("[A-Za-z][a-z]*"); + + private GroovyNamesUtil() { + } + public static boolean isIdentifier(String text) { - ApplicationManager.getApplication().assertReadAccessAllowed(); if (text == null) return false; Lexer lexer = new GroovyLexer(); @@ -45,8 +47,6 @@ public class GroovyNamesUtil { } public static boolean isKeyword(String text) { - ApplicationManager.getApplication().assertReadAccessAllowed(); - Lexer lexer = new GroovyLexer(); lexer.start(text); if (lexer.getTokenType() == null || !GroovyTokenTypes.KEYWORDS.contains(lexer.getTokenType())) return false; @@ -54,45 +54,39 @@ public class GroovyNamesUtil { return lexer.getTokenType() == null; } - public static ArrayList camelizeString(String str) { - String tempString = str; - tempString = deleteNonLetterFromString(tempString); - ArrayList camelizedTokens = new ArrayList(); - if (!isIdentifier(tempString)) { - return camelizedTokens; + ArrayList res = new ArrayList(); + StringBuilder sb = new StringBuilder(); + Matcher matcher = PATTERN.matcher(str); + + while (matcher.find()) { + res.add(matcher.group().toLowerCase()); + sb.append(matcher.group()); } - String result = fromLowerLetter(tempString); - while (!result.equals("")) { - result = fromLowerLetter(result); - String temp = ""; - while (!(result.length() == 0) && !result.substring(0, 1).toUpperCase().equals(result.substring(0, 1))) { - temp += result.substring(0, 1); - result = result.substring(1); - } - camelizedTokens.add(temp); + + if (!isIdentifier(sb.toString())) { + res.clear(); } - return camelizedTokens; + return res; } static String deleteNonLetterFromString(String tempString) { - Pattern pattern = Pattern.compile("[^a-zA-Z]"); - Matcher matcher = pattern.matcher(tempString); - return matcher.replaceAll(""); + return tempString.replaceAll("[^a-zA-Z]", ""); } static String fromLowerLetter(String str) { if (str.length() == 0) return ""; if (str.length() == 1) return str.toLowerCase(); - return str.substring(0, 1).toLowerCase() + str.substring(1); + char c = Character.toLowerCase(str.charAt(0)); + if (c == str.charAt(0)) return str; + return c + str.substring(1); } public static String camelToSnake(final String string) { - ArrayList tokens = camelizeString(string); - return StringUtil.join(ContainerUtil.map2Array(tokens, String.class, new Function() { + return StringUtil.join(camelizeString(string), new Function() { public String fun(final String s) { return StringUtil.decapitalize(s); } - }), "-"); + }, "-"); } } From a900a933be85a41b986f7cbcd570b2a258fe65fe Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 16 Jun 2010 01:26:00 +0400 Subject: [PATCH 58/81] Optimization of LightModifierList. --- .../dynamic/elements/DPropertyElement.java | 11 +-- .../impl/synthetic/GrAccessorMethodImpl.java | 12 ++- .../psi/impl/synthetic/GrGdkMethodImpl.java | 7 +- .../GrSyntheticMethodImplementation.java | 4 +- .../psi/impl/synthetic/LightModifierList.java | 82 +++++++++++++++++-- 5 files changed, 88 insertions(+), 28 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DPropertyElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DPropertyElement.java index cccb839152cf..c6dc0db20db9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DPropertyElement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DPropertyElement.java @@ -22,7 +22,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicManager; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrDynamicImplicitProperty; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.LightModifierList; -import java.util.LinkedHashSet; +import java.lang.reflect.Modifier; /** * User: Dmitry.Krasilschikov @@ -48,17 +48,14 @@ public class DPropertyElement extends DItemElement { public PsiVariable getPsi(PsiManager manager, final String containingClassName) { if (myPsi != null) return myPsi; - LinkedHashSet hashSet = new LinkedHashSet(); - Boolean isStatic = isStatic(); - if (isStatic != null && isStatic.booleanValue()) { - hashSet.add(PsiModifier.STATIC); - } + int modifiers = (isStatic != null && isStatic.booleanValue()) ? Modifier.STATIC : 0; + String type = getType(); if (type == null) { type = CommonClassNames.JAVA_LANG_OBJECT; } - myPsi = new GrDynamicImplicitProperty(manager, getName(), type, containingClassName, new LightModifierList(manager, hashSet), null) { + myPsi = new GrDynamicImplicitProperty(manager, getName(), type, containingClassName, new LightModifierList(manager, modifiers), null) { @Override public PsiElement setName(@NotNull String name) throws IncorrectOperationException { DynamicManager.getInstance(getProject()).replaceDynamicPropertyName(containingClassName, getName(), name); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java index e6604706d33b..c1055df8e8c2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java @@ -26,7 +26,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAc import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import javax.swing.*; -import java.util.LinkedHashSet; +import java.lang.reflect.Modifier; import java.util.Set; /** @@ -76,14 +76,12 @@ public class GrAccessorMethodImpl extends GrSyntheticMethod implements GrAccesso } protected Set getModifiers() { - LinkedHashSet modifiers = new LinkedHashSet(); - modifiers.add(PsiModifier.PUBLIC); + int modifiers = Modifier.PUBLIC; final PsiModifierList original = myProperty.getModifierList(); assert original != null; - if (original.hasExplicitModifier(PsiModifier.STATIC)) modifiers.add(PsiModifier.STATIC); - if (original.hasExplicitModifier(PsiModifier.ABSTRACT)) modifiers.add(PsiModifier.ABSTRACT); - if (original.hasExplicitModifier(PsiModifier.FINAL)) modifiers.add(PsiModifier.FINAL); - return modifiers; + if (original.hasExplicitModifier(PsiModifier.STATIC)) modifiers |= Modifier.STATIC; + if (original.hasExplicitModifier(PsiModifier.FINAL)) modifiers |= Modifier.FINAL; + return LightModifierList.getModifierSet(modifiers); } public PsiClass getContainingClass() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrGdkMethodImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrGdkMethodImpl.java index 0f089efc682f..1a972fdacb0c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrGdkMethodImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrGdkMethodImpl.java @@ -34,7 +34,7 @@ import org.jetbrains.plugins.groovy.GroovyIcons; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import javax.swing.*; -import java.util.LinkedHashSet; +import java.lang.reflect.Modifier; /** * @author ven @@ -60,10 +60,7 @@ public class GrGdkMethodImpl extends LightMethod implements GrGdkMethod { super(method.getManager(), method, null); myMethod = method; final PsiManager manager = method.getManager(); - LinkedHashSet modifiers = new LinkedHashSet(); - modifiers.add(PsiModifier.PUBLIC); - if (isStatic) modifiers.add(PsiModifier.STATIC); - myModifierList = new LightModifierList(manager, modifiers); + myModifierList = new LightModifierList(manager, Modifier.PUBLIC + (isStatic ? Modifier.STATIC : 0)); final PsiParameter[] originalParameters = method.getParameterList().getParameters(); final String[] parmNames = new String[originalParameters.length - 1]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticMethodImplementation.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticMethodImplementation.java index 16aba59e2cea..03692e178c1c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticMethodImplementation.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticMethodImplementation.java @@ -23,7 +23,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.plugins.groovy.GroovyIcons; import javax.swing.*; -import java.util.Collections; +import java.lang.reflect.Modifier; import java.util.Set; /** @@ -48,7 +48,7 @@ public class GrSyntheticMethodImplementation extends GrSyntheticMethod { } protected Set getModifiers() { - return Collections.singleton(PsiModifier.PUBLIC); + return LightModifierList.getModifierSet(Modifier.PUBLIC); } public PsiElement copy() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java index 6fd3f712991d..fe412cb13b55 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java @@ -18,24 +18,88 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightElement; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.GroovyFileType; -import java.util.Iterator; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; /** * @author ven */ public class LightModifierList extends LightElement implements PsiModifierList { + private static final Set[] SET_INSTANCES = new Set[8 * 4]; + + private static final String[] VISABILITY_MODIFIERS = {null, PsiModifier.PUBLIC, PsiModifier.PRIVATE, PsiModifier.PROTECTED}; + + private static final int[] MODIFIER_MAP = {0, 1, 2, -1, 3, -1, -1, -1, -1}; + + static { + SET_INSTANCES[0] = Collections.emptySet(); + for (int i = 1; i < 4; i++) { + SET_INSTANCES[i << 3] = Collections.singleton(VISABILITY_MODIFIERS[i]); + } + + for (int i = 1; i < 8; i++) { + int attr = i << 3; + + Set set = new LinkedHashSet(); + if ((attr & Modifier.STATIC) != 0) set.add(PsiModifier.STATIC); + if ((attr & Modifier.FINAL) != 0) set.add(PsiModifier.FINAL); + if ((attr & (4 << 3)) != 0) set.add(PsiModifier.ABSTRACT); + + if (set.size() == 1) set = Collections.singleton(set.iterator().next()); + + SET_INSTANCES[i] = set; + + for (int k = 1; k < 4; k++) { + Set setWithModifier = new LinkedHashSet(); + setWithModifier.add(VISABILITY_MODIFIERS[k]); + setWithModifier.addAll(set); + assert setWithModifier.size() > 1; + + SET_INSTANCES[(k << 3) + i] = setWithModifier; + } + } + } + private final Set myModifiers; + public LightModifierList(PsiManager manager, int modifiers) { + this(manager, getModifierSet(modifiers)); + } + public LightModifierList(PsiManager manager, Set modifiers) { super(manager, GroovyFileType.GROOVY_LANGUAGE); myModifiers = modifiers; } + public static Set getModifierSet(int modifiers) { + assert (modifiers & ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.FINAL | Modifier.ABSTRACT | Modifier.STATIC)) == 0; + + if ((modifiers & Modifier.ABSTRACT) != 0) { + modifiers = (modifiers & ~Modifier.ABSTRACT) | (1 << 5); + } + + int visabilityModifierIndex = MODIFIER_MAP[modifiers & 3]; + if (visabilityModifierIndex != -1) { + return SET_INSTANCES[(modifiers >> 3) + (visabilityModifierIndex << 3)]; + } + + Set res = new HashSet(); + if ((modifiers & Modifier.PUBLIC) != 0) res.add(PsiModifier.PUBLIC); + if ((modifiers & Modifier.PRIVATE) != 0) res.add(PsiModifier.PRIVATE); + if ((modifiers & Modifier.PROTECTED) != 0) res.add(PsiModifier.PROTECTED); + + res.addAll(SET_INSTANCES[modifiers >> 3]); + + return res; + } + public boolean hasModifierProperty(@NotNull String name) { return myModifiers.contains(name); } @@ -71,12 +135,16 @@ public class LightModifierList extends LightElement implements PsiModifierList { } public String getText() { - StringBuffer buffer = new StringBuffer(); - for (Iterator it = myModifiers.iterator(); it.hasNext();) { - buffer.append(it.next()); - if (it.hasNext()) buffer.append(" "); + if (myModifiers.size() == 0) return ""; + if (myModifiers.size() == 1) return myModifiers.iterator().next(); + + StringBuilder buffer = new StringBuilder(); + for (String modifier : myModifiers) { + buffer.append(modifier).append(' '); } + buffer.setLength(buffer.length() - 1); + return buffer.toString(); } @@ -87,7 +155,7 @@ public class LightModifierList extends LightElement implements PsiModifierList { } public PsiElement copy() { - return null; + return new LightModifierList(myManager, myModifiers); } public String toString() { From 50c5431492f67857ee4d80a889acdc9678c4ec0b Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 16 Jun 2010 01:35:01 +0400 Subject: [PATCH 59/81] Optimization of LightModifierList. --- .../lang/psi/impl/synthetic/LightModifierList.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java index fe412cb13b55..6d970737a24f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java @@ -81,13 +81,10 @@ public class LightModifierList extends LightElement implements PsiModifierList { public static Set getModifierSet(int modifiers) { assert (modifiers & ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.FINAL | Modifier.ABSTRACT | Modifier.STATIC)) == 0; - if ((modifiers & Modifier.ABSTRACT) != 0) { - modifiers = (modifiers & ~Modifier.ABSTRACT) | (1 << 5); - } - int visabilityModifierIndex = MODIFIER_MAP[modifiers & 3]; + modifiers = ((modifiers >>> 3) & 3) + ((modifiers & Modifier.ABSTRACT) >>> 8); if (visabilityModifierIndex != -1) { - return SET_INSTANCES[(modifiers >> 3) + (visabilityModifierIndex << 3)]; + return SET_INSTANCES[modifiers + (visabilityModifierIndex << 3)]; } Set res = new HashSet(); @@ -95,7 +92,7 @@ public class LightModifierList extends LightElement implements PsiModifierList { if ((modifiers & Modifier.PRIVATE) != 0) res.add(PsiModifier.PRIVATE); if ((modifiers & Modifier.PROTECTED) != 0) res.add(PsiModifier.PROTECTED); - res.addAll(SET_INSTANCES[modifiers >> 3]); + res.addAll(SET_INSTANCES[modifiers]); return res; } From 9ab6b2c72e2f073aabbad8220e1a1344bdd0073b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 Jun 2010 23:36:54 +0400 Subject: [PATCH 60/81] - use terminateCommand only for Stop command execution. - additional checks in debugger manager thread to ensure the only one thread at a time using JDI API --- .../debugger/engine/DebugProcessImpl.java | 14 +++-- .../engine/DebuggerManagerThreadImpl.java | 55 +++++++------------ .../debugger/impl/HotSwapManager.java | 22 ++++---- .../intellij/debugger/impl/InvokeThread.java | 12 ++-- .../debugger/impl/MultiProcessCommand.java | 27 +++------ 5 files changed, 56 insertions(+), 74 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index ce9b2590798a..97eb5afd45a1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -48,6 +48,7 @@ import com.intellij.execution.ExecutionResult; import com.intellij.execution.Executor; import com.intellij.execution.configurations.CommandLineState; import com.intellij.execution.configurations.RemoteConnection; +import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.filters.ExceptionFilter; import com.intellij.execution.filters.TextConsoleBuilder; @@ -1738,11 +1739,14 @@ public abstract class DebugProcessImpl implements DebugProcess { // propagate exception only in case we succeded to obtain execution result, // otherwise it the error is induced by the fact that there is nothing to debug, and there is no need to show // this problem to the user - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ExecutionUtil.handleExecutionError(myProject, state.getRunnerSettings().getRunProfile(), e); - } - }); + final RunProfile runProfile = state.getRunnerSettings().getRunProfile(); + if (runProfile != null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ExecutionUtil.handleExecutionError(myProject, runProfile, e); + } + }); + } } break; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java index 1c46a54fbc32..416d63e8f8ae 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java @@ -99,44 +99,31 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread - * Note: if old thread is working and InterruptedException is not thrown - * command will continue execution in old thread simulteniously with - * commands in new thread - *

    - * use very carefully! - */ - - public void terminateCommand(final DebuggerCommandImpl command) { - if (command == myEvents.getCurrentEvent()) { - getCurrentRequest().interrupt(); - try { - getCurrentRequest().join(RESTART_TIMEOUT); - } - catch (Exception e) { - throw new RuntimeException(e); - } - startNewWorkerThread(); + }, terminateTimeout); } } - public DebuggerCommandImpl getCurrentCommand() { - return myEvents.getCurrentEvent(); - } - public void processEvent(@NotNull DebuggerCommandImpl managerCommand) { assertIsManagerThread(); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java index f7289ea7ad7e..647c6e9f6054 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java @@ -36,7 +36,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -132,18 +131,18 @@ public class HotSwapManager extends AbstractProjectComponent { swapProgress.setCancelWorker(new Runnable() { public void run() { - scanClassesCommand.terminate(); + scanClassesCommand.cancel(); } }); - for (Iterator iterator = sessions.iterator(); iterator.hasNext();) { - final DebuggerSession debuggerSession = iterator.next(); - if(debuggerSession.isAttached()) { + for (final DebuggerSession debuggerSession : sessions) { + if (debuggerSession.isAttached()) { scanClassesCommand.addCommand(debuggerSession.getProcess(), new DebuggerCommandImpl() { protected void action() throws Exception { swapProgress.setDebuggerSession(debuggerSession); - HashMap sessionClasses = getInstance(swapProgress.getProject()).getModifiedClasses(debuggerSession, swapProgress); - if(!sessionClasses.isEmpty()) { + HashMap sessionClasses = + getInstance(swapProgress.getProject()).getModifiedClasses(debuggerSession, swapProgress); + if (!sessionClasses.isEmpty()) { modifiedClasses.put(debuggerSession, sessionClasses); } } @@ -162,16 +161,17 @@ public class HotSwapManager extends AbstractProjectComponent { reloadClassesProgress.setCancelWorker(new Runnable() { public void run() { - reloadClassesCommand.terminate(); + reloadClassesCommand.cancel(); } }); - for (Iterator iterator = modifiedClasses.keySet().iterator(); iterator.hasNext();) { - final DebuggerSession debuggerSession = iterator.next(); + for (final DebuggerSession debuggerSession : modifiedClasses.keySet()) { reloadClassesCommand.addCommand(debuggerSession.getProcess(), new DebuggerCommandImpl() { protected void action() throws Exception { reloadClassesProgress.setDebuggerSession(debuggerSession); - getInstance(reloadClassesProgress.getProject()).reloadClasses(debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress); + getInstance(reloadClassesProgress.getProject()).reloadClasses( + debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress + ); } }); } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java b/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java index 6848a3f3450b..5faf11a1f930 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java @@ -121,15 +121,19 @@ public abstract class InvokeThread { workerRequest.setRequestFuture( ApplicationManager.getApplication().executeOnPooledThread(workerRequest) ); } - public void run(WorkerThreadRequest current) { + public void run(WorkerThreadRequest threadRequest) { while(true) { try { - if(current.isInterrupted()) { + if(threadRequest.isInterrupted()) { break; } - if(getCurrentRequest() != current) { - LOG.error("Expected " + current + " instead of " + getCurrentRequest()); + final WorkerThreadRequest currentRequest = getCurrentRequest(); + if(currentRequest != threadRequest) { + LOG.error("Expected " + threadRequest + " instead of " + currentRequest); + if (currentRequest != null && !currentRequest.isDone()) { + continue; // ensure events are processed by one thread at a time + } } processEvent(myEvents.get()); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java b/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java index 3c9f55966f96..ea3d4799fd7c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/MultiProcessCommand.java @@ -15,44 +15,31 @@ */ package com.intellij.debugger.impl; -import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; -import com.intellij.debugger.engine.managerThread.DebuggerCommand; import com.intellij.openapi.util.Pair; -import java.util.List; import java.util.ArrayList; -import java.util.Iterator; +import java.util.List; public class MultiProcessCommand implements Runnable{ private final List> myCommands = new ArrayList>(); public void run() { - for(;;) { + while(true) { Pair pair; - synchronized(myCommands) { - if(myCommands.isEmpty()) break; - - pair = myCommands.get(0); + if(myCommands.isEmpty()) { + break; + } + pair = myCommands.remove(0); } - pair.getFirst().getManagerThread().invokeAndWait(pair.getSecond()); - - synchronized(myCommands) { - if(myCommands.isEmpty()) break; - - myCommands.remove(0); - } } } - public void terminate() { + public void cancel() { synchronized(myCommands) { - if(myCommands.isEmpty()) return; - Pair pair = myCommands.get(0); - pair.getFirst().getManagerThread().terminateCommand(pair.getSecond()); myCommands.clear(); } } From d06f023c577a2b04d8f632d35bdf1b5041d92f0b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 16 Jun 2010 09:27:52 +0400 Subject: [PATCH 61/81] logging --- .../compiler/impl/TranslatingCompilerFilesMonitor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java index cfcbcca74353..e299e40d5f54 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java @@ -46,7 +46,6 @@ import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.newvfs.FileAttribute; import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; -import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile; import com.intellij.openapi.vfs.newvfs.persistent.FSRecords; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; import com.intellij.util.containers.SLRUCache; @@ -172,6 +171,9 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { while (scopeSrcIterator.hasNext()) { final VirtualFile file = scopeSrcIterator.next(); if (!file.isValid()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Skipping invalid file " + file.getPresentableUrl()); + } continue; } final int fileId = getFileId(file); From 45c91b9b44ac93e25a8dde84401d178cbf27fd12 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 11 Jun 2010 16:10:42 +0400 Subject: [PATCH 62/81] run tests once: ignore suites if all mentioned tests would run anyway (IDEA-17950) --- .../intellij/junit3/TestAllInPackage2.java | 24 ++++++++++- .../src/com/intellij/junit4/IdeaSuite.java | 41 ++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/plugins/junit_rt/src/com/intellij/junit3/TestAllInPackage2.java b/plugins/junit_rt/src/com/intellij/junit3/TestAllInPackage2.java index bd884ef0e220..8c83eb729a28 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/TestAllInPackage2.java +++ b/plugins/junit_rt/src/com/intellij/junit3/TestAllInPackage2.java @@ -18,15 +18,20 @@ package com.intellij.junit3; import junit.framework.Test; import junit.framework.TestSuite; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + public class TestAllInPackage2 extends TestSuite { public TestAllInPackage2(JUnit3IdeaTestRunner runner, final String name, String[] classMethodNames) { super(name); int testClassCount = 0; - + final Set allNames = new HashSet(Arrays.asList(classMethodNames)); for (int i = 0; i < classMethodNames.length; i++) { String classMethodName = classMethodNames[i]; Test suite = TestRunnerUtil.createClassOrMethodSuite(runner, classMethodName); if (suite != null) { + if (skipSuite(allNames, suite)) continue; if (suite instanceof TestSuite && ((TestSuite)suite).getName() == null) { attachSuiteInfo(suite, classMethodName); } @@ -38,6 +43,23 @@ public class TestAllInPackage2 extends TestSuite { System.out.println(message); } + private static boolean skipSuite(Set allNames, Test suite) { + if (suite instanceof TestRunnerUtil.SuiteMethodWrapper) { + final Test test = ((TestRunnerUtil.SuiteMethodWrapper)suite).getSuite(); + if (test instanceof TestSuite) { + boolean hasAllComponents = true; + for (int idx = 0; idx < ((TestSuite)test).testCount(); idx++) { + if (!allNames.contains(((TestSuite)test).testAt(idx).toString())) { + hasAllComponents = false; + break; + } + } + if (hasAllComponents) return true; + } + } + return false; + } + private static void attachSuiteInfo(Test test, String name) { if (test instanceof TestSuite) { TestSuite testSuite = (TestSuite)test; diff --git a/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java index 81380653ff0b..f38d7520f415 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java +++ b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java @@ -28,7 +28,10 @@ import org.junit.runners.model.InitializationError; import org.junit.runners.model.RunnerBuilder; import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import java.util.Set; class IdeaSuite extends Suite { private final String myName; @@ -54,4 +57,40 @@ class IdeaSuite extends Suite { } return description; } -} \ No newline at end of file + + protected List getChildren() { + final List children = super.getChildren(); + final Set allNames = new HashSet(); + for (Iterator iterator = children.iterator(); iterator.hasNext();) { + final Object child = iterator.next(); + allNames.add(((Runner)child).getDescription().getDisplayName()); + } + for (Iterator iterator = children.iterator(); iterator.hasNext();) { + final Object child = iterator.next(); + if (child instanceof Suite && skipSuite(allNames, child)) { + iterator.remove(); + } + } + + return children; + } + + private static boolean skipSuite(Set allNames, Object child) { + boolean hasRun = true; + try { + final Method getChildrenMethod = Suite.class.getDeclaredMethod("getChildren", new Class[0]); + getChildrenMethod.setAccessible(true); + final List tests = (List)getChildrenMethod.invoke(child, new Object[0]); + for (Iterator suiteIterator = tests.iterator(); suiteIterator.hasNext();) { + if (!allNames.contains(((Runner)suiteIterator.next()).getDescription().getDisplayName())) { + hasRun = false; + break; + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + return hasRun; + } +} From bfc75928b958bacc01b4170d66e2b3b7ab7825a7 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 11 Jun 2010 16:50:54 +0400 Subject: [PATCH 63/81] NPE: check raw substitution during inline --- .../intellij/refactoring/util/InlineUtil.java | 3 +++ .../inlineMethod/RawSubstitution.java | 16 ++++++++++++++++ .../inlineMethod/RawSubstitution.java.after | 15 +++++++++++++++ .../refactoring/inline/InlineMethodTest.java | 4 ++++ 4 files changed, 38 insertions(+) create mode 100644 java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java create mode 100644 java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java index 6fd5ff28eedf..a79be5cf89d4 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java @@ -289,6 +289,9 @@ public class InlineUtil { PsiElement resolved = resolveResult.getElement(); if (resolved instanceof PsiTypeParameter) { PsiType newType = resolveResult.getSubstitutor().putAll(substitutor).substitute((PsiTypeParameter)resolved); + if (newType == null) { + newType = PsiType.getJavaLangObject(resolved.getManager(), resolved.getResolveScope()); + } try { typeElement.replace(factory.createTypeElement(newType)); return; diff --git a/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java b/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java new file mode 100644 index 000000000000..6e7f02ba0686 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java @@ -0,0 +1,16 @@ +public class NotRaw { + T get(T t){ + T tt = t; + if ( t == null) { + return null; + } else + return null; + } + +} + +class Raw extends NotRaw { + void foo() { + Object o = get(null); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java.after b/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java.after new file mode 100644 index 000000000000..3bdbc002fb30 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/RawSubstitution.java.after @@ -0,0 +1,15 @@ +public class NotRaw { + +} + +class Raw extends NotRaw { + void foo() { + Object result; + Object tt = null; + if ( null == null) { + result = null; + } else + result = null; + Object o = result; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java index 650c7a70b987..6712233eab3a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java @@ -153,6 +153,10 @@ public class InlineMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testRawSubstitution() throws Exception { + doTest(); + } + @Override protected Sdk getProjectJDK() { return JavaSdkImpl.getMockJdk15("java 1.5"); From 0e64a2a4c0ece09418552af48ad959ad89086d9e Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 11 Jun 2010 17:14:11 +0400 Subject: [PATCH 64/81] junit assumtions: mark as ignored, show exceptions (IDEA-55560) --- .../src/com/intellij/junit4/JUnit4TestResultsSender.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java index 0f44c1d8d67e..ee41bad6d5a4 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java @@ -54,6 +54,12 @@ public class JUnit4TestResultsSender extends RunListener { } } + public void testAssumptionFailure(Failure failure) { + final Description description = failure.getDescription(); + stopMeter(description); + prepareIgnoredPacket(description, null).addThrowable(failure.getException()).send(); + } + public synchronized void testIgnored(Description description) throws Exception { String val = null; try { From b0746d4f834f8728e6af51fef8035d82cdaa6b28 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 11 Jun 2010 19:14:32 +0400 Subject: [PATCH 65/81] junit: tests by pattern --- .../execution/junit/JUnitConfiguration.java | 19 ++- .../intellij/execution/junit/TestObject.java | 3 + .../intellij/execution/junit/TestPackage.java | 23 ++-- .../execution/junit/TestsPattern.java | 114 ++++++++++++++++++ .../configuration/JUnitConfigurable.form | 25 +++- .../configuration/JUnitConfigurable.java | 24 +++- .../JUnitConfigurationModel.java | 15 ++- 7 files changed, 198 insertions(+), 25 deletions(-) create mode 100644 plugins/junit/src/com/intellij/execution/junit/TestsPattern.java diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 7ff5eef4de54..1b35293cc125 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -55,6 +55,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration getValidModules() { - if (TEST_PACKAGE.equals(myData.TEST_OBJECT)) { + if (TEST_PACKAGE.equals(myData.TEST_OBJECT) || TEST_PATTERN.equals(myData.TEST_OBJECT)) { return Arrays.asList(ModuleManager.getInstance(getProject()).getModules()); } try { @@ -222,7 +223,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration - + @@ -56,6 +56,14 @@ + + + + + + + + @@ -99,7 +107,7 @@ - + @@ -118,10 +126,21 @@ + + + + + + + + + + + - + diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 7875537e6f70..eda304163546 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -55,8 +55,10 @@ public class JUnitConfigurable extends SettingsEditor { private JRadioButton myAllInPackageButton; private JRadioButton myClassButton; private JRadioButton myTestMethodButton; + private JRadioButton myTestPatternButton; private JComponent myPackagePanel; private LabeledComponent myPackage; + private LabeledComponent myPattern; private LabeledComponent myClass; private LabeledComponent myMethod; @@ -71,11 +73,12 @@ public class JUnitConfigurable extends SettingsEditor { private static final ArrayList ourEnabledFields = new ArrayList(Arrays.asList(new TIntArrayList[]{ new TIntArrayList(new int[]{0}), new TIntArrayList(new int[]{1}), - new TIntArrayList(new int[]{1, 2}) + new TIntArrayList(new int[]{1, 2}), + new TIntArrayList(new int[]{3}) })); private final ConfigurationModuleSelector myModuleSelector; - private final JRadioButton[] myRadioButtons = new JRadioButton[3]; - private final LabeledComponent[] myTestLocations = new LabeledComponent[3]; + private final JRadioButton[] myRadioButtons = new JRadioButton[4]; + private final LabeledComponent[] myTestLocations = new LabeledComponent[4]; private final JUnitConfigurationModel myModel; private final BrowseModuleValueActionListener[] myBrowsers; @@ -92,15 +95,18 @@ public class JUnitConfigurable extends SettingsEditor { myBrowsers = new BrowseModuleValueActionListener[]{ new PackageChooserActionListener(project), new TestClassBrowser(project), - new MethodBrowser(project) + new MethodBrowser(project), + new PackageChooserActionListener(project) //todo }; // Garbage support myRadioButtons[JUnitConfigurationModel.ALL_IN_PACKAGE] = myAllInPackageButton; myRadioButtons[JUnitConfigurationModel.CLASS] = myClassButton; myRadioButtons[JUnitConfigurationModel.METHOD] = myTestMethodButton; + myRadioButtons[JUnitConfigurationModel.PATTERN] = myTestPatternButton; myTestLocations[JUnitConfigurationModel.ALL_IN_PACKAGE] = myPackage; myTestLocations[JUnitConfigurationModel.CLASS] = myClass; myTestLocations[JUnitConfigurationModel.METHOD] = myMethod; + myTestLocations[JUnitConfigurationModel.PATTERN] = myPattern; // Done myModel.setListener(this); @@ -170,6 +176,8 @@ public class JUnitConfigurable extends SettingsEditor { private void changePanel () { if (myAllInPackageButton.isSelected()) { myPackagePanel.setVisible(true); + myPackage.setVisible(true); + myPattern.setVisible(false); myClass.setVisible(false); myMethod.setVisible(false); } @@ -178,10 +186,16 @@ public class JUnitConfigurable extends SettingsEditor { myClass.setVisible(true); myMethod.setVisible(false); } - else { + else if (myTestMethodButton.isSelected()){ myPackagePanel.setVisible(false); myClass.setVisible(true); myMethod.setVisible(true); + } else { + myPackagePanel.setVisible(true); + myPattern.setVisible(true); + myPackage.setVisible(false); + myClass.setVisible(false); + myMethod.setVisible(false); } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java index e744fdc2ecd5..9479fa9d2dcc 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java @@ -35,16 +35,17 @@ public class JUnitConfigurationModel { public static final int ALL_IN_PACKAGE = 0; public static final int CLASS = 1; public static final int METHOD = 2; + public static final int PATTERN = 3; private static final List ourTestObjects; static { - ourTestObjects = Arrays.asList(JUnitConfiguration.TEST_PACKAGE, JUnitConfiguration.TEST_CLASS, JUnitConfiguration.TEST_METHOD); + ourTestObjects = Arrays.asList(JUnitConfiguration.TEST_PACKAGE, JUnitConfiguration.TEST_CLASS, JUnitConfiguration.TEST_METHOD, JUnitConfiguration.TEST_PATTERN); } private JUnitConfigurable myListener; private int myType = -1; - private final Document[] myJUnitDocuments = new Document[3]; + private final Document[] myJUnitDocuments = new Document[4]; private final Project myProject; public JUnitConfigurationModel(final Project project) { @@ -81,7 +82,7 @@ public class JUnitConfigurationModel { final String testObject = getTestObject(); final String className = getJUnitTextValue(CLASS); data.TEST_OBJECT = testObject; - if (testObject != JUnitConfiguration.TEST_PACKAGE) { + if (testObject != JUnitConfiguration.TEST_PACKAGE && testObject != JUnitConfiguration.TEST_PATTERN) { final PsiClass testClass = JUnitUtil.findPsiClass(className, module, myProject); data.METHOD_NAME = getJUnitTextValue(METHOD); if (testClass != null && testClass.isValid()) { @@ -92,7 +93,12 @@ public class JUnitConfigurationModel { } } else { - data.PACKAGE_NAME = getJUnitTextValue(ALL_IN_PACKAGE); + if (testObject == JUnitConfiguration.TEST_PACKAGE) { + data.PACKAGE_NAME = getJUnitTextValue(ALL_IN_PACKAGE); + } + else { + data.PATTERN = getJUnitTextValue(PATTERN); + } data.MAIN_CLASS_NAME = ""; data.METHOD_NAME = ""; } @@ -122,6 +128,7 @@ public class JUnitConfigurationModel { setJUnitTextValue(ALL_IN_PACKAGE, data.getPackageName()); setJUnitTextValue(CLASS, data.getMainClassName()); setJUnitTextValue(METHOD, data.getMethodName()); + setJUnitTextValue(PATTERN, data.getPattern()); } private void setJUnitTextValue(final int index, final String text) { From bb1f832d5bf8a16a6573eaece7bc134d97768c7b Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 11 Jun 2010 22:31:08 +0400 Subject: [PATCH 66/81] junit assumptions: mark as ignored, show exceptions (IDEA-55560) --- .../intellij/execution/junit2/states/IgnoredState.java | 10 ++++++++++ .../com/intellij/junit4/JUnit4TestResultsSender.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/junit/src/com/intellij/execution/junit2/states/IgnoredState.java b/plugins/junit/src/com/intellij/execution/junit2/states/IgnoredState.java index b79fa97f3cab..fba1b82b200c 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/states/IgnoredState.java +++ b/plugins/junit/src/com/intellij/execution/junit2/states/IgnoredState.java @@ -26,15 +26,25 @@ import com.intellij.execution.ui.ConsoleViewContentType; public class IgnoredState extends ReadableState { private TestProxy myPeformedTest; private String myIgnoredMessage; + private String myMessage; + private String myStackTrace; public void initializeFrom(final ObjectReader reader) { myPeformedTest = reader.readObject(); myIgnoredMessage = reader.readLimitedString(); + myMessage = reader.readLimitedString(); + myStackTrace = reader.readLimitedString(); } public void printOn(final Printer printer) { String parentName = myPeformedTest.getParent() == null ? myPeformedTest.getInfo().getComment() : myPeformedTest.getParent().toString(); String message = ExecutionBundle.message("junit.runing.info.ignored.console.message", parentName, myPeformedTest.getInfo().getName()); printer.print(message + (myIgnoredMessage.length() > 0 ? " (" + myIgnoredMessage + ")": "") + PrintableTestProxy.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT); + if (myMessage.length() > 0) { + printer.print(myMessage + PrintableTestProxy.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT); + } + if (myStackTrace.length() > 0) { + printer.print(myStackTrace + PrintableTestProxy.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT); + } } } diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java index ee41bad6d5a4..943a4272372c 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java @@ -73,7 +73,7 @@ public class JUnit4TestResultsSender extends RunListener { } testStarted(description); stopMeter(description); - prepareIgnoredPacket(description, val).send(); + prepareIgnoredPacket(description, val).addLimitedString("").addLimitedString("").send(); } private void doAddFailure(final Description test, final Throwable assertion) { From 7db7c75c90c3c347ba56a4d0f9a9cc5cb6df23e8 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 13:21:35 +0400 Subject: [PATCH 67/81] junit: tests by pattern - quick start --- .../applet/AppletConfigurationProducer.java | 4 +- .../ApplicationConfigurationProducer.java | 4 +- .../actions/ConfigurationContext.java | 4 +- .../actions/PreferedProducerFind.java | 3 +- .../junit/RuntimeConfigurationProducer.java | 9 +- .../GroovyScriptRunConfigurationProducer.java | 4 +- plugins/junit/src/META-INF/plugin.xml | 1 + .../junit/JUnitConfigurationProducer.java | 10 ++- .../junit/PatternConfigurationProducer.java | 88 +++++++++++++++++++ .../junit/TestClassConfigurationProducer.java | 5 ++ .../execution/junit/TestsPattern.java | 73 +++++++-------- .../rt/execution/junit/JUnitStarter.java | 5 +- .../execution/MavenConfigurationProducer.java | 4 +- .../TestNGConfigurationProducer.java | 5 +- .../xslt/run/XsltConfigurationProducer.java | 4 +- 15 files changed, 158 insertions(+), 65 deletions(-) create mode 100644 plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java diff --git a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurationProducer.java b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurationProducer.java index 4c6706faf070..1c10dbb303b3 100644 --- a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurationProducer.java +++ b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurationProducer.java @@ -103,8 +103,8 @@ public class AppletConfigurationProducer extends JavaRuntimeConfigurationProduce @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { final PsiClass aClass = getAppletClass(location.getPsiElement(), PsiManager.getInstance(location.getProject())); if (aClass != null) { for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurationProducer.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurationProducer.java index e57da79ece4c..8716509e92d4 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurationProducer.java +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurationProducer.java @@ -89,8 +89,8 @@ public class ApplicationConfigurationProducer extends JavaRuntimeConfigurationPr @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { final PsiClass aClass = ApplicationConfigurationType.getMainClass(location.getPsiElement()); if (aClass == null) { return null; diff --git a/platform/lang-api/src/com/intellij/execution/actions/ConfigurationContext.java b/platform/lang-api/src/com/intellij/execution/actions/ConfigurationContext.java index 0ad8680e726b..95ea96eaf73a 100644 --- a/platform/lang-api/src/com/intellij/execution/actions/ConfigurationContext.java +++ b/platform/lang-api/src/com/intellij/execution/actions/ConfigurationContext.java @@ -106,12 +106,12 @@ public class ConfigurationContext { if (producers == null) return null; if (myRuntimeConfiguration != null) { for (RuntimeConfigurationProducer producer : producers) { - final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation); + final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this); if (configuration != null && configuration.getConfiguration() == myRuntimeConfiguration) return configuration; } } for (RuntimeConfigurationProducer producer : producers) { - final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation); + final RunnerAndConfigurationSettings configuration = producer.findExistingConfiguration(myLocation, this); if (configuration != null) return configuration; } return null; diff --git a/platform/lang-api/src/com/intellij/execution/actions/PreferedProducerFind.java b/platform/lang-api/src/com/intellij/execution/actions/PreferedProducerFind.java index 502580dd600f..7725523362d1 100644 --- a/platform/lang-api/src/com/intellij/execution/actions/PreferedProducerFind.java +++ b/platform/lang-api/src/com/intellij/execution/actions/PreferedProducerFind.java @@ -116,7 +116,8 @@ class PreferedProducerFind { @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { if (existingConfigurations.length > 0) { ConfigurationType type = existingConfigurations[0].getType(); if (type instanceof LocatableConfigurationType) { diff --git a/platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java b/platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java index bbf73ecb7854..868e98e222ea 100644 --- a/platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java +++ b/platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java @@ -61,7 +61,7 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea final RunManager runManager = RunManager.getInstance(context.getProject()); final ConfigurationType type = result.myConfiguration.getType(); final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettings(type); - final RunnerAndConfigurationSettings configuration = findExistingByElement(_location, configurations); + final RunnerAndConfigurationSettings configuration = findExistingByElement(_location, configurations, context); if (configuration != null) { result.myConfiguration = configuration; } @@ -72,10 +72,10 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea } @Nullable - public RunnerAndConfigurationSettings findExistingConfiguration(@NotNull Location location) { + public RunnerAndConfigurationSettings findExistingConfiguration(@NotNull Location location, ConfigurationContext context) { final RunManager runManager = RunManager.getInstance(location.getProject()); final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettings(getConfigurationType()); - return findExistingByElement(location, configurations); + return findExistingByElement(location, configurations, context); } public abstract PsiElement getSourceElement(); @@ -89,7 +89,8 @@ public abstract class RuntimeConfigurationProducer implements Comparable, Clonea @Nullable protected RunnerAndConfigurationSettings findExistingByElement(final Location location, - @NotNull final RunnerAndConfigurationSettings[] existingConfigurations) { + @NotNull final RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java index 6c1013a76ae9..afb42702ef6c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfigurationProducer.java @@ -72,8 +72,8 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { final RunConfiguration configuration = existingConfiguration.getConfiguration(); final String path = ((GroovyScriptRunConfiguration)configuration).scriptPath; diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index 86112d0117a0..a386ef27929b 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -22,6 +22,7 @@ + diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java index d6f9134c3dab..1924f5438041 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java @@ -19,7 +19,9 @@ package com.intellij.execution.junit; import com.intellij.execution.Location; import com.intellij.execution.RunManagerEx; import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.impl.RunManagerImpl; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; @@ -43,8 +45,12 @@ public abstract class JUnitConfigurationProducer extends JavaRuntimeConfiguratio @Override protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { + final PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()); + if (elements != null && elements.length > 1) { + return null; + } final Module predefinedModule = ((JUnitConfiguration)((RunManagerImpl)RunManagerEx.getInstanceEx(location.getProject())) .getConfigurationTemplate(getConfigurationFactory()) diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java new file mode 100644 index 000000000000..36dd5e45085f --- /dev/null +++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java @@ -0,0 +1,88 @@ +/* + * 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 com.intellij.execution.junit; + +import com.intellij.execution.Location; +import com.intellij.execution.RunConfigurationExtension; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public class PatternConfigurationProducer extends JUnitConfigurationProducer { + + + private PsiElement[] myElements; + + protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) { + final Project project = location.getProject(); + final PsiElement element = location.getPsiElement(); + final StringBuffer buffer = new StringBuffer(); + myElements = collectPatternElements(context, project, element, buffer); + String pattern = buffer.toString(); + if (pattern == null || pattern.length() == 0) return null; + RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); + final JUnitConfiguration configuration = (JUnitConfiguration)settings.getConfiguration(); + final JUnitConfiguration.Data data = configuration.getPersistentData(); + data.PATTERN = pattern; + data.TEST_OBJECT = JUnitConfiguration.TEST_PATTERN; + data.setScope(setupPackageConfiguration(context, project, configuration, data.getScope())); + configuration.setGeneratedName(); + RunConfigurationExtension.patchCreatedConfiguration(configuration); + return settings; + } + + private PsiElement[] collectPatternElements(ConfigurationContext context, Project project, PsiElement element, StringBuffer buf) { + PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()); + if (elements != null && elements.length > 1) { + for (PsiElement psiElement : elements) { + if (psiElement instanceof PsiClass) { + buf.append (buf.length() > 0 ? "||": "").append(((PsiClass)psiElement).getQualifiedName()); + } + } + return elements; + } + return null; + } + + public PsiElement getSourceElement() { + return myElements[0]; + } + + @Override + protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location, + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { + final StringBuffer buffer = new StringBuffer(); + collectPatternElements(context, context.getProject(), location.getPsiElement(), buffer); + final String pattern = buffer.toString(); + for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { + final JUnitConfiguration unitConfiguration = (JUnitConfiguration)existingConfiguration.getConfiguration(); + final TestObject testobject = unitConfiguration.getTestObject(); + if (testobject instanceof TestsPattern) { + if (Comparing.strEqual(pattern, unitConfiguration.getPersistentData().getPattern())) { + return existingConfiguration; + } + } + } + return null; + } +} diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java index 7e00c2e788c5..fb9bc19a597a 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java @@ -21,6 +21,7 @@ import com.intellij.execution.Location; import com.intellij.execution.RunConfigurationExtension; import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; @@ -33,6 +34,10 @@ public class TestClassConfigurationProducer extends JUnitConfigurationProducer { location = JavaExecutionUtil.stepIntoSingleClass(location); final Project project = location.getProject(); + final PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()); + if (elements != null && elements.length > 1) { + return null; + } myTestClass = JUnitUtil.getTestClass(location); if (myTestClass == null) return null; RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java index 01428343c7fc..410c30196ffc 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java @@ -20,23 +20,23 @@ */ package com.intellij.execution.junit; -import com.intellij.execution.CantRunException; -import com.intellij.execution.configurations.ConfigurationPerRunnerSettings; -import com.intellij.execution.configurations.RunnerSettings; -import com.intellij.execution.configurations.RuntimeConfigurationException; -import com.intellij.execution.configurations.RuntimeConfigurationWarning; -import com.intellij.openapi.module.Module; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.JavaExecutionUtil; +import com.intellij.execution.configurations.*; +import com.intellij.execution.util.JavaParametersUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.listeners.RefactoringElementListener; -import org.jetbrains.annotations.NotNull; +import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; -import java.util.regex.Pattern; +import java.util.Arrays; -public class TestsPattern extends TestPackage { +public class TestsPattern extends TestObject { public TestsPattern(final Project project, final JUnitConfiguration configuration, RunnerSettings runnerSettings, @@ -45,39 +45,28 @@ public class TestsPattern extends TestPackage { } @Override - protected GlobalSearchScope filterScope(JUnitConfiguration.Data data) throws CantRunException { - final Pattern pattern = Pattern.compile(data.getPattern()); + protected void initialize() throws ExecutionException { + super.initialize(); + final JUnitConfiguration.Data data = myConfiguration.getPersistentData(); + RunConfigurationModule module = myConfiguration.getConfigurationModule(); + JavaParametersUtil.configureModule(module, myJavaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS, + myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(myConfiguration.getProject()); - final PsiManager manager = PsiManager.getInstance(myConfiguration.getProject()); - return new GlobalSearchScope() { - @Override - public boolean contains(VirtualFile file) { - if (!file.isDirectory()) { - final PsiFile psiFile = manager.findFile(file); - if (psiFile instanceof PsiClassOwner) { - if (pattern.matcher(((PsiClassOwner)psiFile).getPackageName()).matches()) return true; - } - } - - return false; + final Project project = module.getProject(); + final String[] classNames = data.getPattern().split("\\|\\|"); + boolean isJUnit4 = false; + for (String className : classNames) { + final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); + if (JUnitUtil.isJUnit4TestClass(psiClass)) { + isJUnit4 = true; + break; } - - @Override - public int compare(VirtualFile file1, VirtualFile file2) { - return 0; + } + addClassesListToJavaParameters(Arrays.asList(classNames), new Function() { + public String fun(String className) { + return className; } - - @Override - public boolean isSearchInModuleContent(@NotNull Module aModule) { - return true; - } - - @Override - public boolean isSearchInLibraries() { - return false; - } - }; + }, "", true, isJUnit4); } @Override @@ -108,7 +97,5 @@ public class TestsPattern extends TestPackage { if (data.getPattern().trim().length() == 0) { throw new RuntimeConfigurationWarning("No pattern selected"); } - - } } \ No newline at end of file diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java index 22316b22b124..c1de222c3a96 100644 --- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java +++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java @@ -21,9 +21,9 @@ import junit.textui.TestRunner; import java.io.*; import java.net.InetAddress; -import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Vector; @@ -116,6 +116,9 @@ public class JUnitStarter { result.addElement(arg); } } + if (tempFilePath != null && !args.contains(SOCKET)) { + isJunit4 = isJUnit4(isJunit4, tempFilePath); + } args.removeAllElements(); for (int i = 0; i < result.size(); i++) { String arg = (String)result.get(i); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java index 53f8f2c4c994..4fdabdaf7a98 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java @@ -56,8 +56,8 @@ public class MavenConfigurationProducer extends RuntimeConfigurationProducer{ @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { final MavenRunnerParameters runnerParameters = createBuildParameters(location); for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java index 906820138653..e15daffd987f 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationProducer.java @@ -23,6 +23,7 @@ package com.theoryinpractice.testng.configuration; import com.intellij.execution.Location; import com.intellij.execution.RunManagerEx; import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.junit.JavaRuntimeConfigurationProducerBase; import com.intellij.openapi.module.Module; @@ -39,8 +40,8 @@ public abstract class TestNGConfigurationProducer extends JavaRuntimeConfigurati @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { final Module predefinedModule = ((TestNGConfiguration)((RunManagerImpl)RunManagerEx.getInstanceEx(location.getProject())) .getConfigurationTemplate(getConfigurationFactory()) diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java index 2d4a70cc7615..6d2a14ed3a16 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java @@ -69,8 +69,8 @@ public class XsltConfigurationProducer extends RuntimeConfigurationProducer{ @Override protected RunnerAndConfigurationSettings findExistingByElement(Location location, - @NotNull RunnerAndConfigurationSettings[] existingConfigurations - ) { + @NotNull RunnerAndConfigurationSettings[] existingConfigurations, + ConfigurationContext context) { final XmlFile file = PsiTreeUtil.getParentOfType(location.getPsiElement(), XmlFile.class, false); if (file != null && file.isPhysical() && XsltSupport.isXsltFile(file)) { for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { From a3217386527b21135279a1e844c8a14ad301fedb Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 14:53:17 +0400 Subject: [PATCH 68/81] junit: tests by pattern - add test to existing suite (I) --- plugins/junit/src/META-INF/plugin.xml | 4 + .../junit/AddToTestsPatternAction.java | 133 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index a386ef27929b..cd73531f6743 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -48,5 +48,9 @@ + + + + \ No newline at end of file diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java new file mode 100644 index 000000000000..b41ae4b098c7 --- /dev/null +++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java @@ -0,0 +1,133 @@ +/* + * 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. + */ + +/* + * User: anna + * Date: 15-Jun-2010 + */ +package com.intellij.execution.junit; + +import com.intellij.execution.RunManager; +import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassOwner; +import com.intellij.psi.PsiElement; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.*; + +public class AddToTestsPatternAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + final DataContext dataContext = e.getDataContext(); + final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext); + final Set classes = collectTestClasses(psiElements); + + final String classNames = StringUtil.join(classes, new Function() { + public String fun(PsiClass psiClass) { + return psiClass.getQualifiedName(); + } + }, "||"); + final Project project = PlatformDataKeys.PROJECT.getData(dataContext); + final List patternConfigurations = collectPatternConfigurations(classes, project); + if (patternConfigurations.size() == 1) { + final JUnitConfiguration configuration = patternConfigurations.get(0); + configuration.getPersistentData().PATTERN += (configuration.getPersistentData().PATTERN.length() > 0 ? "||" : "") + classNames; + } else { + JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Choose suite to add", patternConfigurations) { + @Override + public PopupStep onChosen(JUnitConfiguration configuration, boolean finalChoice) { + configuration.getPersistentData().PATTERN += (configuration.getPersistentData().PATTERN.length() > 0 ? "||" : "") + classNames; + return FINAL_CHOICE; + } + + @Override + public Icon getIconFor(JUnitConfiguration configuration) { + return configuration.getIcon(); + } + + @NotNull + @Override + public String getTextFor(JUnitConfiguration value) { + return value.getName(); + } + }).showInBestPositionFor(dataContext); + } + } + + @Override + public void update(AnActionEvent e) { + final Presentation presentation = e.getPresentation(); + presentation.setVisible(false); + final DataContext dataContext = e.getDataContext(); + final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext); + if (psiElements != null) { + final Set foundClasses = collectTestClasses(psiElements); + if (foundClasses.isEmpty()) return; + final Project project = PlatformDataKeys.PROJECT.getData(dataContext); + if (project != null) { + final List foundConfigurations = collectPatternConfigurations(foundClasses, project); + if (!foundConfigurations.isEmpty()) { + presentation.setVisible(true); + if (foundConfigurations.size() == 1) { + presentation.setText(presentation.getText() + ": " + foundConfigurations.get(0).getName()); + } + } + } + } + } + + private static List collectPatternConfigurations(Set foundClasses, Project project) { + final RunConfiguration[] configurations = RunManager.getInstance(project).getConfigurations(JUnitConfigurationType.getInstance()); + final List foundConfigurations = new ArrayList(); + for (RunConfiguration configuration : configurations) { + final JUnitConfiguration.Data data = ((JUnitConfiguration)configuration).getPersistentData(); + if (data.TEST_OBJECT == JUnitConfiguration.TEST_PATTERN) { + if (foundClasses.size() > 1 || data.getPattern().indexOf(foundClasses.iterator().next().getQualifiedName()) < 0 ) { + foundConfigurations.add((JUnitConfiguration)configuration); + } + } + } + return foundConfigurations; + } + + private static Set collectTestClasses(PsiElement[] psiElements) { + final Set foundClasses = new HashSet(); + for (PsiElement psiElement : psiElements) { + if (psiElement instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)psiElement).getClasses(); + for (PsiClass aClass : classes) { + if (JUnitUtil.isTestClass(aClass)) { + foundClasses.add(aClass); + } + } + } else if (psiElement instanceof PsiClass) { + if (JUnitUtil.isTestClass((PsiClass)psiElement)) { + foundClasses.add((PsiClass)psiElement); + } + } + } + return foundClasses; + } +} \ No newline at end of file From fe3eefca818801c41f9db67dde194e409daa8552 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 19:22:58 +0400 Subject: [PATCH 69/81] junit: tests by pattern - tests chooser added --- .../junit/AddToTestsPatternAction.java | 46 ++--- .../execution/junit/JUnitConfiguration.java | 57 +++++-- .../junit/PatternConfigurationProducer.java | 49 ++++-- .../execution/junit/TestClassFilter.java | 2 +- .../execution/junit/TestsPattern.java | 20 ++- .../configuration/JUnitConfigurable.java | 19 ++- .../JUnitConfigurationModel.java | 15 +- .../configuration/TestsConfigDialog.java | 158 ++++++++++++++++++ 8 files changed, 294 insertions(+), 72 deletions(-) create mode 100644 plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java index b41ae4b098c7..af92dfe91a6c 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java +++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java @@ -27,38 +27,36 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassOwner; import com.intellij.psi.PsiElement; -import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; public class AddToTestsPatternAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { final DataContext dataContext = e.getDataContext(); final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext); - final Set classes = collectTestClasses(psiElements); + final Set classes = PatternConfigurationProducer.collectTestClasses(psiElements); - final String classNames = StringUtil.join(classes, new Function() { - public String fun(PsiClass psiClass) { - return psiClass.getQualifiedName(); - } - }, "||"); final Project project = PlatformDataKeys.PROJECT.getData(dataContext); final List patternConfigurations = collectPatternConfigurations(classes, project); if (patternConfigurations.size() == 1) { final JUnitConfiguration configuration = patternConfigurations.get(0); - configuration.getPersistentData().PATTERN += (configuration.getPersistentData().PATTERN.length() > 0 ? "||" : "") + classNames; + for (PsiClass aClass : classes) { + configuration.getPersistentData().getPatterns().put(aClass.getQualifiedName(), Boolean.TRUE); + } } else { JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Choose suite to add", patternConfigurations) { @Override public PopupStep onChosen(JUnitConfiguration configuration, boolean finalChoice) { - configuration.getPersistentData().PATTERN += (configuration.getPersistentData().PATTERN.length() > 0 ? "||" : "") + classNames; + for (PsiClass aClass : classes) { + configuration.getPersistentData().getPatterns().put(aClass.getQualifiedName(), Boolean.TRUE); + } return FINAL_CHOICE; } @@ -83,7 +81,7 @@ public class AddToTestsPatternAction extends AnAction { final DataContext dataContext = e.getDataContext(); final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext); if (psiElements != null) { - final Set foundClasses = collectTestClasses(psiElements); + final Set foundClasses = PatternConfigurationProducer.collectTestClasses(psiElements); if (foundClasses.isEmpty()) return; final Project project = PlatformDataKeys.PROJECT.getData(dataContext); if (project != null) { @@ -91,7 +89,7 @@ public class AddToTestsPatternAction extends AnAction { if (!foundConfigurations.isEmpty()) { presentation.setVisible(true); if (foundConfigurations.size() == 1) { - presentation.setText(presentation.getText() + ": " + foundConfigurations.get(0).getName()); + presentation.setText(presentation.getText() + ": " + foundConfigurations.get(0).getName());//todo } } } @@ -104,7 +102,7 @@ public class AddToTestsPatternAction extends AnAction { for (RunConfiguration configuration : configurations) { final JUnitConfiguration.Data data = ((JUnitConfiguration)configuration).getPersistentData(); if (data.TEST_OBJECT == JUnitConfiguration.TEST_PATTERN) { - if (foundClasses.size() > 1 || data.getPattern().indexOf(foundClasses.iterator().next().getQualifiedName()) < 0 ) { + if (foundClasses.size() > 1 || !data.getPatterns().containsKey(foundClasses.iterator().next().getQualifiedName()) ) { foundConfigurations.add((JUnitConfiguration)configuration); } } @@ -112,22 +110,4 @@ public class AddToTestsPatternAction extends AnAction { return foundConfigurations; } - private static Set collectTestClasses(PsiElement[] psiElements) { - final Set foundClasses = new HashSet(); - for (PsiElement psiElement : psiElements) { - if (psiElement instanceof PsiClassOwner) { - final PsiClass[] classes = ((PsiClassOwner)psiElement).getClasses(); - for (PsiClass aClass : classes) { - if (JUnitUtil.isTestClass(aClass)) { - foundClasses.add(aClass); - } - } - } else if (psiElement instanceof PsiClass) { - if (JUnitUtil.isTestClass((PsiClass)psiElement)) { - foundClasses.add((PsiClass)psiElement); - } - } - } - return foundClasses; - } } \ No newline at end of file diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 1b35293cc125..7a31357a3089 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -36,16 +36,14 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.refactoring.listeners.RefactoringElementListener; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; public class JUnitConfiguration extends ModuleBasedConfiguration implements CommonJavaRunConfigurationParameters, RefactoringListenerProvider { @@ -55,7 +53,13 @@ public class JUnitConfiguration extends ModuleBasedConfiguration tests = new LinkedHashMap(); + for (Object o : patternsElement.getChildren(PATTERN_EL_NAME)) { + Element patternElement = (Element)o; + tests.put(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME), Boolean.valueOf(patternElement.getAttributeValue(ENABLED_ATT_NAME))); + } + myData.setPatterns(tests); + } } public void writeExternal(final Element element) throws WriteExternalException { @@ -287,6 +300,14 @@ public class JUnitConfiguration extends ModuleBasedConfiguration myPattern = new LinkedHashMap(); //iws/ipr compatibility public String ENV_VARIABLES; @@ -329,7 +350,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration getPatterns() { + return myPattern; + } + + public String getPatternPresentation() { + final List enabledTests = new ArrayList(); + for (String pattern : myPattern.keySet()) { + if (myPattern.get(pattern)) { + enabledTests.add(pattern); + } + } + return StringUtil.join(enabledTests, "||"); + } + + public void setPatterns(Map pattern) { + myPattern = pattern; } public TestObject getTestObject(final Project project, final JUnitConfiguration configuration) { diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java index 36dd5e45085f..b288ddfc5855 100644 --- a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java @@ -24,9 +24,14 @@ import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassOwner; import com.intellij.psi.PsiElement; +import com.intellij.util.containers.hash.LinkedHashMap; import org.jetbrains.annotations.NotNull; +import java.util.LinkedHashSet; +import java.util.Set; + public class PatternConfigurationProducer extends JUnitConfigurationProducer { @@ -34,15 +39,13 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) { final Project project = location.getProject(); - final PsiElement element = location.getPsiElement(); - final StringBuffer buffer = new StringBuffer(); - myElements = collectPatternElements(context, project, element, buffer); - String pattern = buffer.toString(); - if (pattern == null || pattern.length() == 0) return null; + final LinkedHashMap classes = new LinkedHashMap(); + myElements = collectPatternElements(context, classes); + if (classes.isEmpty()) return null; RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); final JUnitConfiguration configuration = (JUnitConfiguration)settings.getConfiguration(); final JUnitConfiguration.Data data = configuration.getPersistentData(); - data.PATTERN = pattern; + data.getPatterns().putAll(classes); data.TEST_OBJECT = JUnitConfiguration.TEST_PATTERN; data.setScope(setupPackageConfiguration(context, project, configuration, data.getScope())); configuration.setGeneratedName(); @@ -50,13 +53,30 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { return settings; } - private PsiElement[] collectPatternElements(ConfigurationContext context, Project project, PsiElement element, StringBuffer buf) { + static Set collectTestClasses(PsiElement[] psiElements) { + final Set foundClasses = new LinkedHashSet(); + for (PsiElement psiElement : psiElements) { + if (psiElement instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)psiElement).getClasses(); + for (PsiClass aClass : classes) { + if (JUnitUtil.isTestClass(aClass)) { + foundClasses.add(aClass); + } + } + } else if (psiElement instanceof PsiClass) { + if (JUnitUtil.isTestClass((PsiClass)psiElement)) { + foundClasses.add((PsiClass)psiElement); + } + } + } + return foundClasses; + } + + private static PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashMap classes) { PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()); if (elements != null && elements.length > 1) { - for (PsiElement psiElement : elements) { - if (psiElement instanceof PsiClass) { - buf.append (buf.length() > 0 ? "||": "").append(((PsiClass)psiElement).getQualifiedName()); - } + for (PsiClass psiClass : collectTestClasses(elements)) { + classes.put(psiClass.getQualifiedName(), Boolean.TRUE); } return elements; } @@ -71,14 +91,13 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location, @NotNull RunnerAndConfigurationSettings[] existingConfigurations, ConfigurationContext context) { - final StringBuffer buffer = new StringBuffer(); - collectPatternElements(context, context.getProject(), location.getPsiElement(), buffer); - final String pattern = buffer.toString(); + final LinkedHashMap classes = new LinkedHashMap(); + collectPatternElements(context, classes); for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { final JUnitConfiguration unitConfiguration = (JUnitConfiguration)existingConfiguration.getConfiguration(); final TestObject testobject = unitConfiguration.getTestObject(); if (testobject instanceof TestsPattern) { - if (Comparing.strEqual(pattern, unitConfiguration.getPersistentData().getPattern())) { + if (Comparing.equal(classes, unitConfiguration.getPersistentData().getPatterns())) { return existingConfiguration; } } diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java index ece12f555141..143cc718b3d1 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java @@ -46,7 +46,7 @@ public class TestClassFilter implements TreeClassChooser.ClassFilterWithScope { public boolean isAccepted(final PsiClass aClass) { return ConfigurationUtil.PUBLIC_INSTANTIATABLE_CLASS.value(aClass) && - (aClass.isInheritor(myBase, true) || TestUtil.isTestClass(aClass)) + (aClass.isInheritor(myBase, true) || JUnitUtil.isTestClass(aClass)) && !CompilerConfiguration.getInstance(getProject()).isExcludedFromCompilation(PsiUtilBase.getVirtualFile(aClass)) ; } diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java index 410c30196ffc..d5c944cfb862 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java @@ -34,7 +34,7 @@ import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; +import java.util.ArrayList; public class TestsPattern extends TestObject { public TestsPattern(final Project project, @@ -53,16 +53,18 @@ public class TestsPattern extends TestObject { myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null); final Project project = module.getProject(); - final String[] classNames = data.getPattern().split("\\|\\|"); boolean isJUnit4 = false; - for (String className : classNames) { - final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); - if (JUnitUtil.isJUnit4TestClass(psiClass)) { - isJUnit4 = true; - break; + final ArrayList classNames = new ArrayList(); + for (String className : data.getPatterns().keySet()) { + if (data.getPatterns().get(className)) { + classNames.add(className); + final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); + if (JUnitUtil.isJUnit4TestClass(psiClass)) { + isJUnit4 = true; + } } } - addClassesListToJavaParameters(Arrays.asList(classNames), new Function() { + addClassesListToJavaParameters(classNames, new Function() { public String fun(String className) { return className; } @@ -94,7 +96,7 @@ public class TestsPattern extends TestObject { @Override public void checkConfiguration() throws RuntimeConfigurationException { final JUnitConfiguration.Data data = myConfiguration.getPersistentData(); - if (data.getPattern().trim().length() == 0) { + if (data.getPatterns().isEmpty()) { throw new RuntimeConfigurationWarning("No pattern selected"); } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index eda304163546..287023d4ef92 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -96,7 +96,7 @@ public class JUnitConfigurable extends SettingsEditor { new PackageChooserActionListener(project), new TestClassBrowser(project), new MethodBrowser(project), - new PackageChooserActionListener(project) //todo + new TestsChooserActionListener(project) }; // Garbage support myRadioButtons[JUnitConfigurationModel.ALL_IN_PACKAGE] = myAllInPackageButton; @@ -233,6 +233,9 @@ public class JUnitConfigurable extends SettingsEditor { final TIntArrayList enabledFields = ourEnabledFields.get(newType); for (int i = 0; i < myTestLocations.length; i++) getTestLocation(i).setEnabled(enabledFields.contains(i)); + if (newType == JUnitConfigurationModel.PATTERN) { + myPattern.getComponent().getTextField().setEnabled(false); + } if (newType != JUnitConfigurationModel.ALL_IN_PACKAGE) myModule.setEnabled(true); else onScopeChanged(); } @@ -248,6 +251,20 @@ public class JUnitConfigurable extends SettingsEditor { } } + private class TestsChooserActionListener extends BrowseModuleValueActionListener { + public TestsChooserActionListener(final Project project) { + super(project); + } + + protected String showDialog() { + final JUnitConfiguration configurationCopy = new JUnitConfiguration(ExecutionBundle.message("default.junit.configuration.name"), getProject(), JUnitConfigurationType.getInstance().getConfigurationFactories()[0]); + applyEditorTo(configurationCopy); + final TestsConfigDialog dialog = new TestsConfigDialog(myWholePanel, myModel, configurationCopy); + dialog.show(); + return dialog.getPattern(); + } + } + private void onScopeChanged() { myModule.setEnabled(!myWholeProjectScope.isSelected()); } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java index 9479fa9d2dcc..12cb016ef03e 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java @@ -28,6 +28,7 @@ import javax.swing.text.Document; import javax.swing.text.PlainDocument; import java.util.Arrays; import java.util.List; +import java.util.Map; // Author: dyoma @@ -47,6 +48,7 @@ public class JUnitConfigurationModel { private int myType = -1; private final Document[] myJUnitDocuments = new Document[4]; private final Project myProject; + private Map myPatterns; public JUnitConfigurationModel(final Project project) { for (int i = 0; i < myJUnitDocuments.length; i++) myJUnitDocuments[i] = new PlainDocument(); @@ -97,7 +99,7 @@ public class JUnitConfigurationModel { data.PACKAGE_NAME = getJUnitTextValue(ALL_IN_PACKAGE); } else { - data.PATTERN = getJUnitTextValue(PATTERN); + data.setPatterns(myPatterns); } data.MAIN_CLASS_NAME = ""; data.METHOD_NAME = ""; @@ -128,7 +130,8 @@ public class JUnitConfigurationModel { setJUnitTextValue(ALL_IN_PACKAGE, data.getPackageName()); setJUnitTextValue(CLASS, data.getMainClassName()); setJUnitTextValue(METHOD, data.getMethodName()); - setJUnitTextValue(PATTERN, data.getPattern()); + setJUnitTextValue(PATTERN, data.getPatternPresentation()); + setPatterns(data.getPatterns()); } private void setJUnitTextValue(final int index, final String text) { @@ -149,5 +152,13 @@ public class JUnitConfigurationModel { private void setTestType(final String testObject) { setType(ourTestObjects.indexOf(testObject)); } + + public void setPatterns(Map patterns) { + myPatterns = patterns; + } + + public Map getPatterns() { + return myPatterns; + } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java new file mode 100644 index 000000000000..b3262344da13 --- /dev/null +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java @@ -0,0 +1,158 @@ +/* + * 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. + */ + +/* + * User: anna + * Date: 15-Jun-2010 + */ +package com.intellij.execution.junit2.configuration; + +import com.intellij.execution.junit.JUnitConfiguration; +import com.intellij.execution.junit.JUnitUtil; +import com.intellij.execution.junit.TestClassFilter; +import com.intellij.execution.testframework.SourceScope; +import com.intellij.ide.util.TreeClassChooser; +import com.intellij.ide.util.TreeClassChooserFactory; +import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.VerticalFlowLayout; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.ui.OrderPanel; +import org.jetbrains.annotations.NonNls; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class TestsConfigDialog extends DialogWrapper{ + @NonNls private static final String INCLUDE = "Include"; + private final LinkedHashMap myTests; + private final JUnitConfigurationModel myModel; + private final JUnitConfiguration myConfigurationCopy; + private Project myProject; + + protected TestsConfigDialog(Component parent, JUnitConfigurationModel model, JUnitConfiguration configurationCopy) { + super(parent, true); + myModel = model; + myConfigurationCopy = configurationCopy; + myTests = new LinkedHashMap(); + for (Map.Entry entry : model.getPatterns().entrySet()) { + myTests.put(entry.getKey(), entry.getValue()); + } + myProject = configurationCopy.getProject(); + init(); + setTitle("Configure suite tests"); + } + + @Override + protected JComponent createCenterPanel() { + final OrderPanel testsPanel = new OrderPanel(String.class) { + @Override + public boolean isCheckable(String entry) { + return true; + } + + @Override + public boolean isChecked(String entry) { + return myTests.get(entry); + } + + @Override + public void setChecked(String entry, boolean checked) { + myTests.put(entry, checked); + } + + @Override + public String getCheckboxColumnName() { + return INCLUDE; + } + }; + testsPanel.setCheckboxColumnName(INCLUDE); + for (String testName : myTests.keySet()) { + testsPanel.add(testName); + } + final JPanel panel = new JPanel(new BorderLayout()); + panel.add(testsPanel, BorderLayout.CENTER); + final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout()); + final JButton addButton = new JButton(ApplicationBundle.message("button.add")); + addButton.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + try { //todo multiple selection + final SourceScope sourceScope = myConfigurationCopy.getPersistentData().getScope().getSourceScope(myConfigurationCopy); + final GlobalSearchScope searchScope = + sourceScope.getGlobalSearchScope(); + final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject) + .createNoInnerClassesScopeChooser("Choose test", searchScope, TestClassFilter.create(sourceScope, myConfigurationCopy.getConfigurationModule().getModule()), null); + chooser.showDialog(); + final PsiClass selectedClass = chooser.getSelectedClass(); + if (selectedClass != null) { + myTests.put(selectedClass.getQualifiedName(), Boolean.TRUE); + testsPanel.add(selectedClass.getQualifiedName()); + } + } + catch (JUnitUtil.NoJUnitException e1) { + //todo show warning? + } + } + }); + buttonsPanel.add(addButton); + + final JButton removeButton = new JButton(ApplicationBundle.message("button.remove")); + removeButton.setEnabled(false); + testsPanel.getEntryTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + removeButton.setEnabled(testsPanel.getEntryTable().getSelectedRows() != null); + } + }); + removeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final int selectedRow = testsPanel.getEntryTable().getSelectedRow(); + testsPanel.remove(testsPanel.getValueAt(selectedRow)); + } + }); + buttonsPanel.add(removeButton); + + panel.add(buttonsPanel, BorderLayout.EAST); + return panel; + } + + + public String getPattern() { + final List enabledTests = new ArrayList(); + for (String testName : myTests.keySet()) { + if (myTests.get(testName)) { + enabledTests.add(testName); + } + } + return StringUtil.join(enabledTests, "||"); + } + + @Override + protected void doOKAction() { + myModel.setPatterns(myTests); + super.doOKAction(); + } +} \ No newline at end of file From 038d189046e62d8afa7ebe2e608755bc2c3ee3c8 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 20:13:18 +0400 Subject: [PATCH 70/81] junit: tests by pattern - exclude from suite --- plugins/junit/src/META-INF/plugin.xml | 1 + .../execution/junit/ExcludeFromRunAction.java | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index cd73531f6743..960db94f108e 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -40,6 +40,7 @@ + diff --git a/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java b/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java new file mode 100644 index 000000000000..3b5fc223dc86 --- /dev/null +++ b/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +/* + * User: anna + * Date: 15-Jun-2010 + */ +package com.intellij.execution.junit; + +import com.intellij.execution.Location; +import com.intellij.execution.configurations.RuntimeConfiguration; +import com.intellij.execution.testframework.AbstractTestProxy; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; + +import java.util.Map; + +public class ExcludeFromRunAction extends AnAction{ + private static final Logger LOG = Logger.getInstance("#" + ExcludeFromRunAction.class.getName()); + + @Override + public void actionPerformed(AnActionEvent e) { + final DataContext dataContext = e.getDataContext(); + final Project project = PlatformDataKeys.PROJECT.getData(dataContext); + LOG.assertTrue(project != null); + final JUnitConfiguration configuration = (JUnitConfiguration)RuntimeConfiguration.DATA_KEY.getData(dataContext); + LOG.assertTrue(configuration != null); + final Map patterns = configuration.getPersistentData().getPatterns(); + final AbstractTestProxy testProxy = AbstractTestProxy.DATA_KEY.getData(dataContext); + LOG.assertTrue(testProxy != null); + patterns.put(((PsiClass)testProxy.getLocation(project).getPsiElement()).getQualifiedName(), Boolean.FALSE); + } + + @Override + public void update(AnActionEvent e) { + final Presentation presentation = e.getPresentation(); + presentation.setVisible(false); + final DataContext dataContext = e.getDataContext(); + final Project project = PlatformDataKeys.PROJECT.getData(dataContext); + if (project != null) { + final RuntimeConfiguration configuration = RuntimeConfiguration.DATA_KEY.getData(dataContext); + if (configuration instanceof JUnitConfiguration) { + final JUnitConfiguration.Data data = ((JUnitConfiguration)configuration).getPersistentData(); + if (data.TEST_OBJECT == JUnitConfiguration.TEST_PATTERN) { + final AbstractTestProxy testProxy = AbstractTestProxy.DATA_KEY.getData(dataContext); + if (testProxy != null) { + final Location location = testProxy.getLocation(project); + if (location != null) { + final PsiElement psiElement = location.getPsiElement(); + if (psiElement instanceof PsiClass && data.getPatterns().containsKey(((PsiClass)psiElement).getQualifiedName())) { + presentation.setVisible(true); + } + } + } + } + } + } + } +} \ No newline at end of file From 10bc8f2dcbb18371def0e3aa72625c78c1adb9e4 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 20:32:34 +0400 Subject: [PATCH 71/81] junit: tests by pattern - short names --- .../execution/junit/AddToTestsPatternAction.java | 4 +++- .../intellij/execution/junit/JUnitConfiguration.java | 12 ++++++++---- .../junit2/configuration/TestsConfigDialog.java | 11 +---------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java index af92dfe91a6c..ff80fd68499f 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java +++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java @@ -89,7 +89,9 @@ public class AddToTestsPatternAction extends AnAction { if (!foundConfigurations.isEmpty()) { presentation.setVisible(true); if (foundConfigurations.size() == 1) { - presentation.setText(presentation.getText() + ": " + foundConfigurations.get(0).getName());//todo + final String patternPresentation = + JUnitConfiguration.Data.getPatternPresentation(foundConfigurations.get(0).getPersistentData().getPatterns()); + presentation.setText("Add to temp suite: " + patternPresentation); } } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 7a31357a3089..fc7772177df4 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -438,7 +438,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration patterns) { final List enabledTests = new ArrayList(); - for (String pattern : myPattern.keySet()) { - if (myPattern.get(pattern)) { - enabledTests.add(pattern); + for (String pattern : patterns.keySet()) { + if (patterns.get(pattern)) { + enabledTests.add(StringUtil.getShortName(pattern)); } } return StringUtil.join(enabledTests, "||"); diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java index b3262344da13..0b12327431e4 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java @@ -30,7 +30,6 @@ import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.VerticalFlowLayout; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.OrderPanel; @@ -42,9 +41,7 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; public class TestsConfigDialog extends DialogWrapper{ @@ -141,13 +138,7 @@ public class TestsConfigDialog extends DialogWrapper{ public String getPattern() { - final List enabledTests = new ArrayList(); - for (String testName : myTests.keySet()) { - if (myTests.get(testName)) { - enabledTests.add(testName); - } - } - return StringUtil.join(enabledTests, "||"); + return JUnitConfiguration.Data.getPatternPresentation(myTests); } @Override From ca80208e514bb1fb1d02a341b6f5a8e733fa5f63 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 21:27:02 +0400 Subject: [PATCH 72/81] junit: tests by pattern - short names (more) --- .../com/intellij/execution/junit/AddToTestsPatternAction.java | 4 +--- .../src/com/intellij/execution/junit/JUnitConfiguration.java | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java index ff80fd68499f..dfbad982c7ef 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java +++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java @@ -89,9 +89,7 @@ public class AddToTestsPatternAction extends AnAction { if (!foundConfigurations.isEmpty()) { presentation.setVisible(true); if (foundConfigurations.size() == 1) { - final String patternPresentation = - JUnitConfiguration.Data.getPatternPresentation(foundConfigurations.get(0).getPersistentData().getPatterns()); - presentation.setText("Add to temp suite: " + patternPresentation); + presentation.setText("Add to temp suite: " + foundConfigurations.get(0).getName()); } } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index fc7772177df4..29c595f213bc 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -438,7 +438,9 @@ public class JUnitConfiguration extends ModuleBasedConfiguration 1 ? " and " + (size - 1) + " more" : ""); } final String className = JavaExecutionUtil.getPresentableClassName(getMainClassName(), configurationModule); if (TEST_METHOD.equals(TEST_OBJECT)) { From 16373fce7d060e91c50cdffa00f869274f574268 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 21:50:27 +0400 Subject: [PATCH 73/81] junit: tests by pattern - no checkboxes enable/disable tests --- .../junit/AddToTestsPatternAction.java | 6 +- .../execution/junit/ExcludeFromRunAction.java | 7 +- .../execution/junit/JUnitConfiguration.java | 26 ++- .../junit/PatternConfigurationProducer.java | 11 +- .../execution/junit/TestsPattern.java | 12 +- .../configuration/JUnitConfigurable.java | 24 +-- .../JUnitConfigurationModel.java | 21 ++- .../configuration/TestsConfigDialog.java | 149 ------------------ 8 files changed, 49 insertions(+), 207 deletions(-) delete mode 100644 plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java index dfbad982c7ef..59ed8ff39042 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java +++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java @@ -48,14 +48,14 @@ public class AddToTestsPatternAction extends AnAction { if (patternConfigurations.size() == 1) { final JUnitConfiguration configuration = patternConfigurations.get(0); for (PsiClass aClass : classes) { - configuration.getPersistentData().getPatterns().put(aClass.getQualifiedName(), Boolean.TRUE); + configuration.getPersistentData().getPatterns().add(aClass.getQualifiedName()); } } else { JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Choose suite to add", patternConfigurations) { @Override public PopupStep onChosen(JUnitConfiguration configuration, boolean finalChoice) { for (PsiClass aClass : classes) { - configuration.getPersistentData().getPatterns().put(aClass.getQualifiedName(), Boolean.TRUE); + configuration.getPersistentData().getPatterns().add(aClass.getQualifiedName()); } return FINAL_CHOICE; } @@ -102,7 +102,7 @@ public class AddToTestsPatternAction extends AnAction { for (RunConfiguration configuration : configurations) { final JUnitConfiguration.Data data = ((JUnitConfiguration)configuration).getPersistentData(); if (data.TEST_OBJECT == JUnitConfiguration.TEST_PATTERN) { - if (foundClasses.size() > 1 || !data.getPatterns().containsKey(foundClasses.iterator().next().getQualifiedName()) ) { + if (foundClasses.size() > 1 || !data.getPatterns().contains(foundClasses.iterator().next().getQualifiedName()) ) { foundConfigurations.add((JUnitConfiguration)configuration); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java b/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java index 3b5fc223dc86..9b0a22e8237b 100644 --- a/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java +++ b/plugins/junit/src/com/intellij/execution/junit/ExcludeFromRunAction.java @@ -30,6 +30,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import java.util.Map; +import java.util.Set; public class ExcludeFromRunAction extends AnAction{ private static final Logger LOG = Logger.getInstance("#" + ExcludeFromRunAction.class.getName()); @@ -41,10 +42,10 @@ public class ExcludeFromRunAction extends AnAction{ LOG.assertTrue(project != null); final JUnitConfiguration configuration = (JUnitConfiguration)RuntimeConfiguration.DATA_KEY.getData(dataContext); LOG.assertTrue(configuration != null); - final Map patterns = configuration.getPersistentData().getPatterns(); + final Set patterns = configuration.getPersistentData().getPatterns(); final AbstractTestProxy testProxy = AbstractTestProxy.DATA_KEY.getData(dataContext); LOG.assertTrue(testProxy != null); - patterns.put(((PsiClass)testProxy.getLocation(project).getPsiElement()).getQualifiedName(), Boolean.FALSE); + patterns.remove(((PsiClass)testProxy.getLocation(project).getPsiElement()).getQualifiedName()); } @Override @@ -63,7 +64,7 @@ public class ExcludeFromRunAction extends AnAction{ final Location location = testProxy.getLocation(project); if (location != null) { final PsiElement psiElement = location.getPsiElement(); - if (psiElement instanceof PsiClass && data.getPatterns().containsKey(((PsiClass)psiElement).getQualifiedName())) { + if (psiElement instanceof PsiClass && data.getPatterns().contains(((PsiClass)psiElement).getQualifiedName())) { presentation.setVisible(true); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 29c595f213bc..5a2f2f50eed0 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -57,7 +57,6 @@ public class JUnitConfiguration extends ModuleBasedConfiguration tests = new LinkedHashMap(); + final Set tests = new LinkedHashSet(); for (Object o : patternsElement.getChildren(PATTERN_EL_NAME)) { Element patternElement = (Element)o; - tests.put(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME), Boolean.valueOf(patternElement.getAttributeValue(ENABLED_ATT_NAME))); + tests.add(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME)); } myData.setPatterns(tests); } @@ -301,10 +300,9 @@ public class JUnitConfiguration extends ModuleBasedConfiguration myPattern = new LinkedHashMap(); + private Set myPattern = new LinkedHashSet(); //iws/ipr compatibility public String ENV_VARIABLES; @@ -440,7 +438,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration 1 ? " and " + (size - 1) + " more" : ""); + return StringUtil.getShortName(myPattern.iterator().next()) + (size > 1 ? " and " + (size - 1) + " more" : ""); } final String className = JavaExecutionUtil.getPresentableClassName(getMainClassName(), configurationModule); if (TEST_METHOD.equals(TEST_OBJECT)) { @@ -462,25 +460,19 @@ public class JUnitConfiguration extends ModuleBasedConfiguration getPatterns() { + public Set getPatterns() { return myPattern; } public String getPatternPresentation() { - return getPatternPresentation(myPattern); - } - - public static String getPatternPresentation(final Map patterns) { final List enabledTests = new ArrayList(); - for (String pattern : patterns.keySet()) { - if (patterns.get(pattern)) { - enabledTests.add(StringUtil.getShortName(pattern)); - } + for (String pattern : myPattern) { + enabledTests.add(pattern); } return StringUtil.join(enabledTests, "||"); } - public void setPatterns(Map pattern) { + public void setPatterns(Set pattern) { myPattern = pattern; } diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java index b288ddfc5855..0648114b4d96 100644 --- a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java @@ -26,7 +26,6 @@ import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassOwner; import com.intellij.psi.PsiElement; -import com.intellij.util.containers.hash.LinkedHashMap; import org.jetbrains.annotations.NotNull; import java.util.LinkedHashSet; @@ -39,13 +38,13 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) { final Project project = location.getProject(); - final LinkedHashMap classes = new LinkedHashMap(); + final LinkedHashSet classes = new LinkedHashSet(); myElements = collectPatternElements(context, classes); if (classes.isEmpty()) return null; RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); final JUnitConfiguration configuration = (JUnitConfiguration)settings.getConfiguration(); final JUnitConfiguration.Data data = configuration.getPersistentData(); - data.getPatterns().putAll(classes); + data.getPatterns().addAll(classes); data.TEST_OBJECT = JUnitConfiguration.TEST_PATTERN; data.setScope(setupPackageConfiguration(context, project, configuration, data.getScope())); configuration.setGeneratedName(); @@ -72,11 +71,11 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { return foundClasses; } - private static PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashMap classes) { + private static PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashSet classes) { PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(context.getDataContext()); if (elements != null && elements.length > 1) { for (PsiClass psiClass : collectTestClasses(elements)) { - classes.put(psiClass.getQualifiedName(), Boolean.TRUE); + classes.add(psiClass.getQualifiedName()); } return elements; } @@ -91,7 +90,7 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer { protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location, @NotNull RunnerAndConfigurationSettings[] existingConfigurations, ConfigurationContext context) { - final LinkedHashMap classes = new LinkedHashMap(); + final LinkedHashSet classes = new LinkedHashSet(); collectPatternElements(context, classes); for (RunnerAndConfigurationSettings existingConfiguration : existingConfigurations) { final JUnitConfiguration unitConfiguration = (JUnitConfiguration)existingConfiguration.getConfiguration(); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java index d5c944cfb862..cc315f5a10cb 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java @@ -55,13 +55,11 @@ public class TestsPattern extends TestObject { final Project project = module.getProject(); boolean isJUnit4 = false; final ArrayList classNames = new ArrayList(); - for (String className : data.getPatterns().keySet()) { - if (data.getPatterns().get(className)) { - classNames.add(className); - final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); - if (JUnitUtil.isJUnit4TestClass(psiClass)) { - isJUnit4 = true; - } + for (String className : data.getPatterns()) { + classNames.add(className); + final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); + if (JUnitUtil.isJUnit4TestClass(psiClass)) { + isJUnit4 = true; } } addClassesListToJavaParameters(classNames, new Function() { diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 287023d4ef92..70bad34d5930 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -35,9 +35,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.IconLoader; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPackage; +import com.intellij.util.Icons; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; @@ -107,6 +109,7 @@ public class JUnitConfigurable extends SettingsEditor { myTestLocations[JUnitConfigurationModel.CLASS] = myClass; myTestLocations[JUnitConfigurationModel.METHOD] = myMethod; myTestLocations[JUnitConfigurationModel.PATTERN] = myPattern; + myPattern.getComponent().setButtonIcon(Icons.ADD_ICON); // Done myModel.setListener(this); @@ -233,9 +236,6 @@ public class JUnitConfigurable extends SettingsEditor { final TIntArrayList enabledFields = ourEnabledFields.get(newType); for (int i = 0; i < myTestLocations.length; i++) getTestLocation(i).setEnabled(enabledFields.contains(i)); - if (newType == JUnitConfigurationModel.PATTERN) { - myPattern.getComponent().getTextField().setEnabled(false); - } if (newType != JUnitConfigurationModel.ALL_IN_PACKAGE) myModule.setEnabled(true); else onScopeChanged(); } @@ -251,17 +251,21 @@ public class JUnitConfigurable extends SettingsEditor { } } - private class TestsChooserActionListener extends BrowseModuleValueActionListener { + private class TestsChooserActionListener extends TestClassBrowser { public TestsChooserActionListener(final Project project) { super(project); } - protected String showDialog() { - final JUnitConfiguration configurationCopy = new JUnitConfiguration(ExecutionBundle.message("default.junit.configuration.name"), getProject(), JUnitConfigurationType.getInstance().getConfigurationFactories()[0]); - applyEditorTo(configurationCopy); - final TestsConfigDialog dialog = new TestsConfigDialog(myWholePanel, myModel, configurationCopy); - dialog.show(); - return dialog.getPattern(); + @Override + protected void onClassChoosen(PsiClass psiClass) { + final JTextField textField = myPattern.getComponent().getTextField(); + final String text = textField.getText(); + textField.setText(text + (text.length() > 0 ? "||" : "") + psiClass.getQualifiedName()); + } + + @Override + public void actionPerformed(ActionEvent e) { + showDialog(); } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java index 12cb016ef03e..0be0a372a0f1 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java @@ -27,8 +27,8 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; // Author: dyoma @@ -48,7 +48,6 @@ public class JUnitConfigurationModel { private int myType = -1; private final Document[] myJUnitDocuments = new Document[4]; private final Project myProject; - private Map myPatterns; public JUnitConfigurationModel(final Project project) { for (int i = 0; i < myJUnitDocuments.length; i++) myJUnitDocuments[i] = new PlainDocument(); @@ -99,7 +98,14 @@ public class JUnitConfigurationModel { data.PACKAGE_NAME = getJUnitTextValue(ALL_IN_PACKAGE); } else { - data.setPatterns(myPatterns); + final LinkedHashSet set = new LinkedHashSet(); + final String[] patterns = getJUnitTextValue(PATTERN).split("\\|\\|"); + for (String pattern : patterns) { + if (pattern.length() > 0) { + set.add(pattern); + } + } + data.setPatterns(set); } data.MAIN_CLASS_NAME = ""; data.METHOD_NAME = ""; @@ -131,7 +137,6 @@ public class JUnitConfigurationModel { setJUnitTextValue(CLASS, data.getMainClassName()); setJUnitTextValue(METHOD, data.getMethodName()); setJUnitTextValue(PATTERN, data.getPatternPresentation()); - setPatterns(data.getPatterns()); } private void setJUnitTextValue(final int index, final String text) { @@ -152,13 +157,5 @@ public class JUnitConfigurationModel { private void setTestType(final String testObject) { setType(ourTestObjects.indexOf(testObject)); } - - public void setPatterns(Map patterns) { - myPatterns = patterns; - } - - public Map getPatterns() { - return myPatterns; - } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java deleted file mode 100644 index 0b12327431e4..000000000000 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/TestsConfigDialog.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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. - */ - -/* - * User: anna - * Date: 15-Jun-2010 - */ -package com.intellij.execution.junit2.configuration; - -import com.intellij.execution.junit.JUnitConfiguration; -import com.intellij.execution.junit.JUnitUtil; -import com.intellij.execution.junit.TestClassFilter; -import com.intellij.execution.testframework.SourceScope; -import com.intellij.ide.util.TreeClassChooser; -import com.intellij.ide.util.TreeClassChooserFactory; -import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.VerticalFlowLayout; -import com.intellij.psi.PsiClass; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.ui.OrderPanel; -import org.jetbrains.annotations.NonNls; - -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.LinkedHashMap; -import java.util.Map; - -public class TestsConfigDialog extends DialogWrapper{ - @NonNls private static final String INCLUDE = "Include"; - private final LinkedHashMap myTests; - private final JUnitConfigurationModel myModel; - private final JUnitConfiguration myConfigurationCopy; - private Project myProject; - - protected TestsConfigDialog(Component parent, JUnitConfigurationModel model, JUnitConfiguration configurationCopy) { - super(parent, true); - myModel = model; - myConfigurationCopy = configurationCopy; - myTests = new LinkedHashMap(); - for (Map.Entry entry : model.getPatterns().entrySet()) { - myTests.put(entry.getKey(), entry.getValue()); - } - myProject = configurationCopy.getProject(); - init(); - setTitle("Configure suite tests"); - } - - @Override - protected JComponent createCenterPanel() { - final OrderPanel testsPanel = new OrderPanel(String.class) { - @Override - public boolean isCheckable(String entry) { - return true; - } - - @Override - public boolean isChecked(String entry) { - return myTests.get(entry); - } - - @Override - public void setChecked(String entry, boolean checked) { - myTests.put(entry, checked); - } - - @Override - public String getCheckboxColumnName() { - return INCLUDE; - } - }; - testsPanel.setCheckboxColumnName(INCLUDE); - for (String testName : myTests.keySet()) { - testsPanel.add(testName); - } - final JPanel panel = new JPanel(new BorderLayout()); - panel.add(testsPanel, BorderLayout.CENTER); - final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout()); - final JButton addButton = new JButton(ApplicationBundle.message("button.add")); - addButton.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e) { - try { //todo multiple selection - final SourceScope sourceScope = myConfigurationCopy.getPersistentData().getScope().getSourceScope(myConfigurationCopy); - final GlobalSearchScope searchScope = - sourceScope.getGlobalSearchScope(); - final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject) - .createNoInnerClassesScopeChooser("Choose test", searchScope, TestClassFilter.create(sourceScope, myConfigurationCopy.getConfigurationModule().getModule()), null); - chooser.showDialog(); - final PsiClass selectedClass = chooser.getSelectedClass(); - if (selectedClass != null) { - myTests.put(selectedClass.getQualifiedName(), Boolean.TRUE); - testsPanel.add(selectedClass.getQualifiedName()); - } - } - catch (JUnitUtil.NoJUnitException e1) { - //todo show warning? - } - } - }); - buttonsPanel.add(addButton); - - final JButton removeButton = new JButton(ApplicationBundle.message("button.remove")); - removeButton.setEnabled(false); - testsPanel.getEntryTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - removeButton.setEnabled(testsPanel.getEntryTable().getSelectedRows() != null); - } - }); - removeButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final int selectedRow = testsPanel.getEntryTable().getSelectedRow(); - testsPanel.remove(testsPanel.getValueAt(selectedRow)); - } - }); - buttonsPanel.add(removeButton); - - panel.add(buttonsPanel, BorderLayout.EAST); - return panel; - } - - - public String getPattern() { - return JUnitConfiguration.Data.getPatternPresentation(myTests); - } - - @Override - protected void doOKAction() { - myModel.setPatterns(myTests); - super.doOKAction(); - } -} \ No newline at end of file From e4110be5fb2802e58765e2f833559d3a32cb9158 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 22:49:57 +0400 Subject: [PATCH 74/81] NPE --- .../execution/junit/TestsPattern.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java index cc315f5a10cb..c863ab15fa76 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java @@ -35,6 +35,7 @@ import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Set; public class TestsPattern extends TestObject { public TestsPattern(final Project project, @@ -56,10 +57,12 @@ public class TestsPattern extends TestObject { boolean isJUnit4 = false; final ArrayList classNames = new ArrayList(); for (String className : data.getPatterns()) { - classNames.add(className); final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, className, GlobalSearchScope.allScope(project)); - if (JUnitUtil.isJUnit4TestClass(psiClass)) { - isJUnit4 = true; + if (psiClass != null && JUnitUtil.isTestClass(psiClass)) { + classNames.add(className); + if (JUnitUtil.isJUnit4TestClass(psiClass)) { + isJUnit4 = true; + } } } addClassesListToJavaParameters(classNames, new Function() { @@ -94,8 +97,19 @@ public class TestsPattern extends TestObject { @Override public void checkConfiguration() throws RuntimeConfigurationException { final JUnitConfiguration.Data data = myConfiguration.getPersistentData(); - if (data.getPatterns().isEmpty()) { + final Set patterns = data.getPatterns(); + if (patterns.isEmpty()) { throw new RuntimeConfigurationWarning("No pattern selected"); } + final GlobalSearchScope searchScope = data.getScope().getSourceScope(myConfiguration).getGlobalSearchScope(); + for (String pattern : patterns) { + final PsiClass psiClass = JavaExecutionUtil.findMainClass(myConfiguration.getProject(), pattern, searchScope); + if (psiClass == null) { + throw new RuntimeConfigurationWarning("Class " + pattern + " not found"); + } + if (!JUnitUtil.isTestClass(psiClass)) { + throw new RuntimeConfigurationWarning("Class " + pattern + " not a test"); + } + } } } \ No newline at end of file From 6a711b7fd469089fc90db8ea1a34bff32b0058d4 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 15 Jun 2010 22:51:05 +0400 Subject: [PATCH 75/81] junit patterns: row editor --- .../configuration/JUnitConfigurable.form | 2 +- .../configuration/JUnitConfigurable.java | 39 ++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form index 6ca46ffb6114..8ea747cdb9d4 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form @@ -131,7 +131,7 @@ - + diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 70bad34d5930..dfe9baaa737d 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -32,6 +32,7 @@ import com.intellij.ide.util.TreeClassChooser; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.FixedSizeButton; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; @@ -47,6 +48,7 @@ import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.text.Document; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; @@ -60,7 +62,7 @@ public class JUnitConfigurable extends SettingsEditor { private JRadioButton myTestPatternButton; private JComponent myPackagePanel; private LabeledComponent myPackage; - private LabeledComponent myPattern; + private LabeledComponent myPattern; private LabeledComponent myClass; private LabeledComponent myMethod; @@ -71,6 +73,7 @@ public class JUnitConfigurable extends SettingsEditor { private JRadioButton myWholeProjectScope; private JRadioButton mySingleModuleScope; private JRadioButton myModuleWDScope; + private TextFieldWithBrowseButton myPatternTextField; private static final ArrayList ourEnabledFields = new ArrayList(Arrays.asList(new TIntArrayList[]{ new TIntArrayList(new int[]{0}), @@ -108,8 +111,20 @@ public class JUnitConfigurable extends SettingsEditor { myTestLocations[JUnitConfigurationModel.ALL_IN_PACKAGE] = myPackage; myTestLocations[JUnitConfigurationModel.CLASS] = myClass; myTestLocations[JUnitConfigurationModel.METHOD] = myMethod; + final JPanel panel = myPattern.getComponent(); + panel.setLayout(new BorderLayout()); + myPatternTextField = new TextFieldWithBrowseButton(); + myPatternTextField.setButtonIcon(Icons.ADD_ICON); + panel.add(myPatternTextField, BorderLayout.CENTER); + final FixedSizeButton editBtn = new FixedSizeButton(); + editBtn.setIcon(IconLoader.getIcon("/actions/showViewer.png")); + editBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Messages.showTextAreaDialog(myPatternTextField.getTextField(), "Configure suite tests", "EditParametersPopupWindow"); + } + }); + panel.add(editBtn, BorderLayout.EAST); myTestLocations[JUnitConfigurationModel.PATTERN] = myPattern; - myPattern.getComponent().setButtonIcon(Icons.ADD_ICON); // Done myModel.setListener(this); @@ -210,16 +225,22 @@ public class JUnitConfigurable extends SettingsEditor { private void installDocuments() { for (int i = 0; i < myTestLocations.length; i++) { - final LabeledComponent testLocation = getTestLocation(i); - final TextFieldWithBrowseButton field = testLocation.getComponent(); + final LabeledComponent testLocation = getTestLocation(i); + final JComponent component = testLocation.getComponent(); + final TextFieldWithBrowseButton field; + if (component instanceof TextFieldWithBrowseButton) { + field = (TextFieldWithBrowseButton)component; + } else { + field = myPatternTextField; + } final Document document = myModel.getJUnitDocument(i); field.getTextField().setDocument(document); myBrowsers[i].setField(field); } } - public LabeledComponent getTestLocation(final int index) { - return (LabeledComponent)myTestLocations[index]; + public LabeledComponent getTestLocation(final int index) { + return myTestLocations[index]; } private static void addRadioButtonsListeners(final JRadioButton[] radioButtons, ChangeListener listener) { @@ -258,7 +279,7 @@ public class JUnitConfigurable extends SettingsEditor { @Override protected void onClassChoosen(PsiClass psiClass) { - final JTextField textField = myPattern.getComponent().getTextField(); + final JTextField textField = myPatternTextField.getTextField(); final String text = textField.getText(); textField.setText(text + (text.length() > 0 ? "||" : "") + psiClass.getQualifiedName()); } @@ -335,12 +356,12 @@ public class JUnitConfigurable extends SettingsEditor { } private String getClassName() { - return getTestLocation(JUnitConfigurationModel.CLASS).getComponent().getText(); + return ((LabeledComponent)getTestLocation(JUnitConfigurationModel.CLASS).getComponent()).getText(); } private void setPackage(final PsiPackage aPackage) { if (aPackage == null) return; - getTestLocation(JUnitConfigurationModel.ALL_IN_PACKAGE).getComponent().setText(aPackage.getQualifiedName()); + ((LabeledComponent)getTestLocation(JUnitConfigurationModel.ALL_IN_PACKAGE).getComponent()).setText(aPackage.getQualifiedName()); } @NotNull From 0fbec8505197b6876ef9cf8bc3f727544e1ee1cc Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Wed, 16 Jun 2010 12:57:27 +0400 Subject: [PATCH 76/81] Explicitely removing unused listeners in LanguageSelector to prevent memory leaks --- .../options/codeStyle/CodeStyleMainPanel.java | 11 ++++------- .../options/codeStyle/LanguageSelector.java | 4 ++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java index aa63a59a86f2..af3a3b79fd87 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java @@ -30,7 +30,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -public class CodeStyleMainPanel extends JPanel { +public class CodeStyleMainPanel extends JPanel implements LanguageSelectorListener { private final CardLayout myLayout = new CardLayout(); private final JPanel mySettingsPanel = new JPanel(myLayout); @@ -78,11 +78,7 @@ public class CodeStyleMainPanel extends JPanel { } }); - myLangSelector.addListener(new LanguageSelectorListener(){ - public void languageChanged(Language lang) { - onLanguageChange(lang); - } - }); + myLangSelector.addListener(this); addWaitCard(); @@ -206,6 +202,7 @@ public class CodeStyleMainPanel extends JPanel { public void disposeUIResources() { myAlarm.cancelAllRequests(); clearPanels(); + myLangSelector.removeListener(this); } public boolean isModified(final CodeStyleScheme scheme) { @@ -216,7 +213,7 @@ public class CodeStyleMainPanel extends JPanel { return mySettingsPanels.get(scheme.getName()).isModified(); } - private void onLanguageChange(Language lang) { + public void languageChanged(Language lang) { for (NewCodeStyleSettingsPanel panel : mySettingsPanels.values()) { panel.setLanguage(lang); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java index 82603d4bf85f..33341cc17fbd 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/LanguageSelector.java @@ -56,6 +56,10 @@ public class LanguageSelector { myDispatcher.addListener(l); } + public void removeListener(LanguageSelectorListener l) { + myDispatcher.removeListener(l); + } + private void notifyListeners(Language lang) { myDispatcher.getMulticaster().languageChanged(lang); } From e21779668b8642c493b1769d4da24e9eb9de8fb2 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 16 Jun 2010 13:08:53 +0400 Subject: [PATCH 77/81] Optimization of LightModifierList. --- .../psi/impl/synthetic/LightModifierList.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java index 6d970737a24f..49be756098e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightModifierList.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightElement; import com.intellij.util.IncorrectOperationException; @@ -34,14 +35,14 @@ import java.util.Set; public class LightModifierList extends LightElement implements PsiModifierList { private static final Set[] SET_INSTANCES = new Set[8 * 4]; - private static final String[] VISABILITY_MODIFIERS = {null, PsiModifier.PUBLIC, PsiModifier.PRIVATE, PsiModifier.PROTECTED}; + private static final String[] VISIBILITY_MODIFIERS = {null, PsiModifier.PUBLIC, PsiModifier.PRIVATE, PsiModifier.PROTECTED}; private static final int[] MODIFIER_MAP = {0, 1, 2, -1, 3, -1, -1, -1, -1}; static { SET_INSTANCES[0] = Collections.emptySet(); for (int i = 1; i < 4; i++) { - SET_INSTANCES[i << 3] = Collections.singleton(VISABILITY_MODIFIERS[i]); + SET_INSTANCES[i << 3] = Collections.singleton(VISIBILITY_MODIFIERS[i]); } for (int i = 1; i < 8; i++) { @@ -58,7 +59,7 @@ public class LightModifierList extends LightElement implements PsiModifierList { for (int k = 1; k < 4; k++) { Set setWithModifier = new LinkedHashSet(); - setWithModifier.add(VISABILITY_MODIFIERS[k]); + setWithModifier.add(VISIBILITY_MODIFIERS[k]); setWithModifier.addAll(set); assert setWithModifier.size() > 1; @@ -81,10 +82,10 @@ public class LightModifierList extends LightElement implements PsiModifierList { public static Set getModifierSet(int modifiers) { assert (modifiers & ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.FINAL | Modifier.ABSTRACT | Modifier.STATIC)) == 0; - int visabilityModifierIndex = MODIFIER_MAP[modifiers & 3]; + int visibilityModifierIndex = MODIFIER_MAP[modifiers & 3]; modifiers = ((modifiers >>> 3) & 3) + ((modifiers & Modifier.ABSTRACT) >>> 8); - if (visabilityModifierIndex != -1) { - return SET_INSTANCES[modifiers + (visabilityModifierIndex << 3)]; + if (visibilityModifierIndex != -1) { + return SET_INSTANCES[modifiers + (visibilityModifierIndex << 3)]; } Set res = new HashSet(); @@ -135,14 +136,7 @@ public class LightModifierList extends LightElement implements PsiModifierList { if (myModifiers.size() == 0) return ""; if (myModifiers.size() == 1) return myModifiers.iterator().next(); - StringBuilder buffer = new StringBuilder(); - for (String modifier : myModifiers) { - buffer.append(modifier).append(' '); - } - - buffer.setLength(buffer.length() - 1); - - return buffer.toString(); + return StringUtil.join(myModifiers, " "); } public void accept(@NotNull PsiElementVisitor visitor) { From b2daca3789dbae4316a83b49a3b72e105ba92b3e Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 15 Jun 2010 21:40:17 +0400 Subject: [PATCH 78/81] Typo --- .../refactoring/listeners/RefactoringElementListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java index a5b16f7f8056..50609a408e90 100644 --- a/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java +++ b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java @@ -19,7 +19,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; /** - * {@linkplain RefactoringElementListenerProvider} recieves a notifictaion of what happened + * {@linkplain RefactoringElementListenerProvider} receives a notification of what happened * to element it have been observing during a refactoring. * @author dsl */ From 4bc9819752e5a10ff7bf44ea2e04b465c1525c07 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 Jun 2010 14:19:48 +0400 Subject: [PATCH 79/81] Minor optimization (skip duplicate descriptors) --- .../generation/surroundWith/SurroundWithHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java index 7efc9cee5cdb..9bb29ebcde0f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java @@ -37,8 +37,8 @@ import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public class SurroundWithHandler implements CodeInsightActionHandler{ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler"); @@ -77,7 +77,7 @@ public class SurroundWithHandler implements CodeInsightActionHandler{ final Language baseLanguage = file.getViewProvider().getBaseLanguage(); final Language l = element1.getParent().getLanguage(); - List surroundDescriptors = new ArrayList(); + final Set surroundDescriptors = new HashSet(); surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(l)); if (l != baseLanguage) surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(baseLanguage)); From 40cf13824df83e716c37094c6a0d2cffa0a6088b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 Jun 2010 14:21:13 +0400 Subject: [PATCH 80/81] Find statements (to surround) in Java-like languages too --- .../intellij/codeInsight/CodeInsightUtil.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 05f038b3b55a..5e369700c2c5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight; import com.intellij.codeInsight.completion.JavaCompletionUtil; +import com.intellij.lang.Language; import com.intellij.lang.StdLanguages; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; @@ -71,10 +72,11 @@ public class CodeInsightUtil { @NotNull public static PsiElement[] findStatementsInRange(@NotNull PsiFile file, int startOffset, int endOffset) { + Language language = findJavaOrLikeLanguage(file); + if (language == null) return PsiElement.EMPTY_ARRAY; FileViewProvider viewProvider = file.getViewProvider(); - if (!viewProvider.getLanguages().contains(StdLanguages.JAVA)) return PsiElement.EMPTY_ARRAY; - PsiElement element1 = viewProvider.findElementAt(startOffset, StdLanguages.JAVA); - PsiElement element2 = viewProvider.findElementAt(endOffset - 1, StdLanguages.JAVA); + PsiElement element1 = viewProvider.findElementAt(startOffset, language); + PsiElement element2 = viewProvider.findElementAt(endOffset - 1, language); if (element1 instanceof PsiWhiteSpace) { startOffset = element1.getTextRange().getEndOffset(); element1 = file.findElementAt(startOffset); @@ -148,6 +150,18 @@ public class CodeInsightUtil { return array.toArray(new PsiElement[array.size()]); } + @Nullable + public static Language findJavaOrLikeLanguage(@NotNull final PsiFile file) { + final Set languages = file.getViewProvider().getLanguages(); + for (final Language language : languages) { + if (language == StdLanguages.JAVA) return language; + } + for (final Language language : languages) { + if (language.isKindOf(StdLanguages.JAVA)) return language; + } + return null; + } + public static void sortIdenticalShortNameClasses(PsiClass[] classes, @NotNull PsiElement context) { if (classes.length <= 1) return; From 0ba2c27ed7d0a626ce4aa1cc1b52cc6c8eb31588 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 16 Jun 2010 14:31:07 +0400 Subject: [PATCH 81/81] making compiler test output jdk1.6-ready --- .../com/intellij/debugger/impl/DebuggerManagerImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java index 4b574dfa9727..2da2f7f70b1a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java @@ -35,6 +35,7 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ProgramRunner; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsListener; @@ -50,7 +51,6 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.Disposable; import com.intellij.psi.PsiClass; import com.intellij.util.EventDispatcher; import com.intellij.util.Function; @@ -488,10 +488,10 @@ public class DebuggerManagerImpl extends DebuggerManagerEx { return true; } - if (ApplicationManager.getApplication().isUnitTestMode()) { + //if (ApplicationManager.getApplication().isUnitTestMode()) { // need this in unit tests to avoid false alarms when comparing actual output with expected output - return true; - } + //return true; + //} final String version = JdkUtil.getJdkMainAttribute(jdk, Attributes.Name.IMPLEMENTATION_VERSION); return version == null ||