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 600b4a651afb..65f871303e05 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java @@ -536,175 +536,184 @@ public class FindManagerImpl extends FindManager { int offset, @NotNull FindModel model, @NotNull final VirtualFile file) { - FileType ftype = file.getFileType(); - Language lang = null; - if (ftype instanceof LanguageFileType) { - lang = ((LanguageFileType)ftype).getLanguage(); - } - - CommentsLiteralsSearchData data = model.getUserData(ourCommentsLiteralsSearchDataKey); - if (data == null || !Comparing.equal(data.lastFile, file) || !data.model.equals(model)) { - SyntaxHighlighter highlighter = getHighlighter(file, lang); - - if (highlighter == null) { - // no syntax highlighter -> no search - return NOT_FOUND_RESULT; + synchronized (model) { + FileType ftype = file.getFileType(); + Language lang = null; + if (ftype instanceof LanguageFileType) { + lang = ((LanguageFileType)ftype).getLanguage(); } - TokenSet tokensOfInterest = TokenSet.EMPTY; - Set relevantLanguages; - if (lang != null) { - final Language finalLang = lang; - relevantLanguages = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Set compute() { - THashSet result = new THashSet(); + CommentsLiteralsSearchData data = model.getUserData(ourCommentsLiteralsSearchDataKey); + if (data == null || !Comparing.equal(data.lastFile, file) || !data.model.equals(model)) { + SyntaxHighlighter highlighter = getHighlighter(file, lang); - FileViewProvider viewProvider = PsiManager.getInstance(myProject).findViewProvider(file); - if (viewProvider != null) { - result.addAll(viewProvider.getLanguages()); - } - - if (result.isEmpty()) { - result.add(finalLang); - } - return result; - } - }); - - for (Language relevantLanguage:relevantLanguages) { - tokensOfInterest = addTokenTypesForLanguage(model, relevantLanguage, tokensOfInterest); + if (highlighter == null) { + // no syntax highlighter -> no search + return NOT_FOUND_RESULT; } - if(model.isInStringLiteralsOnly()) { - // TODO: xml does not have string literals defined so we add XmlAttributeValue element type as convenience - final Lexer xmlLexer = getHighlighter(null, Language.findLanguageByID("XML")).getHighlightingLexer(); - final String marker = "xxx"; - xmlLexer.start(""); + TokenSet tokensOfInterest = TokenSet.EMPTY; + Set relevantLanguages; + if (lang != null) { + final Language finalLang = lang; + relevantLanguages = ApplicationManager.getApplication().runReadAction(new Computable>() { + @Override + public Set compute() { + THashSet result = new THashSet(); - while (!marker.equals(xmlLexer.getTokenText())) { - xmlLexer.advance(); - if (xmlLexer.getTokenType() == null) break; + FileViewProvider viewProvider = PsiManager.getInstance(myProject).findViewProvider(file); + if (viewProvider != null) { + result.addAll(viewProvider.getLanguages()); + } + + if (result.isEmpty()) { + result.add(finalLang); + } + return result; + } + }); + + for (Language relevantLanguage : relevantLanguages) { + tokensOfInterest = addTokenTypesForLanguage(model, relevantLanguage, tokensOfInterest); } - IElementType convenienceXmlAttrType = xmlLexer.getTokenType(); - if (convenienceXmlAttrType != null) { - tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(convenienceXmlAttrType)); - } - } - } else { - relevantLanguages = ContainerUtil.newHashSet(); - if (ftype instanceof AbstractFileType) { - if (model.isInCommentsOnly()) { - tokensOfInterest = TokenSet.create(CustomHighlighterTokenType.LINE_COMMENT, CustomHighlighterTokenType.MULTI_LINE_COMMENT); - } if (model.isInStringLiteralsOnly()) { - tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(CustomHighlighterTokenType.STRING, CustomHighlighterTokenType.SINGLE_QUOTED_STRING)); + // TODO: xml does not have string literals defined so we add XmlAttributeValue element type as convenience + final Lexer xmlLexer = getHighlighter(null, Language.findLanguageByID("XML")).getHighlightingLexer(); + final String marker = "xxx"; + xmlLexer.start(""); + + while (!marker.equals(xmlLexer.getTokenText())) { + xmlLexer.advance(); + if (xmlLexer.getTokenType() == null) break; + } + + IElementType convenienceXmlAttrType = xmlLexer.getTokenType(); + if (convenienceXmlAttrType != null) { + tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet.create(convenienceXmlAttrType)); + } } } + else { + relevantLanguages = ContainerUtil.newHashSet(); + if (ftype instanceof AbstractFileType) { + if (model.isInCommentsOnly()) { + tokensOfInterest = TokenSet.create(CustomHighlighterTokenType.LINE_COMMENT, CustomHighlighterTokenType.MULTI_LINE_COMMENT); + } + if (model.isInStringLiteralsOnly()) { + tokensOfInterest = TokenSet.orSet(tokensOfInterest, TokenSet + .create(CustomHighlighterTokenType.STRING, CustomHighlighterTokenType.SINGLE_QUOTED_STRING)); + } + } + } + + Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, "") : null; + StringSearcher searcher = matcher != null ? null : new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true); + 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); } - Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null; - StringSearcher searcher = matcher != null ? null: new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true); - 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; + data.highlighter.resetPosition(initialStartOffset); + final Lexer lexer = data.highlighter.getHighlightingLexer(); - int initialStartOffset = model.isForward() && data.startOffset < offset ? data.startOffset : 0; - data.highlighter.resetPosition(initialStartOffset); - final Lexer lexer = data.highlighter.getHighlightingLexer(); + IElementType tokenType; + TokenSet tokens = data.tokensOfInterest; - IElementType tokenType; - TokenSet tokens = data.tokensOfInterest; + int lastGoodOffset = 0; + boolean scanningForward = model.isForward(); + FindResultImpl prevFindResult = NOT_FOUND_RESULT; - int lastGoodOffset = 0; - boolean scanningForward = model.isForward(); - FindResultImpl prevFindResult = NOT_FOUND_RESULT; + while ((tokenType = lexer.getTokenType()) != null) { + if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart(); - while((tokenType = lexer.getTokenType()) != null) { - if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart(); + final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType); - final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType); - - if (tokens.contains(tokenType) || - (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) || - (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys)) - ) { - int start = lexer.getTokenStart(); - int end = lexer.getTokenEnd(); - if (model.isInStringLiteralsOnly()) { // skip literal quotes itself from matching - char c = text.charAt(start); - if (c == '"' || c == '\'') { - while (start < end && c == text.charAt(start)) { - ++start; - if (c == text.charAt(end - 1) && start < end) --end; + if (tokens.contains(tokenType) || + (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) || + (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys)) + ) { + int start = lexer.getTokenStart(); + int end = lexer.getTokenEnd(); + if (model.isInStringLiteralsOnly()) { // skip literal quotes itself from matching + char c = text.charAt(start); + if (c == '"' || c == '\'') { + while (start < end && c == text.charAt(start)) { + ++start; + if (c == text.charAt(end - 1) && start < end) --end; + } } } - } - while(true) { - FindResultImpl findResult = null; + while (true) { + FindResultImpl findResult = null; - if (data.searcher != null) { - int matchStart = data.searcher.scan(text, textArray, start, end); + if (data.searcher != null) { + int matchStart = data.searcher.scan(text, textArray, start, end); - if (matchStart != -1 && matchStart >= start) { - final int matchEnd = matchStart + model.getStringToFind().length(); - if (matchStart >= offset || !scanningForward) - findResult = new FindResultImpl(matchStart, matchEnd); - else { - start = matchEnd; - continue; - } - } - } else if (start <= end) { - data.matcher.reset(StringPattern.newBombedCharSequence(text.subSequence(start, end))); - if (data.matcher.find()) { - final int matchEnd = start + data.matcher.end(); - int matchStart = start + data.matcher.start(); - if (matchStart >= offset || !scanningForward) { - findResult = new FindResultImpl(matchStart, matchEnd); - } - else { - int diff = 0; - if (start == end) { - diff = scanningForward ? 1:-1; + if (matchStart != -1 && matchStart >= start) { + final int matchEnd = matchStart + model.getStringToFind().length(); + if (matchStart >= offset || !scanningForward) + findResult = new FindResultImpl(matchStart, matchEnd); + else { + start = matchEnd; + continue; } - start = matchEnd + diff; + } + } + else if (start <= end) { + data.matcher.reset(StringPattern.newBombedCharSequence(text.subSequence(start, end))); + if (data.matcher.find()) { + final int matchEnd = start + data.matcher.end(); + int matchStart = start + data.matcher.start(); + if (matchStart >= offset || !scanningForward) { + findResult = new FindResultImpl(matchStart, matchEnd); + } + else { + int diff = 0; + if (start == end) { + diff = scanningForward ? 1 : -1; + } + start = matchEnd + diff; + continue; + } + } + } + + if (findResult != null) { + if (scanningForward) { + data.startOffset = lastGoodOffset; + return findResult; + } + else { + + if (findResult.getEndOffset() >= offset) return prevFindResult; + prevFindResult = findResult; + start = findResult.getEndOffset(); continue; } } + break; } - - if (findResult != null) { - if (scanningForward) { - data.startOffset = lastGoodOffset; - return findResult; - } else { - - if (findResult.getEndOffset() >= offset) return prevFindResult; - prevFindResult = findResult; - start = findResult.getEndOffset(); - continue; - } + } + else { + Language tokenLang = tokenType.getLanguage(); + if (tokenLang != lang && tokenLang != Language.ANY && !data.relevantLanguages.contains(tokenLang)) { + tokens = addTokenTypesForLanguage(model, tokenLang, tokens); + data.tokensOfInterest = tokens; + data.relevantLanguages.add(tokenLang); } - break; - } - } else { - Language tokenLang = tokenType.getLanguage(); - if (tokenLang != lang && tokenLang != Language.ANY && !data.relevantLanguages.contains(tokenLang)) { - tokens = addTokenTypesForLanguage(model, tokenLang, tokens); - data.tokensOfInterest = tokens; - data.relevantLanguages.add(tokenLang); } + + lexer.advance(); } - lexer.advance(); + return prevFindResult; } - - return prevFindResult; } private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) {