From 5b0a120466c9ef4b1ae514831de8ebcf9cd1d6b1 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 26 Jul 2010 17:43:08 +0400 Subject: [PATCH] scopes: listen rename/move element (IDEA-11534) --- .../scope/packageSet/PatternPackageSet.java | 21 ++- .../psi/PsiQualifiedNamedElement.java | 0 .../packageSet/ComplementPackageSet.java | 4 + .../packageSet/FilePatternPackageSet.java | 18 ++- .../packageSet/IntersectionPackageSet.java | 8 + .../packageSet/PatternBasedPackageSet.java | 27 ++++ .../scope/packageSet/UnionPackageSet.java | 8 + .../RefactoringElementListenerComposite.java | 0 ...factoringScopeElementListenerProvider.java | 144 ++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 1 + 10 files changed, 228 insertions(+), 3 deletions(-) rename {java/openapi => platform/lang-api}/src/com/intellij/psi/PsiQualifiedNamedElement.java (100%) create mode 100644 platform/lang-api/src/com/intellij/psi/search/scope/packageSet/PatternBasedPackageSet.java rename {java/openapi => platform/lang-api}/src/com/intellij/refactoring/listeners/RefactoringElementListenerComposite.java (100%) create mode 100644 platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java diff --git a/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java b/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java index 9bb1209cf342..9631b4f90b0a 100644 --- a/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java +++ b/java/openapi/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java @@ -18,17 +18,18 @@ package com.intellij.psi.search.scope.packageSet; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.*; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.regex.Pattern; -public class PatternPackageSet implements PackageSet { +public class PatternPackageSet implements PatternBasedPackageSet { @NonNls public static final String SCOPE_TEST = "test"; @NonNls public static final String SCOPE_SOURCE = "src"; @NonNls public static final String SCOPE_LIBRARY = "lib"; @@ -136,4 +137,20 @@ public class PatternPackageSet implements PackageSet { return buf.toString(); } + @Override + public String getModulePattern() { + return myModulePatternText; + } + + @Override + public boolean isOn(String oldQName) { + return Comparing.strEqual(oldQName, myAspectJSyntaxPattern) || //class qname + Comparing.strEqual(oldQName + "..*", myAspectJSyntaxPattern) || //package req + Comparing.strEqual(oldQName + ".*", myAspectJSyntaxPattern); //package + } + + @Override + public String getPattern() { + return myAspectJSyntaxPattern; + } } \ No newline at end of file diff --git a/java/openapi/src/com/intellij/psi/PsiQualifiedNamedElement.java b/platform/lang-api/src/com/intellij/psi/PsiQualifiedNamedElement.java similarity index 100% rename from java/openapi/src/com/intellij/psi/PsiQualifiedNamedElement.java rename to platform/lang-api/src/com/intellij/psi/PsiQualifiedNamedElement.java diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/ComplementPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/ComplementPackageSet.java index 010707b85741..f9536b1887f8 100644 --- a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/ComplementPackageSet.java +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/ComplementPackageSet.java @@ -45,4 +45,8 @@ public class ComplementPackageSet implements PackageSet { public int getNodePriority() { return 1; } + + public PackageSet getComplementarySet() { + return myComplementarySet; + } } diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java index 2ad0fe15b41f..b1824bf43a54 100644 --- a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java @@ -26,6 +26,7 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -34,7 +35,7 @@ import org.jetbrains.annotations.NonNls; import java.util.regex.Pattern; -public class FilePatternPackageSet implements PackageSet { +public class FilePatternPackageSet implements PatternBasedPackageSet { public static final @NonNls String SCOPE_FILE = "file"; private Pattern myModulePattern; private Pattern myModuleGroupPattern; @@ -169,6 +170,21 @@ public class FilePatternPackageSet implements PackageSet { return buf.toString(); } + @Override + public String getPattern() { + return myPathPattern; + } + + @Override + public String getModulePattern() { + return myModulePatternText; + } + + @Override + public boolean isOn(String oldQName) { + return Comparing.strEqual(myPathPattern, oldQName); + } + public static String getRelativePath(final VirtualFile virtualFile, final ProjectFileIndex index, final boolean useFQName) { final Module module = index.getModuleForFile(virtualFile); if (module != null) { diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/IntersectionPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/IntersectionPackageSet.java index f9a96d092cfd..11526b528efb 100644 --- a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/IntersectionPackageSet.java +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/IntersectionPackageSet.java @@ -52,4 +52,12 @@ public class IntersectionPackageSet implements PackageSet { return buf.toString(); } + + public PackageSet getFirstSet() { + return myFirstSet; + } + + public PackageSet getSecondSet() { + return mySecondSet; + } } diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/PatternBasedPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/PatternBasedPackageSet.java new file mode 100644 index 000000000000..34aaace526fa --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/PatternBasedPackageSet.java @@ -0,0 +1,27 @@ +/* + * 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.psi.search.scope.packageSet; + +/** + * User: anna + * Date: Jul 26, 2010 + */ +public interface PatternBasedPackageSet extends PackageSet{ + String getPattern(); + String getModulePattern(); + + boolean isOn(String oldQName); +} diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/UnionPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/UnionPackageSet.java index b47609873ccb..8a227836c881 100644 --- a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/UnionPackageSet.java +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/UnionPackageSet.java @@ -42,4 +42,12 @@ public class UnionPackageSet implements PackageSet { public String getText() { return myFirstSet.getText() + "||" + mySecondSet.getText(); } + + public PackageSet getFirstSet() { + return myFirstSet; + } + + public PackageSet getSecondSet() { + return mySecondSet; + } } \ No newline at end of file diff --git a/java/openapi/src/com/intellij/refactoring/listeners/RefactoringElementListenerComposite.java b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListenerComposite.java similarity index 100% rename from java/openapi/src/com/intellij/refactoring/listeners/RefactoringElementListenerComposite.java rename to platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringElementListenerComposite.java diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java new file mode 100644 index 000000000000..505ed9dbb175 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java @@ -0,0 +1,144 @@ +/* + * 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.packageDependencies.ui; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiQualifiedNamedElement; +import com.intellij.psi.search.scope.packageSet.*; +import com.intellij.refactoring.listeners.RefactoringElementListener; +import com.intellij.refactoring.listeners.RefactoringElementListenerComposite; +import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + * Date: Jul 26, 2010 + */ +public class RefactoringScopeElementListenerProvider implements RefactoringElementListenerProvider { + private static final Logger LOG = Logger.getInstance("#" + RefactoringScopeElementListenerProvider.class.getName()); + + @Override + public RefactoringElementListener getListener(PsiElement element) { + final PsiFile containingFile = element.getContainingFile(); + if (!(element instanceof PsiQualifiedNamedElement)) return null; + final String oldName = ((PsiQualifiedNamedElement)element).getQualifiedName(); + RefactoringElementListenerComposite composite = null; + for (final NamedScopesHolder holder : NamedScopeManager.getAllNamedScopeHolders(element.getProject())) { + final NamedScope[] scopes = holder.getEditableScopes(); + for (int i = 0; i < scopes.length; i++) { + final NamedScope scope = scopes[i]; + final PackageSet packageSet = scope.getValue(); + if (packageSet != null && (containingFile == null || packageSet.contains(containingFile, holder))) { + composite = traverse(new OldScopeDescriptor(oldName, scope, i, holder), composite, packageSet); + } + } + } + return composite; + } + + private static RefactoringElementListenerComposite traverse(OldScopeDescriptor scopeDescriptor, + RefactoringElementListenerComposite composite, + PackageSet packageSet) { + if (packageSet instanceof PatternBasedPackageSet) { + composite = checkPatternPackageSet(scopeDescriptor, composite, ((PatternBasedPackageSet)packageSet), + scopeDescriptor.getScope().getValue().getText()); + } + else if (packageSet instanceof ComplementPackageSet) { + composite = traverse(scopeDescriptor, composite, ((ComplementPackageSet)packageSet).getComplementarySet()); + } + else if (packageSet instanceof UnionPackageSet) { + composite = traverse(scopeDescriptor, composite, ((UnionPackageSet)packageSet).getFirstSet()); + composite = traverse(scopeDescriptor, composite, ((UnionPackageSet)packageSet).getSecondSet()); + } + else if (packageSet instanceof IntersectionPackageSet) { + composite = traverse(scopeDescriptor, composite, ((IntersectionPackageSet)packageSet).getFirstSet()); + composite = traverse(scopeDescriptor, composite, ((IntersectionPackageSet)packageSet).getSecondSet()); + } + return composite; + } + + private static RefactoringElementListenerComposite checkPatternPackageSet(final OldScopeDescriptor descriptor, + RefactoringElementListenerComposite composite, + final PatternBasedPackageSet pattern, + final String text) { + if (pattern.isOn(descriptor.getOldQName())) { + if (composite == null) { + composite = new RefactoringElementListenerComposite(); + } + composite.addListener(new RefactoringElementListener() { + @Override + public void elementMoved(@NotNull PsiElement newElement) { + setName(newElement); + } + + @Override + public void elementRenamed(@NotNull PsiElement newElement) { + setName(newElement); + } + + private void setName(@NotNull PsiElement newElement) { + LOG.assertTrue(newElement instanceof PsiQualifiedNamedElement); + try { + final String newPattern = text.replace(descriptor.getOldQName(), ((PsiQualifiedNamedElement)newElement).getQualifiedName()); + final PackageSet newSet = PackageSetFactory.getInstance().compile(newPattern); + NamedScope newScope = new NamedScope(descriptor.getScope().getName(), newSet); + final NamedScope[] currentScopes = descriptor.getHolder().getEditableScopes(); + currentScopes[descriptor.getIdx()] = newScope; + descriptor.getHolder().setScopes(currentScopes); + } + catch (ParsingException ignore) { + } + } + }); + } + return composite; + } + + private static class OldScopeDescriptor { + private final String myOldQName; + private final NamedScopesHolder myHolder; + private final int myIdx; + private final NamedScope myScope; + + private OldScopeDescriptor(final String oldQName, + final NamedScope scope, + final int idx, + final NamedScopesHolder holder) { + myOldQName = oldQName; + myHolder = holder; + myIdx = idx; + myScope = scope; + } + + public String getOldQName() { + return myOldQName; + } + + public NamedScopesHolder getHolder() { + return myHolder; + } + + public int getIdx() { + return myIdx; + } + + public NamedScope getScope() { + return myScope; + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 21b6000930ab..49b97ae80a36 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -296,6 +296,7 @@ +