summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java')
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java204
1 files changed, 121 insertions, 83 deletions
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index e327ec79c227..27e2b7215f25 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -27,7 +27,6 @@ import com.intellij.find.impl.livePreview.SearchResults;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
-import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.Lexer;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -42,11 +41,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.FoldingModelEx;
-import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
-import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
@@ -58,15 +52,17 @@ 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.search.LexerEditorHighlighterLexer;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.ReplacePromptDialog;
+import com.intellij.usages.ChunkExtractor;
import com.intellij.usages.UsageViewManager;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Predicate;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.StringSearcher;
@@ -96,6 +92,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
private final FindUsagesManager myFindUsagesManager;
private boolean isFindWasPerformed = false;
+ private boolean isSelectNextOccurrenceWasPerformed = false;
private Point myReplaceInFilePromptPos = new Point(-1, -1);
private Point myReplaceInProjectPromptPos = new Point(-1, -1);
private final FindModel myFindInProjectModel = new FindModel();
@@ -257,7 +254,18 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
@Override
public void setFindWasPerformed() {
isFindWasPerformed = true;
- //myFindUsagesManager.clearFindingNextUsageInFile();
+ isSelectNextOccurrenceWasPerformed = false;
+ }
+
+ @Override
+ public boolean selectNextOccurrenceWasPerformed() {
+ return isSelectNextOccurrenceWasPerformed;
+ }
+
+ @Override
+ public void setSelectNextOccurrenceWasPerformed() {
+ isSelectNextOccurrenceWasPerformed = true;
+ isFindWasPerformed = false;
}
@Override
@@ -270,7 +278,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
if (myFindNextModel == null) return null;
final JComponent header = editor.getHeaderComponent();
- if (header instanceof EditorSearchComponent) {
+ if (header instanceof EditorSearchComponent && !isSelectNextOccurrenceWasPerformed) {
final EditorSearchComponent searchComponent = (EditorSearchComponent)header;
final String textInField = searchComponent.getTextInField();
if (!Comparing.equal(textInField, myFindInFileModel.getStringToFind()) && !textInField.isEmpty()) {
@@ -305,25 +313,103 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
LOG.debug(model.toString());
}
- final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
+ return findStringLoop(text, offset, model, file, getFindContextPredicate(model, file, text));
+ }
+ private FindResult findStringLoop(CharSequence text, int offset, FindModel model, VirtualFile file, @Nullable Predicate<FindResult> filter) {
+ final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
while(true) {
FindResult result = doFindString(text, textArray, offset, model, file);
+ if (filter == null || filter.apply(result)) {
+ if (!model.isWholeWordsOnly()) {
+ return result;
+ }
+ if (!result.isStringFound()) {
+ return result;
+ }
+ if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())) {
+ return result;
+ }
+ }
+
+ offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
+ if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ }
+ }
+
+ private class FindExceptCommentsOrLiteralsData implements Predicate<FindResult> {
+ private final VirtualFile myFile;
+ private final FindModel myFindModel;
+ private final TreeMap<Integer, Integer> mySkipRangesSet;
+
+ private FindExceptCommentsOrLiteralsData(VirtualFile file, FindModel model, CharSequence text) {
+ myFile = file;
+ myFindModel = model.clone();
- if (!model.isWholeWordsOnly()) {
- return result;
+ TreeMap<Integer, Integer> result = new TreeMap<Integer, Integer>();
+
+ if (model.isExceptComments() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_COMMENTS);
}
- if (!result.isStringFound()){
- return result;
+
+ if (model.isExceptStringLiterals() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_STRING_LITERALS);
}
- if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())){
- return result;
+
+ mySkipRangesSet = result;
+ }
+
+ private void addRanges(VirtualFile file,
+ FindModel model,
+ CharSequence text,
+ TreeMap<Integer, Integer> result,
+ FindModel.SearchContext searchContext) {
+ FindModel clonedModel = model.clone();
+ clonedModel.setSearchContext(searchContext);
+ clonedModel.setForward(true);
+ int offset = 0;
+
+ while(true) {
+ FindResult customResult = findStringLoop(text, offset, clonedModel, file, null);
+ if (!customResult.isStringFound()) break;
+ result.put(customResult.getStartOffset(), customResult.getEndOffset());
+ offset = Math.max(customResult.getEndOffset(), offset + 1); // avoid loop for zero size reg exps matches
+ if (offset >= text.length()) break;
}
+ }
- offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
- if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ boolean isAcceptableFor(FindModel model, VirtualFile file) {
+ return Comparing.equal(myFile, file) && myFindModel.equals(model);
+ }
+
+ @Override
+ public boolean apply(@Nullable FindResult input) {
+ if (input == null || !input.isStringFound()) return true;
+ NavigableMap<Integer, Integer> map = mySkipRangesSet.headMap(input.getStartOffset(), true);
+ for(Map.Entry<Integer, Integer> e:map.descendingMap().entrySet()) {
+ if (e.getKey() <= input.getStartOffset() && e.getValue() >= input.getEndOffset()) return false;
+ if (e.getValue() <= input.getStartOffset()) break;
+ }
+ return true;
}
}
+ private static Key<FindExceptCommentsOrLiteralsData> ourExceptCommentsOrLiteralsDataKey = Key.create("except.comments.literals.search.data");
+
+ private Predicate<FindResult> getFindContextPredicate(@NotNull FindModel model, VirtualFile file, CharSequence text) {
+ if (file == null) return null;
+ FindModel.SearchContext context = model.getSearchContext();
+ if( context == FindModel.SearchContext.ANY || context == FindModel.SearchContext.IN_COMMENTS ||
+ context == FindModel.SearchContext.IN_STRING_LITERALS) {
+ return null;
+ }
+
+ FindExceptCommentsOrLiteralsData data = model.getUserData(ourExceptCommentsOrLiteralsDataKey);
+ if (data == null || !data.isAcceptableFor(model, file)) {
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, data = new FindExceptCommentsOrLiteralsData(file, model, text));
+ }
+
+ return data;
+ }
@Override
public int showMalformedReplacementPrompt(@NotNull FindModel model, String title, MalformedReplacementStringException exception) {
@@ -408,11 +494,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), model.isForward());
}
+ public static void clearPreviousFindData(FindModel model) {
+ model.putUserData(ourCommentsLiteralsSearchDataKey, null);
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, null);
+ }
+
private static class CommentsLiteralsSearchData {
final VirtualFile lastFile;
int startOffset = 0;
- final SyntaxHighlighter highlighter;
- final Lexer highlightingLexer;
+ final SyntaxHighlighterOverEditorHighlighter highlighter;
TokenSet tokensOfInterest;
final StringSearcher searcher;
@@ -420,8 +510,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
final Set<Language> relevantLanguages;
final FindModel model;
- public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages, SyntaxHighlighter highlighter,
- Lexer lexer, TokenSet tokensOfInterest,
+ public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages,
+ SyntaxHighlighterOverEditorHighlighter highlighter, TokenSet tokensOfInterest,
StringSearcher searcher, Matcher matcher, FindModel model) {
this.lastFile = lastFile;
this.highlighter = highlighter;
@@ -429,12 +519,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
this.searcher = searcher;
this.matcher = matcher;
this.relevantLanguages = relevantLanguages;
- highlightingLexer = lexer;
this.model = model;
}
}
- public static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
+ private static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
@NotNull
private FindResult findInCommentsAndLiterals(@NotNull CharSequence text,
@@ -512,38 +601,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null;
StringSearcher searcher = matcher != null ? null: new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true);
- LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
- EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, file);
- Lexer lexer;
-
- try {
- if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
- lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
- } else {
- lexer = highlighter.getHighlightingLexer();
- }
- }
- finally {
- LayeredLexer.ourDisableLayersFlag.set(null);
- }
-
- data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighter, lexer, tokensOfInterest, searcher, matcher, (FindModel)model.clone());
- lexer.start(text, 0, text.length(), 0);
+ SyntaxHighlighterOverEditorHighlighter highlighterAdapter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file, myProject);
+ data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighterAdapter, tokensOfInterest, searcher, matcher, model.clone());
+ data.highlighter.restart(text);
model.putUserData(ourCommentsLiteralsSearchDataKey, data);
}
int initialStartOffset = model.isForward() && data.startOffset < offset ? data.startOffset : 0;
- final Lexer lexer = data.highlightingLexer;
- LayeredHighlighterIterator layeredHighlighterIterator = null;
- if (lexer instanceof LexerEditorHighlighterLexer) {
- ((LexerEditorHighlighterLexer)lexer).resetPosition(initialStartOffset);
- HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
- if (iterator instanceof LayeredHighlighterIterator) {
- layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
- }
- } else {
- lexer.start(text, initialStartOffset, text.length(), 0);
- }
+ data.highlighter.resetPosition(initialStartOffset);
+ final Lexer lexer = data.highlighter.getHighlightingLexer();
IElementType tokenType;
TokenSet tokens = data.tokensOfInterest;
@@ -555,13 +621,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
while((tokenType = lexer.getTokenType()) != null) {
if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart();
- final SyntaxHighlighter activeSyntaxHighlighter =
- layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : data.highlighter;
- final TextAttributesKey[] keys = activeSyntaxHighlighter.getTokenHighlights(tokenType);
+ final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType);
if (tokens.contains(tokenType) ||
- (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) ||
- (model.isInCommentsOnly() && isHighlightedAsDocComment(keys))
+ (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) ||
+ (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys))
) {
int start = lexer.getTokenStart();
int end = lexer.getTokenEnd();
@@ -634,32 +698,6 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return prevFindResult;
}
- private static boolean isHighlightedAsDocComment(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || key == SyntaxHighlighterColors.DOC_COMMENT) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsDocComment(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isHighlightedAsString(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) {
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
if (definition != null) {