diff options
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.java | 204 |
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) { |