From 33c9e16209ccdcbd17ae3ce8144138e8c1e8d247 Mon Sep 17 00:00:00 2001 From: Sergey Stupin Date: Fri, 27 Dec 2019 18:27:55 +0100 Subject: [PATCH] LAB-31 RenameUtil independent of TextOccurrencesUtil (less coupling with lang module) GitOrigin-RevId: b9384cf5c9e2df28cf5b7abd01cdc9caf377fe1a --- .../util/TextOccurrencesUtilBase.java | 121 ++++++++++++++++++ .../refactoring/rename/RenameUtil.java | 6 +- .../refactoring/util/TextOccurrencesUtil.java | 86 +------------ 3 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 platform/analysis-impl/src/com/intellij/refactoring/util/TextOccurrencesUtilBase.java diff --git a/platform/analysis-impl/src/com/intellij/refactoring/util/TextOccurrencesUtilBase.java b/platform/analysis-impl/src/com/intellij/refactoring/util/TextOccurrencesUtilBase.java new file mode 100644 index 000000000000..9664618824ec --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/refactoring/util/TextOccurrencesUtilBase.java @@ -0,0 +1,121 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.refactoring.util; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.LanguageParserDefinitions; +import com.intellij.lang.ParserDefinition; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiPolyVariantReference; +import com.intellij.psi.PsiReference; +import com.intellij.psi.impl.search.PsiSearchHelperImpl; +import com.intellij.psi.search.*; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageInfoFactory; +import com.intellij.util.PairProcessor; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public final class TextOccurrencesUtilBase { + + private TextOccurrencesUtilBase() { + } + + public static void addTextOccurrences(@NotNull PsiElement element, + @NotNull String stringToSearch, + @NotNull GlobalSearchScope searchScope, + @NotNull Collection results, + @NotNull UsageInfoFactory factory) { + PsiSearchHelperImpl.processTextOccurrences(element, stringToSearch, searchScope, factory, t -> { + results.add(t); + return true; + }); + } + + public static boolean processUsagesInStringsAndComments(@NotNull PsiElement element, + @NotNull SearchScope searchScope, + @NotNull String stringToSearch, + boolean ignoreReferences, + @NotNull PairProcessor processor) { + PsiSearchHelper helper = PsiSearchHelper.getInstance(element.getProject()); + SearchScope scope = helper.getUseScope(element); + scope = scope.intersectWith(searchScope); + Processor commentOrLiteralProcessor = literal -> processTextIn(literal, stringToSearch, ignoreReferences, processor); + return processStringLiteralsContainingIdentifier(stringToSearch, scope, helper, commentOrLiteralProcessor) && + helper.processCommentsContainingIdentifier(stringToSearch, scope, commentOrLiteralProcessor); + } + + private static boolean processStringLiteralsContainingIdentifier(@NotNull String identifier, + @NotNull SearchScope searchScope, + PsiSearchHelper helper, + final Processor processor) { + TextOccurenceProcessor occurenceProcessor = (element, offsetInElement) -> { + final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(element.getLanguage()); + final ASTNode node = element.getNode(); + if (definition != null && node != null && definition.getStringLiteralElements().contains(node.getElementType())) { + return processor.process(element); + } + return true; + }; + + return helper.processElementsWithWord(occurenceProcessor, searchScope, identifier, UsageSearchContext.IN_STRINGS, true); + } + + private static boolean processTextIn(PsiElement scope, + String stringToSearch, + boolean ignoreReferences, + PairProcessor processor) { + String text = scope.getText(); + for (int offset = 0; offset < text.length(); offset++) { + offset = text.indexOf(stringToSearch, offset); + if (offset < 0) break; + final PsiReference referenceAt = scope.findReferenceAt(offset); + if (!ignoreReferences && referenceAt != null + && (referenceAt.resolve() != null || referenceAt instanceof PsiPolyVariantReference + && ((PsiPolyVariantReference)referenceAt).multiResolve(true).length > 0)) { + continue; + } + + if (offset > 0) { + char c = text.charAt(offset - 1); + if (Character.isJavaIdentifierPart(c) && c != '$') { + if (offset < 2 || text.charAt(offset - 2) != '\\') continue; //escape sequence + } + } + + if (offset + stringToSearch.length() < text.length()) { + char c = text.charAt(offset + stringToSearch.length()); + if (Character.isJavaIdentifierPart(c) && c != '$') { + continue; + } + } + + TextRange textRange = new TextRange(offset, offset + stringToSearch.length()); + if (!processor.process(scope, textRange)) { + return false; + } + + offset += stringToSearch.length(); + } + return true; + } + + public static void addUsagesInStringsAndComments(@NotNull PsiElement element, + @NotNull SearchScope searchScope, + @NotNull String stringToSearch, + @NotNull Collection results, + @NotNull UsageInfoFactory factory) { + Object lock = new Object(); + processUsagesInStringsAndComments(element, searchScope, stringToSearch, false, (commentOrLiteral, textRange) -> { + UsageInfo usageInfo = factory.createUsageInfo(commentOrLiteral, textRange.getStartOffset(), textRange.getEndOffset()); + if (usageInfo != null) { + synchronized (lock) { + results.add(usageInfo); + } + } + return true; + }); + } +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java index 484b60ec2649..fa8daecf5aee 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java @@ -32,7 +32,7 @@ import com.intellij.refactoring.listeners.UndoRefactoringElementListener; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.NonCodeSearchDescriptionLocation; import com.intellij.refactoring.util.NonCodeUsageInfo; -import com.intellij.refactoring.util.TextOccurrencesUtil; +import com.intellij.refactoring.util.TextOccurrencesUtilBase; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfoFactory; import com.intellij.util.IncorrectOperationException; @@ -92,7 +92,7 @@ public class RenameUtil { if (stringToSearch.length() > 0) { final String stringToReplace = getStringToReplace(element, newName, false, processor); UsageInfoFactory factory = new NonCodeUsageInfoFactory(searchForInComments, stringToReplace); - TextOccurrencesUtil.addUsagesInStringsAndComments(searchForInComments, searchScope, stringToSearch, result, factory); + TextOccurrencesUtilBase.addUsagesInStringsAndComments(searchForInComments, searchScope, stringToSearch, result, factory); } } @@ -126,7 +126,7 @@ public class RenameUtil { } }; if (searchScope instanceof GlobalSearchScope) { - TextOccurrencesUtil.addTextOccurrences(element, stringToSearch, (GlobalSearchScope)searchScope, result, factory); + TextOccurrencesUtilBase.addTextOccurrences(element, stringToSearch, (GlobalSearchScope)searchScope, result, factory); } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java index 120f486263e8..728e4b71cc39 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java @@ -7,19 +7,13 @@ import com.intellij.find.findUsages.FindUsagesHandler; import com.intellij.find.findUsages.FindUsagesManager; import com.intellij.find.findUsages.FindUsagesUtil; import com.intellij.find.impl.FindManagerImpl; -import com.intellij.lang.ASTNode; -import com.intellij.lang.LanguageParserDefinitions; -import com.intellij.lang.ParserDefinition; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiPolyVariantReference; -import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.search.PsiSearchHelperImpl; -import com.intellij.psi.search.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.SearchScope; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfoFactory; import com.intellij.util.PairProcessor; -import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -43,26 +37,7 @@ public class TextOccurrencesUtil { @NotNull GlobalSearchScope searchScope, @NotNull Collection results, @NotNull UsageInfoFactory factory) { - PsiSearchHelperImpl.processTextOccurrences(element, stringToSearch, searchScope, factory, t -> { - results.add(t); - return true; - }); - } - - private static boolean processStringLiteralsContainingIdentifier(@NotNull String identifier, - @NotNull SearchScope searchScope, - PsiSearchHelper helper, - final Processor processor) { - TextOccurenceProcessor occurenceProcessor = (element, offsetInElement) -> { - final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(element.getLanguage()); - final ASTNode node = element.getNode(); - if (definition != null && node != null && definition.getStringLiteralElements().contains(node.getElementType())) { - return processor.process(element); - } - return true; - }; - - return helper.processElementsWithWord(occurenceProcessor, searchScope, identifier, UsageSearchContext.IN_STRINGS, true); + TextOccurrencesUtilBase.addTextOccurrences(element, stringToSearch, searchScope, results, factory); } /** @deprecated Use {@link TextOccurrencesUtil#processUsagesInStringsAndComments( @@ -81,12 +56,7 @@ public class TextOccurrencesUtil { @NotNull String stringToSearch, boolean ignoreReferences, @NotNull PairProcessor processor) { - PsiSearchHelper helper = PsiSearchHelper.getInstance(element.getProject()); - SearchScope scope = helper.getUseScope(element); - scope = scope.intersectWith(searchScope); - Processor commentOrLiteralProcessor = literal -> processTextIn(literal, stringToSearch, ignoreReferences, processor); - return processStringLiteralsContainingIdentifier(stringToSearch, scope, helper, commentOrLiteralProcessor) && - helper.processCommentsContainingIdentifier(stringToSearch, scope, commentOrLiteralProcessor); + return TextOccurrencesUtilBase.processUsagesInStringsAndComments(element, searchScope, stringToSearch, ignoreReferences, processor); } /** @deprecated Use {@link TextOccurrencesUtil#addUsagesInStringsAndComments( @@ -104,53 +74,7 @@ public class TextOccurrencesUtil { @NotNull String stringToSearch, @NotNull Collection results, @NotNull UsageInfoFactory factory) { - Object lock = new Object(); - processUsagesInStringsAndComments(element, searchScope, stringToSearch, false, (commentOrLiteral, textRange) -> { - UsageInfo usageInfo = factory.createUsageInfo(commentOrLiteral, textRange.getStartOffset(), textRange.getEndOffset()); - if (usageInfo != null) { - synchronized (lock) { - results.add(usageInfo); - } - } - return true; - }); - } - - private static boolean processTextIn(PsiElement scope, - String stringToSearch, - boolean ignoreReferences, - PairProcessor processor) { - String text = scope.getText(); - for (int offset = 0; offset < text.length(); offset++) { - offset = text.indexOf(stringToSearch, offset); - if (offset < 0) break; - final PsiReference referenceAt = scope.findReferenceAt(offset); - if (!ignoreReferences && referenceAt != null - && (referenceAt.resolve() != null || referenceAt instanceof PsiPolyVariantReference - && ((PsiPolyVariantReference)referenceAt).multiResolve(true).length > 0)) continue; - - if (offset > 0) { - char c = text.charAt(offset - 1); - if (Character.isJavaIdentifierPart(c) && c != '$') { - if (offset < 2 || text.charAt(offset - 2) != '\\') continue; //escape sequence - } - } - - if (offset + stringToSearch.length() < text.length()) { - char c = text.charAt(offset + stringToSearch.length()); - if (Character.isJavaIdentifierPart(c) && c != '$') { - continue; - } - } - - TextRange textRange = new TextRange(offset, offset + stringToSearch.length()); - if (!processor.process(scope, textRange)) { - return false; - } - - offset += stringToSearch.length(); - } - return true; + TextOccurrencesUtilBase.addUsagesInStringsAndComments(element, searchScope, stringToSearch, results, factory); } public static boolean isSearchTextOccurrencesEnabled(@NotNull PsiElement element) {