From 1a2220dc57ea8159c0e5d911e4a42e7960366a8d Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Fri, 27 Jul 2012 17:10:20 +0400 Subject: [PATCH 01/16] IDEA-85455 Dropdown for runnable configs doesn't open on press --- .../actionSystem/ex/ComboBoxAction.java | 65 +++++++++++++++---- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java index 011659fd78f6..142957886db8 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java @@ -35,10 +35,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -101,6 +98,7 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent private boolean myForcePressed = false; private PropertyChangeListener myButtonSynchronizer; private boolean myMouseInside = false; + private JBPopup myPopup; public ComboBoxButton(Presentation presentation) { myPresentation = presentation; @@ -143,7 +141,56 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent myMouseInside = false; repaint(); } + + @Override + public void mousePressed(final MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + e.consume(); + doClick(); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + dispatchEventToPopup(e); + } }); + addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(new MouseEvent(e.getComponent(), + MouseEvent.MOUSE_MOVED, + e.getWhen(), + e.getModifiers(), + e.getX(), + e.getY(), + e.getClickCount(), + e.isPopupTrigger(), + e.getButton())); + } + + @Override + public void mouseMoved(MouseEvent e) { + dispatchEventToPopup(e); + } + }); + } + // Event forwarding. We need it if user does press-and-drag gesture for opening popup and choosing item there. + // It works in JComboBox, here we provide the same behavior + private void dispatchEventToPopup(MouseEvent e) { + if (myPopup != null && myPopup.isVisible()) { + JComponent content = myPopup.getContent(); + Rectangle rectangle = content.getBounds(); + Point location = rectangle.getLocation(); + SwingUtilities.convertPointToScreen(location, content); + Point eventPoint = e.getLocationOnScreen(); + rectangle.setLocation(location); + if (rectangle.contains(eventPoint)) { + MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, myPopup.getContent()); + Component component = SwingUtilities.getDeepestComponentAt(content, event.getX(), event.getY()); + component.dispatchEvent(event); + } + } } public void showPopup() { @@ -156,15 +203,15 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { myForcePressed = false; + myPopup = null; } }); repaint(); } }; - JBPopup popup = createPopup(onDispose); - - popup.show(new RelativePoint(this, new Point(0, this.getHeight() - 1))); + myPopup = createPopup(onDispose); + myPopup.show(new RelativePoint(this, new Point(0, this.getHeight() - 1))); } @Nullable @@ -372,10 +419,6 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent g.setPaintMode(); } - private boolean isGlowSupported() { - return false; - } - protected void updateButtonSize() { invalidate(); repaint(); From f544d3ffc4fd769112129fef383cbcb5d1593a36 Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Fri, 27 Jul 2012 15:04:23 +0400 Subject: [PATCH 02/16] FindUsages for Java step definition implemented --- .../findUsages/CustomJavaFindUsagesHandler.java | 14 ++++++++++++++ .../CustomJavaFindUsagesHandlerProvider.java | 13 +++++++++++++ .../find/findUsages/JavaFindUsagesHandler.java | 5 +++++ 3 files changed, 32 insertions(+) create mode 100644 java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandler.java create mode 100644 java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandlerProvider.java diff --git a/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandler.java new file mode 100644 index 000000000000..d8fe4c7ca09c --- /dev/null +++ b/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandler.java @@ -0,0 +1,14 @@ +package com.intellij.find.findUsages; + +import com.intellij.psi.PsiElement; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +/** + * User: Andrey.Vokin + * Date: 7/26/12 + */ +public interface CustomJavaFindUsagesHandler { + public void processElementUsages(@NotNull final PsiElement element, @NotNull final Processor processor, @NotNull final FindUsagesOptions options); +} diff --git a/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandlerProvider.java b/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandlerProvider.java new file mode 100644 index 000000000000..368c8aed3904 --- /dev/null +++ b/java/java-impl/src/com/intellij/find/findUsages/CustomJavaFindUsagesHandlerProvider.java @@ -0,0 +1,13 @@ +package com.intellij.find.findUsages; + +import com.intellij.openapi.extensions.ExtensionPointName; + +/** + * User: Andrey.Vokin + * Date: 7/26/12 + */ +public abstract class CustomJavaFindUsagesHandlerProvider { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.findUsages.java.customJavaFindUsagesHandlerProvider"); + + public abstract CustomJavaFindUsagesHandler getHandler(); +} diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index 3059580b3f2a..ac0f39f31054 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -384,6 +384,11 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ // todo add to fastTrack processUsagesInText(element, processor, (GlobalSearchScope)options.searchScope); } + + final CustomJavaFindUsagesHandlerProvider[] customJavaFindUsagesHandlerProviders = Extensions.getExtensions(CustomJavaFindUsagesHandlerProvider.EP_NAME); + for (CustomJavaFindUsagesHandlerProvider provider : customJavaFindUsagesHandlerProviders) { + provider.getHandler().processElementUsages(element, processor, options); + } } private static void addAliasingUsages(PomTarget pomTarget, final Processor processor, final FindUsagesOptions options) { From 4b0b573d689682b90e81d4701c687aba0011bf44 Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Fri, 27 Jul 2012 17:13:50 +0400 Subject: [PATCH 03/16] FindUsages for Java step definition implemented --- .../com/intellij/testFramework/CodeInsightTestCase.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java index b6d3fb87f2cc..f8b28b832dcb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java @@ -1,9 +1,7 @@ package com.intellij.testFramework; -import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.testFramework.fixtures.CodeInsightTestFixture; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import org.jetbrains.annotations.NonNls; @@ -14,12 +12,6 @@ import org.jetbrains.annotations.NonNls; public class CodeInsightTestCase extends LightPlatformCodeInsightFixtureTestCase { @NonNls protected static final String CARET_STR = ""; - protected CodeInsightTestFixture myFixture; - - protected Project getProject() { - return myFixture.getProject(); - } - protected int findOffsetBySignature(String signature) { return findOffsetBySignature(signature, myFixture.getFile()); } From 6d34a5f2e9a7bf1def4330a9f5cc3738356180c5 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 27 Jul 2012 17:25:23 +0400 Subject: [PATCH 04/16] text that we pass to stdin should be encoded with stdout/stderr encoding #RUBY-10785 fixed --- .../execution/runners/ConsoleExecuteActionHandler.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index 13cf5a7c67b6..e42cbeae10d0 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -16,6 +16,7 @@ package com.intellij.execution.runners; import com.intellij.execution.console.LanguageConsoleImpl; +import com.intellij.execution.process.BaseOSProcessHandler; import com.intellij.execution.process.ConsoleHistoryModel; import com.intellij.execution.process.ProcessHandler; import com.intellij.openapi.command.impl.UndoManagerImpl; @@ -28,6 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.Charset; /** * @author traff @@ -91,14 +93,14 @@ public class ConsoleExecuteActionHandler { } public void sendText(String line) { - //final Charset charset = myProcessHandler.getCharset(); + final Charset charset = myProcessHandler instanceof BaseOSProcessHandler ? + ((BaseOSProcessHandler)myProcessHandler).getCharset() : null; final ProcessHandler handler = getProcessHandler(); assert handler != null : "process handler is null"; final OutputStream outputStream = handler.getProcessInput(); assert outputStream != null : "output stream is null"; try { - //byte[] bytes = (line + "\n").getBytes(charset.name()); - byte[] bytes = line.getBytes(); + byte[] bytes = charset != null ? (line + "\n").getBytes(charset) : line.getBytes(); outputStream.write(bytes); outputStream.flush(); } From ccb1eed6ae40227d8bd160f9cdaf168aff71beb5 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 27 Jul 2012 17:27:24 +0400 Subject: [PATCH 05/16] cleanup spaghetti incident --- .../execution/process/ColoredProcessHandler.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/ColoredProcessHandler.java index 96df0f61e596..58a076afec67 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ColoredProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/ColoredProcessHandler.java @@ -35,7 +35,6 @@ public class ColoredProcessHandler extends OSProcessHandler { private static final String TEXT_ATTRS_PATTERN = "m" + TEXT_ATTRS_PREFIX_CH + "\\["; private Key myCurrentColor; - @Nullable private final Charset myCharset; public static TextAttributes getByKey(final TextAttributesKey key){ return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key); @@ -56,17 +55,7 @@ public class ColoredProcessHandler extends OSProcessHandler { public ColoredProcessHandler(final Process process, final String commandLine, @Nullable final Charset charset) { - super(process, commandLine); - myCharset = charset; - } - - @Override - public Charset getCharset() { - if (myCharset != null) { - return myCharset; - } - // Charset wasn't specified - use default one - return super.getCharset(); + super(process, commandLine, charset); } public final void notifyTextAvailable(final String text, final Key outputType) { From 5e14d6a760c836b7c056be31e902c0dde23cea3d Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 27 Jul 2012 16:13:10 +0400 Subject: [PATCH 06/16] RUBY-11144: change way Slim parses/handles Doctype. Doctype is not wrapped in tag now and still resolved. --- .../indentation/IndentationParser.java | 33 +++++++++---- .../psi/impl/source/xml/XmlDoctypeImpl.java | 49 +++++++++---------- .../src/com/intellij/psi/xml/XmlDoctype.java | 4 +- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java b/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java index acf195d828ff..240300157d39 100644 --- a/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java +++ b/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java @@ -6,6 +6,7 @@ import com.intellij.lang.PsiParser; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author oleg @@ -38,7 +39,7 @@ public abstract class IndentationParser implements PsiParser { final PsiBuilder.Marker documentMarker = builder.mark(); final Stack stack = new Stack(); - stack.push(new BlockInfo(0, builder.mark())); + stack.push(new BlockInfo(0, builder.mark(), builder.getTokenType())); PsiBuilder.Marker startLineMarker = null; int currentIndent = 0; @@ -71,17 +72,19 @@ public abstract class IndentationParser implements PsiParser { } // Close indentation blocks while (!stack.isEmpty() && currentIndent < stack.peek().getIndent()) { - closeBlock(builder, stack.pop().getMarker()); + final BlockInfo blockInfo = stack.pop(); + closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType()); } if (!stack.isEmpty()) { final BlockInfo blockInfo = stack.peek(); if (currentIndent >= blockInfo.getIndent()) { if (currentIndent == blockInfo.getIndent()) { - closeBlock(builder, stack.pop().getMarker()); + final BlockInfo info = stack.pop(); + closeBlock(builder, info.getMarker(), info.getStartTokenType()); } passEOLsAndIndents(builder); - stack.push(new BlockInfo(currentIndent, builder.mark())); + stack.push(new BlockInfo(currentIndent, builder.mark(), type)); } } eolSeen = false; @@ -97,7 +100,8 @@ public abstract class IndentationParser implements PsiParser { startLineMarker.drop(); } while (!stack.isEmpty()){ - closeBlock(builder, stack.pop().getMarker()); + final BlockInfo blockInfo = stack.pop(); + closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType()); } documentMarker.done(myDocumentType); @@ -105,7 +109,10 @@ public abstract class IndentationParser implements PsiParser { return builder.getTreeBuilt(); } - protected void closeBlock(@NotNull PsiBuilder builder, @NotNull PsiBuilder.Marker marker) { + protected void closeBlock(final @NotNull PsiBuilder builder, + final @NotNull PsiBuilder.Marker marker, + final @Nullable IElementType startTokenType) + { marker.done(myBlockElementType); } @@ -125,10 +132,13 @@ public abstract class IndentationParser implements PsiParser { private final int myIndent; @NotNull private final PsiBuilder.Marker myMarker; + @Nullable + private final IElementType myStartTokenType; - private BlockInfo(final int indent, final @NotNull PsiBuilder.Marker marker) { - this.myIndent = indent; - this.myMarker = marker; + private BlockInfo(final int indent, final @NotNull PsiBuilder.Marker marker, final @Nullable IElementType type) { + myIndent = indent; + myMarker = marker; + myStartTokenType = type; } public int getIndent() { @@ -139,5 +149,10 @@ public abstract class IndentationParser implements PsiParser { public PsiBuilder.Marker getMarker() { return myMarker; } + + @Nullable + public IElementType getStartTokenType() { + return myStartTokenType; + } } } diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java index 3ac95f0d9e68..14d07718ba87 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java @@ -83,7 +83,7 @@ public class XmlDoctypeImpl extends XmlElementImpl implements XmlDoctype { @Nullable public String getDtdUri() { - final XmlElement dtdUrlElement = getDtdUrlElement(); + final PsiElement dtdUrlElement = getDtdUrlElement(); if (dtdUrlElement == null || dtdUrlElement.getTextLength() == 0) return null; return extractValue(dtdUrlElement); } @@ -120,7 +120,7 @@ public class XmlDoctypeImpl extends XmlElementImpl implements XmlDoctype { } @Nullable - public XmlElement getDtdUrlElement() { + public PsiElement getDtdUrlElement() { PsiElement docTypePublic = findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_PUBLIC); if (docTypePublic != null){ @@ -216,33 +216,32 @@ public class XmlDoctypeImpl extends XmlElementImpl implements XmlDoctype { @NotNull public PsiReference[] getReferences() { - final XmlElement dtdUrlElement = getDtdUrlElement(); - final PsiElement docTypePublic = findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_PUBLIC); - PsiReference[] uriRefs = null; + final PsiElement dtdUrlElement = getDtdUrlElement(); + PsiReference uriRef = null; if (dtdUrlElement != null) { - uriRefs = new PsiReference[1]; - uriRefs[0] = new URLReference(XmlDoctypeImpl.this) { - @NotNull - public Object[] getVariants() { - return docTypePublic != null ? - super.getVariants(): EMPTY_ARRAY; - } - @NotNull - public String getCanonicalText() { - return extractValue(dtdUrlElement); - } - public TextRange getRangeInElement() { - return TextRange.from(dtdUrlElement.getTextRange().getStartOffset() - getTextRange().getStartOffset() + 1, Math.max(dtdUrlElement.getTextRange().getLength() - 2, 0)); - } - }; + uriRef = createUrlReference(dtdUrlElement); } - final PsiReference[] referencesFromProviders = ReferenceProvidersRegistry.getReferencesFromProviders(this); + final PsiReference[] refs = ReferenceProvidersRegistry.getReferencesFromProviders(this); - return ArrayUtil.mergeArrays( - uriRefs != null? uriRefs: PsiReference.EMPTY_ARRAY, - referencesFromProviders - ); + return uriRef == null ? refs : ArrayUtil.mergeArrays(new PsiReference[] {uriRef}, refs); + } + + protected PsiReference createUrlReference(final PsiElement dtdUrlElement) { + return new URLReference(XmlDoctypeImpl.this) { + @NotNull + public Object[] getVariants() { + return findChildByRoleAsPsiElement(XmlChildRole.XML_DOCTYPE_PUBLIC) != null ? + super.getVariants(): EMPTY_ARRAY; + } + @NotNull + public String getCanonicalText() { + return extractValue(dtdUrlElement); + } + public TextRange getRangeInElement() { + return TextRange.from(dtdUrlElement.getTextRange().getStartOffset() - getTextRange().getStartOffset() + 1, Math.max(dtdUrlElement.getTextRange().getLength() - 2, 0)); + } + }; } } diff --git a/xml/openapi/src/com/intellij/psi/xml/XmlDoctype.java b/xml/openapi/src/com/intellij/psi/xml/XmlDoctype.java index f10b039ed84c..461329c7a565 100644 --- a/xml/openapi/src/com/intellij/psi/xml/XmlDoctype.java +++ b/xml/openapi/src/com/intellij/psi/xml/XmlDoctype.java @@ -15,13 +15,15 @@ */ package com.intellij.psi.xml; +import com.intellij.psi.PsiElement; + /** * @author Mike */ public interface XmlDoctype extends XmlElement { XmlElement getNameElement(); String getDtdUri(); - XmlElement getDtdUrlElement(); + PsiElement getDtdUrlElement(); XmlMarkupDecl getMarkupDecl(); String getPublicId(); String getSystemId(); From a4ff8667708da4c38cc95951111ddf4026736012 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 27 Jul 2012 15:08:12 +0200 Subject: [PATCH 07/16] more truthful middle word start matching criterion --- .../testSrc/com/intellij/psi/util/NameUtilTest.java | 1 + .../util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java index a226e63ebf10..f4a13533c64b 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java @@ -441,6 +441,7 @@ public class NameUtilTest extends UsefulTestCase { assertPreference("*ap", "add_profile", "application", NameUtil.MatchingCaseSensitivity.NONE); assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.FIRST_LETTER); assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.NONE); + assertPreference("*ea", "LEADING", "NORTH_EAST", NameUtil.MatchingCaseSensitivity.NONE); } public void testPreferEarlyMatching() { diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java index f20d33e03c35..8f15d1bd3d13 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java +++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java @@ -92,9 +92,9 @@ public class MinusculeMatcher implements Matcher { int startIndex = first.getStartOffset(); boolean prefixMatching = isStartMatch(name, startIndex); - boolean middleWordStart = !prefixMatching && NameUtil.isWordStart(name, first.getStartOffset()); + boolean middleWordStart = !prefixMatching && startIndex > 0 && NameUtil.isWordStart(name, startIndex) && !NameUtil.isWordStart(name, startIndex - 1); - return -fragmentCount + matchingCase * 20 + commonStart * 30 - startIndex + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 100 - integral; + return -fragmentCount + matchingCase * 20 + commonStart * 30 - startIndex + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 1000 - integral; } public boolean isStartMatch(String name) { From b97d7b82614a64af3857490920688e7a1e41e9ef Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 27 Jul 2012 16:00:36 +0200 Subject: [PATCH 08/16] remove incorrect dependency --- plugins/properties/properties.iml | 1 - .../com/intellij/lang/properties/PropertiesFoldingTest.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/properties/properties.iml b/plugins/properties/properties.iml index 26ceccc422a5..3aa5283970cb 100644 --- a/plugins/properties/properties.iml +++ b/plugins/properties/properties.iml @@ -19,7 +19,6 @@ - diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFoldingTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFoldingTest.java index 8d5ddea18558..56c6c0329b33 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFoldingTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFoldingTest.java @@ -15,12 +15,12 @@ */ package com.intellij.lang.properties; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; /** * @author Rustam Vishnyakov */ -public class PropertiesFoldingTest extends LightCodeInsightFixtureTestCase { +public class PropertiesFoldingTest extends LightPlatformCodeInsightFixtureTestCase { private static final String BASE_PATH = "/plugins/properties/testData/propertiesFile/folding/"; From b45324b54ebf00bdd072c157bf056002ec788ffb Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Fri, 27 Jul 2012 18:30:52 +0400 Subject: [PATCH 09/16] Revert removed extension point --- resources/src/META-INF/IdeaPlugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 151119596901..d9edb61a95fa 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -153,7 +153,7 @@ - + From 3dc6305178d0cf7cdb773a8d61a1b71937d8c2da Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 27 Jul 2012 18:32:03 +0400 Subject: [PATCH 10/16] RUBY-11340: ErbErrorFilter should also disable errors for HTML #RUBY-11340 fixed --- .../highlighting/TemplateLanguageErrorFilter.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java index 3b58b7602ea1..d18fc4fe6439 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java @@ -45,10 +45,7 @@ public abstract class TemplateLanguageErrorFilter extends HighlightErrorFilter { if (!(viewProvider.getClass() == myTemplateFileViewProviderClass)) { return true; } - final Language parentLanguage = element.getParent().getLanguage(); - final Language javaScript = Language.findLanguageByID("JavaScript"); - final Language css = Language.findLanguageByID("CSS"); - if (javaScript != null && parentLanguage.is(javaScript) || css != null && parentLanguage.is(css)) { + if (isKnownSubLanguage(element.getParent().getLanguage())) { final PsiElement next = viewProvider.findElementAt(element.getTextOffset() + 1, viewProvider.getBaseLanguage()); if (next != null && myTemplateExpressionStartTokens.contains(next.getNode().getElementType())) { return false; @@ -56,4 +53,10 @@ public abstract class TemplateLanguageErrorFilter extends HighlightErrorFilter { } return true; } + + protected boolean isKnownSubLanguage(final @NotNull Language language) { + final Language javaScript = Language.findLanguageByID("JavaScript"); + final Language css = Language.findLanguageByID("CSS"); + return javaScript != null && language.is(javaScript) || css != null && language.is(css); + } } From d1a1d1d4928fc3c5873a93bb49102fb7059e5ff8 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 26 Jul 2012 14:33:31 +0400 Subject: [PATCH 11/16] EA-37497 fix: split with ':' --- .../android/dom/converters/StyleItemNameConverter.java | 2 +- plugins/android/testData/dom/resources/styles4.xml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/StyleItemNameConverter.java b/plugins/android/src/org/jetbrains/android/dom/converters/StyleItemNameConverter.java index 5f191265cdb0..d3586b2dde11 100644 --- a/plugins/android/src/org/jetbrains/android/dom/converters/StyleItemNameConverter.java +++ b/plugins/android/src/org/jetbrains/android/dom/converters/StyleItemNameConverter.java @@ -68,7 +68,7 @@ public class StyleItemNameConverter extends ResolvingConverter { @Override public String fromString(@Nullable @NonNls String s, ConvertContext context) { if (s == null) return null; - String[] strs = s.split(s); + String[] strs = s.split(":"); if (strs.length < 2 || !"android".equals(strs[0])) { return s; } diff --git a/plugins/android/testData/dom/resources/styles4.xml b/plugins/android/testData/dom/resources/styles4.xml index 0e82088b200b..ff62a213e857 100644 --- a/plugins/android/testData/dom/resources/styles4.xml +++ b/plugins/android/testData/dom/resources/styles4.xml @@ -2,5 +2,7 @@ \ No newline at end of file From 37a4148519d8e6260346b1e51201b42aa9be12cb Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 26 Jul 2012 17:41:12 +0400 Subject: [PATCH 12/16] ability to get lazy info objects for android value resources --- .../android/AndroidValueResourcesIndex.java | 16 +-- .../resourceManagers/IdResourceInfo.java | 53 +++++++++ .../LocalResourceManager.java | 3 +- .../resourceManagers/ResourceManager.java | 107 +++++++++++------- .../resourceManagers/ValueResourceInfo.java | 25 ++++ .../ValueResourceInfoBase.java | 43 +++++++ .../ValueResourceInfoImpl.java | 50 ++++++++ 7 files changed, 242 insertions(+), 55 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/resourceManagers/IdResourceInfo.java create mode 100644 plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfo.java create mode 100644 plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoBase.java create mode 100644 plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java diff --git a/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java b/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java index de2f9d0309ac..1738f748896a 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java +++ b/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java @@ -56,7 +56,7 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtensionemptySet()); + result.put(entry, Collections.emptySet()); addEntryToMap(entry, createTypeMarkerKey(entry.getType()), result); addEntryToMap(entry, createTypeNameMarkerKey(entry.getType(), entry.getName()), result); } @@ -83,17 +83,7 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension result = Ref.create(); + + psiFile.accept(new XmlRecursiveElementVisitor() { + @Override + public void visitXmlAttributeValue(XmlAttributeValue attributeValue) { + if (!result.isNull()) { + return; + } + + if (AndroidResourceUtil.isIdDeclaration(attributeValue)) { + final String idInAttr = AndroidResourceUtil.getResourceNameByReferenceText(attributeValue.getValue()); + + if (myName.equals(idInAttr)) { + result.set(attributeValue); + } + } + } + }); + return result.get(); + } +} diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java index 901edeef9843..a1c39cdd098f 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java @@ -143,8 +143,7 @@ public class LocalResourceManager extends ResourceManager { for (Set entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) { for (ResourceEntry entry : entrySet) { - final Collection files = - index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, AndroidValueResourcesIndex.createKey(entry), scope); + final Collection files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); for (VirtualFile file : files) { Set resourcesInFile = file2Types.get(file); diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java index 4074d08af222..1713ac0463b3 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java @@ -23,10 +23,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; @@ -287,8 +288,7 @@ public abstract class ResourceManager { final Map> file2resourceSet = new HashMap>(); for (Set entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) { for (ResourceEntry entry : entrySet) { - final Collection files = - index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, AndroidValueResourcesIndex.createKey(entry), scope); + final Collection files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); for (VirtualFile file : files) { Set resourcesInFile = file2resourceSet.get(file); @@ -332,41 +332,44 @@ public abstract class ResourceManager { public abstract AttributeDefinitions getAttributeDefinitions(); // searches only declarations such as "@+id/..." - @Nullable - public List findIdDeclarations(@NotNull final String id) { + @NotNull + public List findIdDeclarationInfos(@NotNull final String id) { if (!isResourcePublic(ResourceType.ID.getName(), id)) { return Collections.emptyList(); } - final List declarations = new ArrayList(); + final List result = new ArrayList(); final Collection files = FileBasedIndex.getInstance().getContainingFiles(AndroidIdIndex.INDEX_ID, id, GlobalSearchScope.allScope(myModule.getProject())); final Set fileSet = new HashSet(files); - final PsiManager psiManager = PsiManager.getInstance(myModule.getProject()); for (VirtualFile subdir : getResourceSubdirsToSearchIds()) { for (VirtualFile file : subdir.getChildren()) { if (fileSet.contains(file)) { - final PsiFile psiFile = psiManager.findFile(file); - - if (psiFile instanceof XmlFile) { - psiFile.accept(new XmlRecursiveElementVisitor() { - @Override - public void visitXmlAttributeValue(XmlAttributeValue attributeValue) { - if (AndroidResourceUtil.isIdDeclaration(attributeValue)) { - final String idInAttr = AndroidResourceUtil.getResourceNameByReferenceText(attributeValue.getValue()); - - if (id.equals(idInAttr)) { - declarations.add(attributeValue); - } - } - } - }); - } + result.add(new IdResourceInfo(id, file, myModule.getProject())); } } } - return declarations; + return result; + } + + @NotNull + public List findIdDeclarations(@NotNull String id) { + final List infos = findIdDeclarationInfos(id); + + if (infos.size() == 0) { + return Collections.emptyList(); + } + final List result = new ArrayList(); + + for (IdResourceInfo info : infos) { + final PsiElement element = info.computeXmlElement(); + + if (element != null) { + result.add(element); + } + } + return result; } @NotNull @@ -428,31 +431,55 @@ public abstract class ResourceManager { return findValueResources(resType, resName, true); } + // not recommended to use, because it is too slow @NotNull public List findValueResources(@NotNull String resourceType, @NotNull String resourceName, - boolean distinguishDelimetersInName) { + boolean distinguishDelimitersInName) { + final List resources = findValueResourceInfos(resourceType, resourceName, distinguishDelimitersInName); + final List result = new ArrayList(); + + for (ValueResourceInfoImpl resource : resources) { + final ResourceElement domElement = resource.computeDomElement(); + + if (domElement != null) { + result.add(domElement); + } + } + return result; + } + + @NotNull + public List findValueResourceInfos(@NotNull String resourceType, + @NotNull String resourceName, + boolean distinguishDelimetersInName) { final ResourceType type = ResourceType.getEnum(resourceType); if (type == null) { return Collections.emptyList(); } - final Collection files = FileBasedIndex.getInstance() - .getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, - AndroidValueResourcesIndex.createTypeNameMarkerKey(resourceType, resourceName), - GlobalSearchScope.allScope(myModule.getProject())); + final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject()); + final List> values = FileBasedIndex.getInstance() + .getValues(AndroidValueResourcesIndex.INDEX_ID, AndroidValueResourcesIndex.createTypeNameMarkerKey(resourceType, resourceName), + scope); - if (files.size() == 0) { - return Collections.emptyList(); - } - final Set fileSet = new HashSet(files); - final List result = new ArrayList(); + final Set valueResourceFiles = getAllValueResourceFiles(); + final List result = new ArrayList(); - for (ResourceElement element : getValueResources(resourceType, fileSet)) { - final String name = element.getName().getValue(); + for (Set entrySet : values) { + for (ResourceEntry entry : entrySet) { + final String name = entry.getName(); - if (AndroidUtils.equal(resourceName, name, distinguishDelimetersInName)) { - result.add(element); + if (AndroidUtils.equal(resourceName, name, distinguishDelimetersInName)) { + final Collection files = + FileBasedIndex.getInstance().getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); + + for (VirtualFile file : files) { + if (valueResourceFiles.contains(file)) { + result.add(new ValueResourceInfoImpl(name, type, file, myModule)); + } + } + } } } return result; diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfo.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfo.java new file mode 100644 index 000000000000..7ce2016601f6 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfo.java @@ -0,0 +1,25 @@ +package org.jetbrains.android.resourceManagers; + +import com.android.resources.ResourceType; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.xml.XmlAttributeValue; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public interface ValueResourceInfo { + @Nullable + XmlAttributeValue computeXmlElement(); + + @NotNull + VirtualFile getContainingFile(); + + @NotNull + String getName(); + + @NotNull + ResourceType getType(); + +} diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoBase.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoBase.java new file mode 100644 index 000000000000..6aebd92ad583 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoBase.java @@ -0,0 +1,43 @@ +package org.jetbrains.android.resourceManagers; + +import com.android.resources.ResourceType; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +/** + * @author Eugene.Kudelevsky + */ +abstract class ValueResourceInfoBase implements ValueResourceInfo { + protected final String myName; + protected final ResourceType myType; + protected final VirtualFile myFile; + + protected ValueResourceInfoBase(@NotNull String name, @NotNull ResourceType type, @NotNull VirtualFile file) { + myName = name; + myType = type; + myFile = file; + } + + @NotNull + @Override + public VirtualFile getContainingFile() { + return myFile; + } + + @NotNull + @Override + public String getName() { + return myName; + } + + @NotNull + @Override + public ResourceType getType() { + return myType; + } + + @Override + public String toString() { + return "ANDROID_RESOURCE: " + myType + ", " + myName + ", " + myFile.getPath() + "]"; + } +} diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java new file mode 100644 index 000000000000..4afa5cb8607b --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java @@ -0,0 +1,50 @@ +package org.jetbrains.android.resourceManagers; + +import com.android.resources.ResourceType; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.xml.XmlAttributeValue; +import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.resources.Resources; +import org.jetbrains.android.util.AndroidResourceUtil; +import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Eugene.Kudelevsky + */ +public class ValueResourceInfoImpl extends ValueResourceInfoBase { + private final Module myModule; + + ValueResourceInfoImpl(@NotNull String name, @NotNull ResourceType type, @NotNull VirtualFile file, @NotNull Module module) { + super(name, type, file); + myModule = module; + } + + @Override + public XmlAttributeValue computeXmlElement() { + final ResourceElement element = computeDomElement(); + return element != null ? element.getName().getXmlAttributeValue() : null; + } + + @Nullable + public ResourceElement computeDomElement() { + final Resources resources = AndroidUtils.loadDomElement(myModule, myFile, Resources.class); + if (resources == null) { + return null; + } + final List elements = AndroidResourceUtil.getValueResourcesFromElement(myType.getName(), resources); + + for (ResourceElement element : elements) { + final String name = element.getName().getValue(); + + if (myName.equals(name)) { + return element; + } + } + return null; + } +} From 0357b26c4e93bad629a46213ed590877ca0f9fe7 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 27 Jul 2012 18:41:18 +0400 Subject: [PATCH 13/16] optimize working with android resources --- .../AndroidFindUsagesHandlerFactory.java | 30 +- .../AndroidRenameResourceProcessor.java | 47 +- .../android/AndroidValueResourcesIndex.java | 181 +- .../converters/AndroidResourceReference.java | 57 +- .../LazyValueResourceElementWrapper.java | 103 + .../LocalResourceManager.java | 14 +- .../resourceManagers/ResourceManager.java | 100 +- .../ValueResourceInfoImpl.java | 54 +- .../testData/dom/layout/many_strings.xml | 3002 +++++++++++++++++ .../resourceHighlightingPerformance.xml | 35 + .../layout/resourceNavigationPerformance.xml | 11 + .../android/dom/AndroidLayoutDomTest.java | 66 +- .../dom/AndroidValueResourcesTest.java | 5 +- 13 files changed, 3538 insertions(+), 167 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/dom/wrappers/LazyValueResourceElementWrapper.java create mode 100644 plugins/android/testData/dom/layout/many_strings.xml create mode 100644 plugins/android/testData/dom/layout/resourceHighlightingPerformance.xml create mode 100644 plugins/android/testData/dom/layout/resourceNavigationPerformance.xml diff --git a/plugins/android/src/org/jetbrains/android/AndroidFindUsagesHandlerFactory.java b/plugins/android/src/org/jetbrains/android/AndroidFindUsagesHandlerFactory.java index 5d113eefd434..5a103cc06935 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidFindUsagesHandlerFactory.java +++ b/plugins/android/src/org/jetbrains/android/AndroidFindUsagesHandlerFactory.java @@ -26,6 +26,7 @@ import com.intellij.psi.xml.*; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomManager; import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper; import org.jetbrains.android.dom.wrappers.ResourceElementWrapper; import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper; import org.jetbrains.android.facet.AndroidFacet; @@ -45,21 +46,26 @@ import java.util.List; public class AndroidFindUsagesHandlerFactory extends FindUsagesHandlerFactory { @Override public boolean canFindUsages(@NotNull PsiElement element) { - if (element instanceof XmlAttributeValue) { - XmlAttributeValue value = (XmlAttributeValue)element; + PsiElement element1 = LazyValueResourceElementWrapper.computeLazyElement(element); + if (element1 == null) { + return false; + } + + if (element1 instanceof XmlAttributeValue) { + XmlAttributeValue value = (XmlAttributeValue)element1; if (AndroidResourceUtil.findIdFields(value).length > 0) { return true; } } - element = correctResourceElement(element); - if (element instanceof PsiField) { - return AndroidResourceUtil.isResourceField((PsiField)element); + element1 = correctResourceElement(element1); + if (element1 instanceof PsiField) { + return AndroidResourceUtil.isResourceField((PsiField)element1); } - else if (element instanceof PsiFile) { - return AndroidResourceUtil.findResourceFieldsForFileResource((PsiFile)element, true).length > 0; + else if (element1 instanceof PsiFile) { + return AndroidResourceUtil.findResourceFieldsForFileResource((PsiFile)element1, true).length > 0; } - else if (element instanceof XmlTag) { - return AndroidResourceUtil.findResourceFieldsForValueResource((XmlTag)element, true).length > 0; + else if (element1 instanceof XmlTag) { + return AndroidResourceUtil.findResourceFieldsForValueResource((XmlTag)element1, true).length > 0; } return false; } @@ -101,7 +107,11 @@ public class AndroidFindUsagesHandlerFactory extends FindUsagesHandlerFactory { @Override public FindUsagesHandler createFindUsagesHandler(@NotNull PsiElement element, boolean forHighlightUsages) { - PsiElement e = element; + PsiElement e = LazyValueResourceElementWrapper.computeLazyElement(element); + if (e == null) { + return null; + } + AndroidFacet facet = AndroidFacet.getInstance(e); assert facet != null; if (e instanceof XmlAttributeValue) { diff --git a/plugins/android/src/org/jetbrains/android/AndroidRenameResourceProcessor.java b/plugins/android/src/org/jetbrains/android/AndroidRenameResourceProcessor.java index 5457ad25899b..6c8b800da1e2 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidRenameResourceProcessor.java +++ b/plugins/android/src/org/jetbrains/android/AndroidRenameResourceProcessor.java @@ -41,6 +41,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomManager; import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper; import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.resourceManagers.LocalResourceManager; @@ -67,23 +68,28 @@ public class AndroidRenameResourceProcessor extends RenamePsiElementProcessor { public boolean canProcessElement(@NotNull final PsiElement element) { return ApplicationManager.getApplication().runReadAction(new Computable() { public Boolean compute() { - if (element instanceof PsiFile) { - return AndroidFacet.getInstance(element) != null && AndroidResourceUtil.isInResourceSubdirectory((PsiFile)element, null); + final PsiElement element1 = LazyValueResourceElementWrapper.computeLazyElement(element); + if (element1 == null) { + return false; } - else if (element instanceof PsiField) { - PsiField field = (PsiField)element; + + if (element1 instanceof PsiFile) { + return AndroidFacet.getInstance(element1) != null && AndroidResourceUtil.isInResourceSubdirectory((PsiFile)element1, null); + } + else if (element1 instanceof PsiField) { + PsiField field = (PsiField)element1; if (AndroidResourceUtil.isResourceField(field)) { return AndroidResourceUtil.findResourcesByField(field).size() > 0; } } - else if (element instanceof XmlAttributeValue) { - LocalResourceManager manager = LocalResourceManager.getInstance(element); + else if (element1 instanceof XmlAttributeValue) { + LocalResourceManager manager = LocalResourceManager.getInstance(element1); if (manager != null) { - if (AndroidResourceUtil.isIdDeclaration((XmlAttributeValue)element)) { + if (AndroidResourceUtil.isIdDeclaration((XmlAttributeValue)element1)) { return true; } // then it is value resource - XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class); + XmlTag tag = PsiTreeUtil.getParentOfType(element1, XmlTag.class); return tag != null && manager.getValueResourceType(tag) != null; } } @@ -94,22 +100,29 @@ public class AndroidRenameResourceProcessor extends RenamePsiElementProcessor { @Override public void prepareRenaming(PsiElement element, String newName, Map allRenames) { - AndroidFacet facet = AndroidFacet.getInstance(element); - assert facet != null; - if (element instanceof PsiFile) { - prepareResourceFileRenaming((PsiFile)element, newName, allRenames, facet); + final PsiElement element1 = LazyValueResourceElementWrapper.computeLazyElement(element); + if (element1 == null) { + return; } - else if (element instanceof XmlAttributeValue) { - XmlAttributeValue value = (XmlAttributeValue)element; + + // todo: support renaming alternative value resources + + AndroidFacet facet = AndroidFacet.getInstance(element1); + assert facet != null; + if (element1 instanceof PsiFile) { + prepareResourceFileRenaming((PsiFile)element1, newName, allRenames, facet); + } + else if (element1 instanceof XmlAttributeValue) { + XmlAttributeValue value = (XmlAttributeValue)element1; if (AndroidResourceUtil.isIdDeclaration(value)) { prepareIdRenaming(value, newName, allRenames, facet); } else { - prepareValueResourceRenaming(element, newName, allRenames, facet); + prepareValueResourceRenaming(element1, newName, allRenames, facet); } } - else if (element instanceof PsiField) { - prepareResourceFieldRenaming((PsiField)element, newName, allRenames); + else if (element1 instanceof PsiField) { + prepareResourceFieldRenaming((PsiField)element1, newName, allRenames); } } diff --git a/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java b/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java index 1738f748896a..ee4c1eaba8cd 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java +++ b/plugins/android/src/org/jetbrains/android/AndroidValueResourcesIndex.java @@ -1,9 +1,14 @@ package org.jetbrains.android; +import com.android.resources.ResourceType; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.ex.temp.TempFileSystem; +import com.intellij.psi.PsiFile; +import com.intellij.psi.XmlRecursiveElementVisitor; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.indexing.*; @@ -11,8 +16,9 @@ import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.KeyDescriptor; import com.intellij.util.text.CharArrayUtil; import com.intellij.util.xml.NanoXmlUtil; +import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.ResourceEntry; -import org.jetbrains.android.util.ValueResourcesFileParser; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,8 +32,12 @@ import java.util.Set; /** * @author Eugene.Kudelevsky */ -public class AndroidValueResourcesIndex extends FileBasedIndexExtension> { - public static final ID> INDEX_ID = ID.create("android.value.resources.index"); +public class AndroidValueResourcesIndex extends FileBasedIndexExtension> { + public static final ID> INDEX_ID = ID.create("android.value.resources.index"); + + @NonNls private static final String RESOURCES_ROOT_TAG = "resources"; + @NonNls private static final String NAME_ATTRIBUTE_VALUE = "name"; + @NonNls private static final String TYPE_ATTRIBUTE_VALUE = "type"; private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() { @Override @@ -37,28 +47,54 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension, FileContent> myIndexer = - new DataIndexer, FileContent>() { + private final DataIndexer, FileContent> myIndexer = + new DataIndexer, FileContent>() { @Override @NotNull - public Map> map(FileContent inputData) { - - if (CharArrayUtil.indexOf(inputData.getContentAsText(), "> map(FileContent inputData) { + if (!isSimilarFile(inputData)) { return Collections.emptyMap(); } - final Map> result = new HashMap>(); + final PsiFile file = inputData.getPsiFile(); - NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()), new ValueResourcesFileParser() { - @Override - protected void stop() { - throw new NanoXmlUtil.ParserStoppedException(); - } + if (!(file instanceof XmlFile)) { + return Collections.emptyMap(); + } + final Map> result = new HashMap>(); + file.accept(new XmlRecursiveElementVisitor() { @Override - protected void process(@NotNull ResourceEntry entry) { - result.put(entry, Collections.emptySet()); - addEntryToMap(entry, createTypeMarkerKey(entry.getType()), result); - addEntryToMap(entry, createTypeNameMarkerKey(entry.getType(), entry.getName()), result); + public void visitXmlTag(XmlTag tag) { + super.visitXmlTag(tag); + final String resName = tag.getAttributeValue(NAME_ATTRIBUTE_VALUE); + + if (resName == null) { + return; + } + final String tagName = tag.getName(); + final String resTypeStr; + + if ("item".equals(tagName)) { + resTypeStr = tag.getAttributeValue(TYPE_ATTRIBUTE_VALUE); + } + else { + resTypeStr = AndroidCommonUtils.getResourceTypeByTagName(tagName); + } + final ResourceType resType = resTypeStr != null ? ResourceType.getEnum(resTypeStr) : null; + + if (resType == null) { + return; + } + final int offset = tag.getTextRange().getStartOffset(); + + if (resType == ResourceType.ATTR) { + final XmlTag parentTag = tag.getParentTag(); + final String contextName = parentTag != null ? parentTag.getAttributeValue(NAME_ATTRIBUTE_VALUE) : null; + processResourceEntry(new ResourceEntry(resTypeStr, resName, contextName != null ? contextName : ""), result, offset); + } + else { + processResourceEntry(new ResourceEntry(resTypeStr, resName, ""), result, offset); + } } }); @@ -66,14 +102,40 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension> result) { - Set set = result.get(marker); + private static boolean isSimilarFile(FileContent inputData) { + if (CharArrayUtil.indexOf(inputData.getContentAsText(), "<" + RESOURCES_ROOT_TAG, 0) < 0) { + return false; + } + final boolean[] ourRootTag = {false}; + + NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()), new NanoXmlUtil.IXMLBuilderAdapter() { + @Override + public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) + throws Exception { + ourRootTag[0] = RESOURCES_ROOT_TAG.equals(name) && nsPrefix == null; + stop(); + } + }); + return ourRootTag[0]; + } + + private static void processResourceEntry(@NotNull ResourceEntry entry, + @NotNull Map> result, + int offset) { + final MyResourceInfo info = new MyResourceInfo(entry, offset); + result.put(entry, Collections.singleton(info)); + addEntryToMap(info, createTypeMarkerKey(entry.getType()), result); + addEntryToMap(info, createTypeNameMarkerKey(entry.getType(), entry.getName()), result); + } + + private static void addEntryToMap(MyResourceInfo info, ResourceEntry marker, Map> result) { + Set set = result.get(marker); if (set == null) { - set = new HashSet(); + set = new HashSet(); result.put(marker, set); } - set.add(entry); + set.add(info); } @NotNull @@ -128,33 +190,35 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension> myValueExternalizer = new DataExternalizer>() { + private final DataExternalizer> myValueExternalizer = new DataExternalizer>() { @Override - public void save(DataOutput out, Set value) throws IOException { + public void save(DataOutput out, Set value) throws IOException { out.writeInt(value.size()); - for (ResourceEntry entry : value) { - out.writeUTF(entry.getType()); - out.writeUTF(entry.getName()); - out.writeUTF(entry.getContext()); + for (MyResourceInfo entry : value) { + out.writeUTF(entry.getResourceEntry().getType()); + out.writeUTF(entry.getResourceEntry().getName()); + out.writeUTF(entry.getResourceEntry().getContext()); + out.writeInt(entry.getOffset()); } } @Nullable @Override - public Set read(DataInput in) throws IOException { + public Set read(DataInput in) throws IOException { final int size = in.readInt(); if (size == 0) { return Collections.emptySet(); } - final Set result = new HashSet(size); + final Set result = new HashSet(size); for (int i = 0; i < size; i++) { final String type = in.readUTF(); final String name = in.readUTF(); final String context = in.readUTF(); - result.add(new ResourceEntry(type, name, context)); + final int offset = in.readInt(); + result.add(new MyResourceInfo(new ResourceEntry(type, name, context), offset)); } return result; } @@ -162,13 +226,13 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension> getName() { + public ID> getName() { return INDEX_ID; } @NotNull @Override - public DataIndexer, FileContent> getIndexer() { + public DataIndexer, FileContent> getIndexer() { return myIndexer; } @@ -178,7 +242,7 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension> getValueExternalizer() { + public DataExternalizer> getValueExternalizer() { return myValueExternalizer; } @@ -194,6 +258,53 @@ public class AndroidValueResourcesIndex extends FileBasedIndexExtension collectTargets(myFacet, myResourceValue, elements, files); final List result = new ArrayList(); - + for (PsiFile target : files) { if (target != null) { final PsiFile e = new FileResourceElementWrapper(target); @@ -131,15 +132,15 @@ public class AndroidResourceReference extends PsiReferenceBase.Poly } for (PsiElement target : elements) { - final PsiElement e = target instanceof NavigationItem && target instanceof XmlAttributeValue + /*final PsiElement e = target instanceof NavigationItem && target instanceof XmlAttributeValue ? new ValueResourceElementWrapper((XmlAttributeValue)target) - : target; - result.add(new PsiElementResolveResult(e)); + : target;*/ + result.add(new PsiElementResolveResult(target)); } return result.toArray(new ResolveResult[result.size()]); } - private static void collectTargets(AndroidFacet facet, ResourceValue resValue, List elements, List files) { + private void collectTargets(AndroidFacet facet, ResourceValue resValue, List elements, List files) { String resType = resValue.getResourceType(); if (resType == null) { return; @@ -148,15 +149,13 @@ public class AndroidResourceReference extends PsiReferenceBase.Poly if (manager != null) { String resName = resValue.getResourceName(); if (resName != null) { - List valueResources = manager.findValueResources(resType, resName, false); - for (ResourceElement resource : valueResources) { - elements.add(resource.getName().getXmlAttributeValue()); + List valueResources = manager.findValueResourceInfos(resType, resName, false); + + for (final ValueResourceInfo resource : valueResources) { + elements.add(new LazyValueResourceElementWrapper(resource, myElement)); } if (resType.equals("id")) { - List idAttrs = manager.findIdDeclarations(resName); - if (idAttrs != null) { - elements.addAll(idAttrs); - } + elements.addAll(manager.findIdDeclarations(resName)); } if (elements.size() == 0) { files.addAll(manager.findResourceFiles(resType, resName, false)); @@ -164,4 +163,32 @@ public class AndroidResourceReference extends PsiReferenceBase.Poly } } } + + @Override + public boolean isReferenceTo(PsiElement element) { + final ResolveResult[] results = multiResolve(false); + final PsiFile psiFile = element.getContainingFile(); + final VirtualFile vFile = psiFile != null ? psiFile.getVirtualFile() : null; + + for (ResolveResult result : results) { + final PsiElement target = result.getElement(); + + if (element.getManager().areElementsEquivalent(target, element)) { + return true; + } + + if (target instanceof LazyValueResourceElementWrapper && vFile != null) { + final ValueResourceInfo info = ((LazyValueResourceElementWrapper)target).getResourceInfo(); + + if (info.getContainingFile().equals(vFile)) { + final XmlAttributeValue realTarget = info.computeXmlElement(); + + if (element.getManager().areElementsEquivalent(realTarget, element)) { + return true; + } + } + } + } + return false; + } } diff --git a/plugins/android/src/org/jetbrains/android/dom/wrappers/LazyValueResourceElementWrapper.java b/plugins/android/src/org/jetbrains/android/dom/wrappers/LazyValueResourceElementWrapper.java new file mode 100644 index 000000000000..5ac56ab7e1a9 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/dom/wrappers/LazyValueResourceElementWrapper.java @@ -0,0 +1,103 @@ +package org.jetbrains.android.dom.wrappers; + +import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiTarget; +import com.intellij.psi.impl.RenameableFakePsiElement; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.android.resourceManagers.ValueResourceInfo; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** +* @author Eugene.Kudelevsky +*/ +public class LazyValueResourceElementWrapper extends RenameableFakePsiElement implements PsiTarget { + private final ValueResourceInfo myResourceInfo; + private final PsiElement myParent; + + public LazyValueResourceElementWrapper(@NotNull ValueResourceInfo resourceInfo, @NotNull PsiElement parent) { + super(parent); + myParent = parent; + myResourceInfo = resourceInfo; + } + + @Override + public String getName() { + return myResourceInfo.getName(); + } + + @Nullable + @Override + public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { + final XmlAttributeValue element = computeElement(); + if (element == null) { + throw new IncorrectOperationException( + "Cannot find resource '" + myResourceInfo.getName() + "' in file " + myResourceInfo.getContainingFile().getPath()); + } + return new ValueResourceElementWrapper(element).setName(name); + } + + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Nullable + public String getPresentableText() { + final String name = myResourceInfo.getName(); + final VirtualFile resDir = myResourceInfo.getContainingFile().getParent(); + if (resDir == null) { + return name; + } + return name + " (" + resDir.getName() + ')'; + } + + public String getLocationString() { + return null; + } + + public Icon getIcon(boolean open) { + return null; + } + }; + } + + @Nullable + public XmlAttributeValue computeElement() { + return myResourceInfo.computeXmlElement(); + } + + @NotNull + @Override + public PsiElement getNavigationElement() { + final XmlAttributeValue element = myResourceInfo.computeXmlElement(); + return element != null ? element : myParent; + } + + @NotNull + public ValueResourceInfo getResourceInfo() { + return myResourceInfo; + } + + @Override + public String getTypeName() { + return "Android Value Resource"; + } + + @Override + public Icon getIcon() { + return null; + } + + @Nullable + public static PsiElement computeLazyElement(PsiElement element) { + if (element instanceof LazyValueResourceElementWrapper) { + element = ((LazyValueResourceElementWrapper)element).computeElement(); + } + return element; + } +} diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java index a1c39cdd098f..6549540335e9 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java @@ -141,21 +141,21 @@ public class LocalResourceManager extends ResourceManager { for (ResourceType resourceType : AndroidResourceUtil.ALL_VALUE_RESOURCE_TYPES) { final ResourceEntry typeMarkerEntry = AndroidValueResourcesIndex.createTypeMarkerKey(resourceType.getName()); - for (Set entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) { - for (ResourceEntry entry : entrySet) { - final Collection files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); - - for (VirtualFile file : files) { + index.processValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, null, new FileBasedIndex.ValueProcessor>() { + @Override + public boolean process(VirtualFile file, Set infos) { + for (AndroidValueResourcesIndex.MyResourceInfo info : infos) { Set resourcesInFile = file2Types.get(file); if (resourcesInFile == null) { resourcesInFile = new HashSet(); file2Types.put(file, resourcesInFile); } - resourcesInFile.add(entry.getType()); + resourcesInFile.add(info.getResourceEntry().getType()); } + return true; } - } + }, scope); } final Set result = new HashSet(); diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java index 1713ac0463b3..286402250b95 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java @@ -23,11 +23,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; @@ -280,27 +279,28 @@ public abstract class ResourceManager { if (type == null) { return Collections.emptyList(); } - final FileBasedIndex index = FileBasedIndex.getInstance(); final ResourceEntry typeMarkerEntry = AndroidValueResourcesIndex.createTypeMarkerKey(resourceType); final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject()); final Map> file2resourceSet = new HashMap>(); - for (Set entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) { - for (ResourceEntry entry : entrySet) { - final Collection files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); - for (VirtualFile file : files) { + index.processValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, null, new FileBasedIndex.ValueProcessor>() { + @Override + public boolean process(VirtualFile file, Set infos) { + for (AndroidValueResourcesIndex.MyResourceInfo info : infos) { Set resourcesInFile = file2resourceSet.get(file); if (resourcesInFile == null) { resourcesInFile = new HashSet(); file2resourceSet.put(file, resourcesInFile); } - resourcesInFile.add(entry); + resourcesInFile.add(info.getResourceEntry()); } + return true; } - } + }, scope); + final List result = new ArrayList(); for (VirtualFile file : getAllValueResourceFiles()) { @@ -333,43 +333,40 @@ public abstract class ResourceManager { // searches only declarations such as "@+id/..." @NotNull - public List findIdDeclarationInfos(@NotNull final String id) { + public List findIdDeclarations(@NotNull final String id) { if (!isResourcePublic(ResourceType.ID.getName(), id)) { return Collections.emptyList(); } - final List result = new ArrayList(); + final List declarations = new ArrayList(); final Collection files = FileBasedIndex.getInstance().getContainingFiles(AndroidIdIndex.INDEX_ID, id, GlobalSearchScope.allScope(myModule.getProject())); final Set fileSet = new HashSet(files); + final PsiManager psiManager = PsiManager.getInstance(myModule.getProject()); for (VirtualFile subdir : getResourceSubdirsToSearchIds()) { for (VirtualFile file : subdir.getChildren()) { if (fileSet.contains(file)) { - result.add(new IdResourceInfo(id, file, myModule.getProject())); + final PsiFile psiFile = psiManager.findFile(file); + + if (psiFile instanceof XmlFile) { + psiFile.accept(new XmlRecursiveElementVisitor() { + @Override + public void visitXmlAttributeValue(XmlAttributeValue attributeValue) { + if (AndroidResourceUtil.isIdDeclaration(attributeValue)) { + final String idInAttr = AndroidResourceUtil.getResourceNameByReferenceText(attributeValue.getValue()); + + if (id.equals(idInAttr)) { + declarations.add(attributeValue); + } + } + } + }); + } } } } - return result; - } - - @NotNull - public List findIdDeclarations(@NotNull String id) { - final List infos = findIdDeclarationInfos(id); - - if (infos.size() == 0) { - return Collections.emptyList(); - } - final List result = new ArrayList(); - - for (IdResourceInfo info : infos) { - final PsiElement element = info.computeXmlElement(); - - if (element != null) { - result.add(element); - } - } - return result; + return declarations; } @NotNull @@ -451,37 +448,36 @@ public abstract class ResourceManager { @NotNull public List findValueResourceInfos(@NotNull String resourceType, - @NotNull String resourceName, - boolean distinguishDelimetersInName) { + @NotNull final String resourceName, + final boolean distinguishDelimetersInName) { final ResourceType type = ResourceType.getEnum(resourceType); - if (type == null) { + if (type == null || !AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(type)) { + // do not search for styleables and atts here because we don't want to resolve references to it return Collections.emptyList(); } + new HashMap>(); final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject()); - final List> values = FileBasedIndex.getInstance() - .getValues(AndroidValueResourcesIndex.INDEX_ID, AndroidValueResourcesIndex.createTypeNameMarkerKey(resourceType, resourceName), - scope); - - final Set valueResourceFiles = getAllValueResourceFiles(); final List result = new ArrayList(); + final Set valueResourceFiles = getAllValueResourceFiles(); - for (Set entrySet : values) { - for (ResourceEntry entry : entrySet) { - final String name = entry.getName(); + FileBasedIndex.getInstance() + .processValues(AndroidValueResourcesIndex.INDEX_ID, AndroidValueResourcesIndex.createTypeNameMarkerKey(resourceType, resourceName), + null, new FileBasedIndex.ValueProcessor>() { + @Override + public boolean process(VirtualFile file, Set infos) { + for (AndroidValueResourcesIndex.MyResourceInfo info : infos) { + final String name = info.getResourceEntry().getName(); - if (AndroidUtils.equal(resourceName, name, distinguishDelimetersInName)) { - final Collection files = - FileBasedIndex.getInstance().getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope); - - for (VirtualFile file : files) { + if (AndroidUtils.equal(resourceName, name, distinguishDelimetersInName)) { if (valueResourceFiles.contains(file)) { - result.add(new ValueResourceInfoImpl(name, type, file, myModule)); + result.add(new ValueResourceInfoImpl(info.getResourceEntry().getName(), type, file, myModule, info.getOffset())); } } } + return true; } - } + }, scope); return result; } } diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java index 4afa5cb8607b..1998e3bb20f1 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ValueResourceInfoImpl.java @@ -2,49 +2,67 @@ package org.jetbrains.android.resourceManagers; import com.android.resources.ResourceType; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.xml.DomElement; +import com.intellij.util.xml.DomManager; +import org.jetbrains.android.dom.resources.Item; import org.jetbrains.android.dom.resources.ResourceElement; -import org.jetbrains.android.dom.resources.Resources; -import org.jetbrains.android.util.AndroidResourceUtil; -import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * @author Eugene.Kudelevsky */ public class ValueResourceInfoImpl extends ValueResourceInfoBase { private final Module myModule; + private final int myOffset; - ValueResourceInfoImpl(@NotNull String name, @NotNull ResourceType type, @NotNull VirtualFile file, @NotNull Module module) { + ValueResourceInfoImpl(@NotNull String name, @NotNull ResourceType type, @NotNull VirtualFile file, @NotNull Module module, int offset) { super(name, type, file); myModule = module; + myOffset = offset; } @Override public XmlAttributeValue computeXmlElement() { - final ResourceElement element = computeDomElement(); - return element != null ? element.getName().getXmlAttributeValue() : null; + final ResourceElement resDomElement = computeDomElement(); + return resDomElement != null ? resDomElement.getName().getXmlAttributeValue() : null; } @Nullable public ResourceElement computeDomElement() { - final Resources resources = AndroidUtils.loadDomElement(myModule, myFile, Resources.class); - if (resources == null) { + final Project project = myModule.getProject(); + final PsiFile file = PsiManager.getInstance(project).findFile(myFile); + + if (!(file instanceof XmlFile)) { return null; } - final List elements = AndroidResourceUtil.getValueResourcesFromElement(myType.getName(), resources); + final XmlTag tag = PsiTreeUtil.findElementOfClassAtOffset(file, myOffset, XmlTag.class, true); - for (ResourceElement element : elements) { - final String name = element.getName().getValue(); - - if (myName.equals(name)) { - return element; - } + if (tag == null) { + return null; } - return null; + final DomElement domElement = DomManager.getDomManager(project).getDomElement(tag); + if (!(domElement instanceof ResourceElement)) { + return null; + } + final String resType = domElement instanceof Item + ? ((Item)domElement).getType().getStringValue() + : AndroidCommonUtils.getResourceTypeByTagName(tag.getName()); + + if (!myType.getName().equals(resType)) { + return null; + } + final ResourceElement resDomElement = (ResourceElement)domElement; + final String resName = ((ResourceElement)domElement).getName().getStringValue(); + return myName.equals(resName) ? resDomElement : null; } } diff --git a/plugins/android/testData/dom/layout/many_strings.xml b/plugins/android/testData/dom/layout/many_strings.xml new file mode 100644 index 000000000000..73860ad3039e --- /dev/null +++ b/plugins/android/testData/dom/layout/many_strings.xml @@ -0,0 +1,3002 @@ + + Hello, world 1 + Hello, world 2 + Hello, world 3 + Hello, world 4 + Hello, world 5 + Hello, world 6 + Hello, world 7 + Hello, world 8 + Hello, world 9 + Hello, world 10 + Hello, world 11 + Hello, world 12 + Hello, world 13 + Hello, world 14 + Hello, world 15 + Hello, world 16 + Hello, world 17 + Hello, world 18 + Hello, world 19 + Hello, world 20 + Hello, world 21 + Hello, world 22 + Hello, world 23 + Hello, world 24 + Hello, world 25 + Hello, world 26 + Hello, world 27 + Hello, world 28 + Hello, world 29 + Hello, world 30 + Hello, world 31 + Hello, world 32 + Hello, world 33 + Hello, world 34 + Hello, world 35 + Hello, world 36 + Hello, world 37 + Hello, world 38 + Hello, world 39 + Hello, world 40 + Hello, world 41 + Hello, world 42 + Hello, world 43 + Hello, world 44 + Hello, world 45 + Hello, world 46 + Hello, world 47 + Hello, world 48 + Hello, world 49 + Hello, world 50 + Hello, world 51 + Hello, world 52 + Hello, world 53 + Hello, world 54 + Hello, world 55 + Hello, world 56 + Hello, world 57 + Hello, world 58 + Hello, world 59 + Hello, world 60 + Hello, world 61 + Hello, world 62 + Hello, world 63 + Hello, world 64 + Hello, world 65 + Hello, world 66 + Hello, world 67 + Hello, world 68 + Hello, world 69 + Hello, world 70 + Hello, world 71 + Hello, world 72 + Hello, world 73 + Hello, world 74 + Hello, world 75 + Hello, world 76 + Hello, world 77 + Hello, world 78 + Hello, world 79 + Hello, world 80 + Hello, world 81 + Hello, world 82 + Hello, world 83 + Hello, world 84 + Hello, world 85 + Hello, world 86 + Hello, world 87 + Hello, world 88 + Hello, world 89 + Hello, world 90 + Hello, world 91 + Hello, world 92 + Hello, world 93 + Hello, world 94 + Hello, world 95 + Hello, world 96 + Hello, world 97 + Hello, world 98 + Hello, world 99 + Hello, world 100 + Hello, world 101 + Hello, world 102 + Hello, world 103 + Hello, world 104 + Hello, world 105 + Hello, world 106 + Hello, world 107 + Hello, world 108 + Hello, world 109 + Hello, world 110 + Hello, world 111 + Hello, world 112 + Hello, world 113 + Hello, world 114 + Hello, world 115 + Hello, world 116 + Hello, world 117 + Hello, world 118 + Hello, world 119 + Hello, world 120 + Hello, world 121 + Hello, world 122 + Hello, world 123 + Hello, world 124 + Hello, world 125 + Hello, world 126 + Hello, world 127 + Hello, world 128 + Hello, world 129 + Hello, world 130 + Hello, world 131 + Hello, world 132 + Hello, world 133 + Hello, world 134 + Hello, world 135 + Hello, world 136 + Hello, world 137 + Hello, world 138 + Hello, world 139 + Hello, world 140 + Hello, world 141 + Hello, world 142 + Hello, world 143 + Hello, world 144 + Hello, world 145 + Hello, world 146 + Hello, world 147 + Hello, world 148 + Hello, world 149 + Hello, world 150 + Hello, world 151 + Hello, world 152 + Hello, world 153 + Hello, world 154 + Hello, world 155 + Hello, world 156 + Hello, world 157 + Hello, world 158 + Hello, world 159 + Hello, world 160 + Hello, world 161 + Hello, world 162 + Hello, world 163 + Hello, world 164 + Hello, world 165 + Hello, world 166 + Hello, world 167 + Hello, world 168 + Hello, world 169 + Hello, world 170 + Hello, world 171 + Hello, world 172 + Hello, world 173 + Hello, world 174 + Hello, world 175 + Hello, world 176 + Hello, world 177 + Hello, world 178 + Hello, world 179 + Hello, world 180 + Hello, world 181 + Hello, world 182 + Hello, world 183 + Hello, world 184 + Hello, world 185 + Hello, world 186 + Hello, world 187 + Hello, world 188 + Hello, world 189 + Hello, world 190 + Hello, world 191 + Hello, world 192 + Hello, world 193 + Hello, world 194 + Hello, world 195 + Hello, world 196 + Hello, world 197 + Hello, world 198 + Hello, world 199 + Hello, world 200 + Hello, world 201 + Hello, world 202 + Hello, world 203 + Hello, world 204 + Hello, world 205 + Hello, world 206 + Hello, world 207 + Hello, world 208 + Hello, world 209 + Hello, world 210 + Hello, world 211 + Hello, world 212 + Hello, world 213 + Hello, world 214 + Hello, world 215 + Hello, world 216 + Hello, world 217 + Hello, world 218 + Hello, world 219 + Hello, world 220 + Hello, world 221 + Hello, world 222 + Hello, world 223 + Hello, world 224 + Hello, world 225 + Hello, world 226 + Hello, world 227 + Hello, world 228 + Hello, world 229 + Hello, world 230 + Hello, world 231 + Hello, world 232 + Hello, world 233 + Hello, world 234 + Hello, world 235 + Hello, world 236 + Hello, world 237 + Hello, world 238 + Hello, world 239 + Hello, world 240 + Hello, world 241 + Hello, world 242 + Hello, world 243 + Hello, world 244 + Hello, world 245 + Hello, world 246 + Hello, world 247 + Hello, world 248 + Hello, world 249 + Hello, world 250 + Hello, world 251 + Hello, world 252 + Hello, world 253 + Hello, world 254 + Hello, world 255 + Hello, world 256 + Hello, world 257 + Hello, world 258 + Hello, world 259 + Hello, world 260 + Hello, world 261 + Hello, world 262 + Hello, world 263 + Hello, world 264 + Hello, world 265 + Hello, world 266 + Hello, world 267 + Hello, world 268 + Hello, world 269 + Hello, world 270 + Hello, world 271 + Hello, world 272 + Hello, world 273 + Hello, world 274 + Hello, world 275 + Hello, world 276 + Hello, world 277 + Hello, world 278 + Hello, world 279 + Hello, world 280 + Hello, world 281 + Hello, world 282 + Hello, world 283 + Hello, world 284 + Hello, world 285 + Hello, world 286 + Hello, world 287 + Hello, world 288 + Hello, world 289 + Hello, world 290 + Hello, world 291 + Hello, world 292 + Hello, world 293 + Hello, world 294 + Hello, world 295 + Hello, world 296 + Hello, world 297 + Hello, world 298 + Hello, world 299 + Hello, world 300 + Hello, world 301 + Hello, world 302 + Hello, world 303 + Hello, world 304 + Hello, world 305 + Hello, world 306 + Hello, world 307 + Hello, world 308 + Hello, world 309 + Hello, world 310 + Hello, world 311 + Hello, world 312 + Hello, world 313 + Hello, world 314 + Hello, world 315 + Hello, world 316 + Hello, world 317 + Hello, world 318 + Hello, world 319 + Hello, world 320 + Hello, world 321 + Hello, world 322 + Hello, world 323 + Hello, world 324 + Hello, world 325 + Hello, world 326 + Hello, world 327 + Hello, world 328 + Hello, world 329 + Hello, world 330 + Hello, world 331 + Hello, world 332 + Hello, world 333 + Hello, world 334 + Hello, world 335 + Hello, world 336 + Hello, world 337 + Hello, world 338 + Hello, world 339 + Hello, world 340 + Hello, world 341 + Hello, world 342 + Hello, world 343 + Hello, world 344 + Hello, world 345 + Hello, world 346 + Hello, world 347 + Hello, world 348 + Hello, world 349 + Hello, world 350 + Hello, world 351 + Hello, world 352 + Hello, world 353 + Hello, world 354 + Hello, world 355 + Hello, world 356 + Hello, world 357 + Hello, world 358 + Hello, world 359 + Hello, world 360 + Hello, world 361 + Hello, world 362 + Hello, world 363 + Hello, world 364 + Hello, world 365 + Hello, world 366 + Hello, world 367 + Hello, world 368 + Hello, world 369 + Hello, world 370 + Hello, world 371 + Hello, world 372 + Hello, world 373 + Hello, world 374 + Hello, world 375 + Hello, world 376 + Hello, world 377 + Hello, world 378 + Hello, world 379 + Hello, world 380 + Hello, world 381 + Hello, world 382 + Hello, world 383 + Hello, world 384 + Hello, world 385 + Hello, world 386 + Hello, world 387 + Hello, world 388 + Hello, world 389 + Hello, world 390 + Hello, world 391 + Hello, world 392 + Hello, world 393 + Hello, world 394 + Hello, world 395 + Hello, world 396 + Hello, world 397 + Hello, world 398 + Hello, world 399 + Hello, world 400 + Hello, world 401 + Hello, world 402 + Hello, world 403 + Hello, world 404 + Hello, world 405 + Hello, world 406 + Hello, world 407 + Hello, world 408 + Hello, world 409 + Hello, world 410 + Hello, world 411 + Hello, world 412 + Hello, world 413 + Hello, world 414 + Hello, world 415 + Hello, world 416 + Hello, world 417 + Hello, world 418 + Hello, world 419 + Hello, world 420 + Hello, world 421 + Hello, world 422 + Hello, world 423 + Hello, world 424 + Hello, world 425 + Hello, world 426 + Hello, world 427 + Hello, world 428 + Hello, world 429 + Hello, world 430 + Hello, world 431 + Hello, world 432 + Hello, world 433 + Hello, world 434 + Hello, world 435 + Hello, world 436 + Hello, world 437 + Hello, world 438 + Hello, world 439 + Hello, world 440 + Hello, world 441 + Hello, world 442 + Hello, world 443 + Hello, world 444 + Hello, world 445 + Hello, world 446 + Hello, world 447 + Hello, world 448 + Hello, world 449 + Hello, world 450 + Hello, world 451 + Hello, world 452 + Hello, world 453 + Hello, world 454 + Hello, world 455 + Hello, world 456 + Hello, world 457 + Hello, world 458 + Hello, world 459 + Hello, world 460 + Hello, world 461 + Hello, world 462 + Hello, world 463 + Hello, world 464 + Hello, world 465 + Hello, world 466 + Hello, world 467 + Hello, world 468 + Hello, world 469 + Hello, world 470 + Hello, world 471 + Hello, world 472 + Hello, world 473 + Hello, world 474 + Hello, world 475 + Hello, world 476 + Hello, world 477 + Hello, world 478 + Hello, world 479 + Hello, world 480 + Hello, world 481 + Hello, world 482 + Hello, world 483 + Hello, world 484 + Hello, world 485 + Hello, world 486 + Hello, world 487 + Hello, world 488 + Hello, world 489 + Hello, world 490 + Hello, world 491 + Hello, world 492 + Hello, world 493 + Hello, world 494 + Hello, world 495 + Hello, world 496 + Hello, world 497 + Hello, world 498 + Hello, world 499 + Hello, world 500 + Hello, world 501 + Hello, world 502 + Hello, world 503 + Hello, world 504 + Hello, world 505 + Hello, world 506 + Hello, world 507 + Hello, world 508 + Hello, world 509 + Hello, world 510 + Hello, world 511 + Hello, world 512 + Hello, world 513 + Hello, world 514 + Hello, world 515 + Hello, world 516 + Hello, world 517 + Hello, world 518 + Hello, world 519 + Hello, world 520 + Hello, world 521 + Hello, world 522 + Hello, world 523 + Hello, world 524 + Hello, world 525 + Hello, world 526 + Hello, world 527 + Hello, world 528 + Hello, world 529 + Hello, world 530 + Hello, world 531 + Hello, world 532 + Hello, world 533 + Hello, world 534 + Hello, world 535 + Hello, world 536 + Hello, world 537 + Hello, world 538 + Hello, world 539 + Hello, world 540 + Hello, world 541 + Hello, world 542 + Hello, world 543 + Hello, world 544 + Hello, world 545 + Hello, world 546 + Hello, world 547 + Hello, world 548 + Hello, world 549 + Hello, world 550 + Hello, world 551 + Hello, world 552 + Hello, world 553 + Hello, world 554 + Hello, world 555 + Hello, world 556 + Hello, world 557 + Hello, world 558 + Hello, world 559 + Hello, world 560 + Hello, world 561 + Hello, world 562 + Hello, world 563 + Hello, world 564 + Hello, world 565 + Hello, world 566 + Hello, world 567 + Hello, world 568 + Hello, world 569 + Hello, world 570 + Hello, world 571 + Hello, world 572 + Hello, world 573 + Hello, world 574 + Hello, world 575 + Hello, world 576 + Hello, world 577 + Hello, world 578 + Hello, world 579 + Hello, world 580 + Hello, world 581 + Hello, world 582 + Hello, world 583 + Hello, world 584 + Hello, world 585 + Hello, world 586 + Hello, world 587 + Hello, world 588 + Hello, world 589 + Hello, world 590 + Hello, world 591 + Hello, world 592 + Hello, world 593 + Hello, world 594 + Hello, world 595 + Hello, world 596 + Hello, world 597 + Hello, world 598 + Hello, world 599 + Hello, world 600 + Hello, world 601 + Hello, world 602 + Hello, world 603 + Hello, world 604 + Hello, world 605 + Hello, world 606 + Hello, world 607 + Hello, world 608 + Hello, world 609 + Hello, world 610 + Hello, world 611 + Hello, world 612 + Hello, world 613 + Hello, world 614 + Hello, world 615 + Hello, world 616 + Hello, world 617 + Hello, world 618 + Hello, world 619 + Hello, world 620 + Hello, world 621 + Hello, world 622 + Hello, world 623 + Hello, world 624 + Hello, world 625 + Hello, world 626 + Hello, world 627 + Hello, world 628 + Hello, world 629 + Hello, world 630 + Hello, world 631 + Hello, world 632 + Hello, world 633 + Hello, world 634 + Hello, world 635 + Hello, world 636 + Hello, world 637 + Hello, world 638 + Hello, world 639 + Hello, world 640 + Hello, world 641 + Hello, world 642 + Hello, world 643 + Hello, world 644 + Hello, world 645 + Hello, world 646 + Hello, world 647 + Hello, world 648 + Hello, world 649 + Hello, world 650 + Hello, world 651 + Hello, world 652 + Hello, world 653 + Hello, world 654 + Hello, world 655 + Hello, world 656 + Hello, world 657 + Hello, world 658 + Hello, world 659 + Hello, world 660 + Hello, world 661 + Hello, world 662 + Hello, world 663 + Hello, world 664 + Hello, world 665 + Hello, world 666 + Hello, world 667 + Hello, world 668 + Hello, world 669 + Hello, world 670 + Hello, world 671 + Hello, world 672 + Hello, world 673 + Hello, world 674 + Hello, world 675 + Hello, world 676 + Hello, world 677 + Hello, world 678 + Hello, world 679 + Hello, world 680 + Hello, world 681 + Hello, world 682 + Hello, world 683 + Hello, world 684 + Hello, world 685 + Hello, world 686 + Hello, world 687 + Hello, world 688 + Hello, world 689 + Hello, world 690 + Hello, world 691 + Hello, world 692 + Hello, world 693 + Hello, world 694 + Hello, world 695 + Hello, world 696 + Hello, world 697 + Hello, world 698 + Hello, world 699 + Hello, world 700 + Hello, world 701 + Hello, world 702 + Hello, world 703 + Hello, world 704 + Hello, world 705 + Hello, world 706 + Hello, world 707 + Hello, world 708 + Hello, world 709 + Hello, world 710 + Hello, world 711 + Hello, world 712 + Hello, world 713 + Hello, world 714 + Hello, world 715 + Hello, world 716 + Hello, world 717 + Hello, world 718 + Hello, world 719 + Hello, world 720 + Hello, world 721 + Hello, world 722 + Hello, world 723 + Hello, world 724 + Hello, world 725 + Hello, world 726 + Hello, world 727 + Hello, world 728 + Hello, world 729 + Hello, world 730 + Hello, world 731 + Hello, world 732 + Hello, world 733 + Hello, world 734 + Hello, world 735 + Hello, world 736 + Hello, world 737 + Hello, world 738 + Hello, world 739 + Hello, world 740 + Hello, world 741 + Hello, world 742 + Hello, world 743 + Hello, world 744 + Hello, world 745 + Hello, world 746 + Hello, world 747 + Hello, world 748 + Hello, world 749 + Hello, world 750 + Hello, world 751 + Hello, world 752 + Hello, world 753 + Hello, world 754 + Hello, world 755 + Hello, world 756 + Hello, world 757 + Hello, world 758 + Hello, world 759 + Hello, world 760 + Hello, world 761 + Hello, world 762 + Hello, world 763 + Hello, world 764 + Hello, world 765 + Hello, world 766 + Hello, world 767 + Hello, world 768 + Hello, world 769 + Hello, world 770 + Hello, world 771 + Hello, world 772 + Hello, world 773 + Hello, world 774 + Hello, world 775 + Hello, world 776 + Hello, world 777 + Hello, world 778 + Hello, world 779 + Hello, world 780 + Hello, world 781 + Hello, world 782 + Hello, world 783 + Hello, world 784 + Hello, world 785 + Hello, world 786 + Hello, world 787 + Hello, world 788 + Hello, world 789 + Hello, world 790 + Hello, world 791 + Hello, world 792 + Hello, world 793 + Hello, world 794 + Hello, world 795 + Hello, world 796 + Hello, world 797 + Hello, world 798 + Hello, world 799 + Hello, world 800 + Hello, world 801 + Hello, world 802 + Hello, world 803 + Hello, world 804 + Hello, world 805 + Hello, world 806 + Hello, world 807 + Hello, world 808 + Hello, world 809 + Hello, world 810 + Hello, world 811 + Hello, world 812 + Hello, world 813 + Hello, world 814 + Hello, world 815 + Hello, world 816 + Hello, world 817 + Hello, world 818 + Hello, world 819 + Hello, world 820 + Hello, world 821 + Hello, world 822 + Hello, world 823 + Hello, world 824 + Hello, world 825 + Hello, world 826 + Hello, world 827 + Hello, world 828 + Hello, world 829 + Hello, world 830 + Hello, world 831 + Hello, world 832 + Hello, world 833 + Hello, world 834 + Hello, world 835 + Hello, world 836 + Hello, world 837 + Hello, world 838 + Hello, world 839 + Hello, world 840 + Hello, world 841 + Hello, world 842 + Hello, world 843 + Hello, world 844 + Hello, world 845 + Hello, world 846 + Hello, world 847 + Hello, world 848 + Hello, world 849 + Hello, world 850 + Hello, world 851 + Hello, world 852 + Hello, world 853 + Hello, world 854 + Hello, world 855 + Hello, world 856 + Hello, world 857 + Hello, world 858 + Hello, world 859 + Hello, world 860 + Hello, world 861 + Hello, world 862 + Hello, world 863 + Hello, world 864 + Hello, world 865 + Hello, world 866 + Hello, world 867 + Hello, world 868 + Hello, world 869 + Hello, world 870 + Hello, world 871 + Hello, world 872 + Hello, world 873 + Hello, world 874 + Hello, world 875 + Hello, world 876 + Hello, world 877 + Hello, world 878 + Hello, world 879 + Hello, world 880 + Hello, world 881 + Hello, world 882 + Hello, world 883 + Hello, world 884 + Hello, world 885 + Hello, world 886 + Hello, world 887 + Hello, world 888 + Hello, world 889 + Hello, world 890 + Hello, world 891 + Hello, world 892 + Hello, world 893 + Hello, world 894 + Hello, world 895 + Hello, world 896 + Hello, world 897 + Hello, world 898 + Hello, world 899 + Hello, world 900 + Hello, world 901 + Hello, world 902 + Hello, world 903 + Hello, world 904 + Hello, world 905 + Hello, world 906 + Hello, world 907 + Hello, world 908 + Hello, world 909 + Hello, world 910 + Hello, world 911 + Hello, world 912 + Hello, world 913 + Hello, world 914 + Hello, world 915 + Hello, world 916 + Hello, world 917 + Hello, world 918 + Hello, world 919 + Hello, world 920 + Hello, world 921 + Hello, world 922 + Hello, world 923 + Hello, world 924 + Hello, world 925 + Hello, world 926 + Hello, world 927 + Hello, world 928 + Hello, world 929 + Hello, world 930 + Hello, world 931 + Hello, world 932 + Hello, world 933 + Hello, world 934 + Hello, world 935 + Hello, world 936 + Hello, world 937 + Hello, world 938 + Hello, world 939 + Hello, world 940 + Hello, world 941 + Hello, world 942 + Hello, world 943 + Hello, world 944 + Hello, world 945 + Hello, world 946 + Hello, world 947 + Hello, world 948 + Hello, world 949 + Hello, world 950 + Hello, world 951 + Hello, world 952 + Hello, world 953 + Hello, world 954 + Hello, world 955 + Hello, world 956 + Hello, world 957 + Hello, world 958 + Hello, world 959 + Hello, world 960 + Hello, world 961 + Hello, world 962 + Hello, world 963 + Hello, world 964 + Hello, world 965 + Hello, world 966 + Hello, world 967 + Hello, world 968 + Hello, world 969 + Hello, world 970 + Hello, world 971 + Hello, world 972 + Hello, world 973 + Hello, world 974 + Hello, world 975 + Hello, world 976 + Hello, world 977 + Hello, world 978 + Hello, world 979 + Hello, world 980 + Hello, world 981 + Hello, world 982 + Hello, world 983 + Hello, world 984 + Hello, world 985 + Hello, world 986 + Hello, world 987 + Hello, world 988 + Hello, world 989 + Hello, world 990 + Hello, world 991 + Hello, world 992 + Hello, world 993 + Hello, world 994 + Hello, world 995 + Hello, world 996 + Hello, world 997 + Hello, world 998 + Hello, world 999 + Hello, world 1000 + Hello, world 1001 + Hello, world 1002 + Hello, world 1003 + Hello, world 1004 + Hello, world 1005 + Hello, world 1006 + Hello, world 1007 + Hello, world 1008 + Hello, world 1009 + Hello, world 1010 + Hello, world 1011 + Hello, world 1012 + Hello, world 1013 + Hello, world 1014 + Hello, world 1015 + Hello, world 1016 + Hello, world 1017 + Hello, world 1018 + Hello, world 1019 + Hello, world 1020 + Hello, world 1021 + Hello, world 1022 + Hello, world 1023 + Hello, world 1024 + Hello, world 1025 + Hello, world 1026 + Hello, world 1027 + Hello, world 1028 + Hello, world 1029 + Hello, world 1030 + Hello, world 1031 + Hello, world 1032 + Hello, world 1033 + Hello, world 1034 + Hello, world 1035 + Hello, world 1036 + Hello, world 1037 + Hello, world 1038 + Hello, world 1039 + Hello, world 1040 + Hello, world 1041 + Hello, world 1042 + Hello, world 1043 + Hello, world 1044 + Hello, world 1045 + Hello, world 1046 + Hello, world 1047 + Hello, world 1048 + Hello, world 1049 + Hello, world 1050 + Hello, world 1051 + Hello, world 1052 + Hello, world 1053 + Hello, world 1054 + Hello, world 1055 + Hello, world 1056 + Hello, world 1057 + Hello, world 1058 + Hello, world 1059 + Hello, world 1060 + Hello, world 1061 + Hello, world 1062 + Hello, world 1063 + Hello, world 1064 + Hello, world 1065 + Hello, world 1066 + Hello, world 1067 + Hello, world 1068 + Hello, world 1069 + Hello, world 1070 + Hello, world 1071 + Hello, world 1072 + Hello, world 1073 + Hello, world 1074 + Hello, world 1075 + Hello, world 1076 + Hello, world 1077 + Hello, world 1078 + Hello, world 1079 + Hello, world 1080 + Hello, world 1081 + Hello, world 1082 + Hello, world 1083 + Hello, world 1084 + Hello, world 1085 + Hello, world 1086 + Hello, world 1087 + Hello, world 1088 + Hello, world 1089 + Hello, world 1090 + Hello, world 1091 + Hello, world 1092 + Hello, world 1093 + Hello, world 1094 + Hello, world 1095 + Hello, world 1096 + Hello, world 1097 + Hello, world 1098 + Hello, world 1099 + Hello, world 1100 + Hello, world 1101 + Hello, world 1102 + Hello, world 1103 + Hello, world 1104 + Hello, world 1105 + Hello, world 1106 + Hello, world 1107 + Hello, world 1108 + Hello, world 1109 + Hello, world 1110 + Hello, world 1111 + Hello, world 1112 + Hello, world 1113 + Hello, world 1114 + Hello, world 1115 + Hello, world 1116 + Hello, world 1117 + Hello, world 1118 + Hello, world 1119 + Hello, world 1120 + Hello, world 1121 + Hello, world 1122 + Hello, world 1123 + Hello, world 1124 + Hello, world 1125 + Hello, world 1126 + Hello, world 1127 + Hello, world 1128 + Hello, world 1129 + Hello, world 1130 + Hello, world 1131 + Hello, world 1132 + Hello, world 1133 + Hello, world 1134 + Hello, world 1135 + Hello, world 1136 + Hello, world 1137 + Hello, world 1138 + Hello, world 1139 + Hello, world 1140 + Hello, world 1141 + Hello, world 1142 + Hello, world 1143 + Hello, world 1144 + Hello, world 1145 + Hello, world 1146 + Hello, world 1147 + Hello, world 1148 + Hello, world 1149 + Hello, world 1150 + Hello, world 1151 + Hello, world 1152 + Hello, world 1153 + Hello, world 1154 + Hello, world 1155 + Hello, world 1156 + Hello, world 1157 + Hello, world 1158 + Hello, world 1159 + Hello, world 1160 + Hello, world 1161 + Hello, world 1162 + Hello, world 1163 + Hello, world 1164 + Hello, world 1165 + Hello, world 1166 + Hello, world 1167 + Hello, world 1168 + Hello, world 1169 + Hello, world 1170 + Hello, world 1171 + Hello, world 1172 + Hello, world 1173 + Hello, world 1174 + Hello, world 1175 + Hello, world 1176 + Hello, world 1177 + Hello, world 1178 + Hello, world 1179 + Hello, world 1180 + Hello, world 1181 + Hello, world 1182 + Hello, world 1183 + Hello, world 1184 + Hello, world 1185 + Hello, world 1186 + Hello, world 1187 + Hello, world 1188 + Hello, world 1189 + Hello, world 1190 + Hello, world 1191 + Hello, world 1192 + Hello, world 1193 + Hello, world 1194 + Hello, world 1195 + Hello, world 1196 + Hello, world 1197 + Hello, world 1198 + Hello, world 1199 + Hello, world 1200 + Hello, world 1201 + Hello, world 1202 + Hello, world 1203 + Hello, world 1204 + Hello, world 1205 + Hello, world 1206 + Hello, world 1207 + Hello, world 1208 + Hello, world 1209 + Hello, world 1210 + Hello, world 1211 + Hello, world 1212 + Hello, world 1213 + Hello, world 1214 + Hello, world 1215 + Hello, world 1216 + Hello, world 1217 + Hello, world 1218 + Hello, world 1219 + Hello, world 1220 + Hello, world 1221 + Hello, world 1222 + Hello, world 1223 + Hello, world 1224 + Hello, world 1225 + Hello, world 1226 + Hello, world 1227 + Hello, world 1228 + Hello, world 1229 + Hello, world 1230 + Hello, world 1231 + Hello, world 1232 + Hello, world 1233 + Hello, world 1234 + Hello, world 1235 + Hello, world 1236 + Hello, world 1237 + Hello, world 1238 + Hello, world 1239 + Hello, world 1240 + Hello, world 1241 + Hello, world 1242 + Hello, world 1243 + Hello, world 1244 + Hello, world 1245 + Hello, world 1246 + Hello, world 1247 + Hello, world 1248 + Hello, world 1249 + Hello, world 1250 + Hello, world 1251 + Hello, world 1252 + Hello, world 1253 + Hello, world 1254 + Hello, world 1255 + Hello, world 1256 + Hello, world 1257 + Hello, world 1258 + Hello, world 1259 + Hello, world 1260 + Hello, world 1261 + Hello, world 1262 + Hello, world 1263 + Hello, world 1264 + Hello, world 1265 + Hello, world 1266 + Hello, world 1267 + Hello, world 1268 + Hello, world 1269 + Hello, world 1270 + Hello, world 1271 + Hello, world 1272 + Hello, world 1273 + Hello, world 1274 + Hello, world 1275 + Hello, world 1276 + Hello, world 1277 + Hello, world 1278 + Hello, world 1279 + Hello, world 1280 + Hello, world 1281 + Hello, world 1282 + Hello, world 1283 + Hello, world 1284 + Hello, world 1285 + Hello, world 1286 + Hello, world 1287 + Hello, world 1288 + Hello, world 1289 + Hello, world 1290 + Hello, world 1291 + Hello, world 1292 + Hello, world 1293 + Hello, world 1294 + Hello, world 1295 + Hello, world 1296 + Hello, world 1297 + Hello, world 1298 + Hello, world 1299 + Hello, world 1300 + Hello, world 1301 + Hello, world 1302 + Hello, world 1303 + Hello, world 1304 + Hello, world 1305 + Hello, world 1306 + Hello, world 1307 + Hello, world 1308 + Hello, world 1309 + Hello, world 1310 + Hello, world 1311 + Hello, world 1312 + Hello, world 1313 + Hello, world 1314 + Hello, world 1315 + Hello, world 1316 + Hello, world 1317 + Hello, world 1318 + Hello, world 1319 + Hello, world 1320 + Hello, world 1321 + Hello, world 1322 + Hello, world 1323 + Hello, world 1324 + Hello, world 1325 + Hello, world 1326 + Hello, world 1327 + Hello, world 1328 + Hello, world 1329 + Hello, world 1330 + Hello, world 1331 + Hello, world 1332 + Hello, world 1333 + Hello, world 1334 + Hello, world 1335 + Hello, world 1336 + Hello, world 1337 + Hello, world 1338 + Hello, world 1339 + Hello, world 1340 + Hello, world 1341 + Hello, world 1342 + Hello, world 1343 + Hello, world 1344 + Hello, world 1345 + Hello, world 1346 + Hello, world 1347 + Hello, world 1348 + Hello, world 1349 + Hello, world 1350 + Hello, world 1351 + Hello, world 1352 + Hello, world 1353 + Hello, world 1354 + Hello, world 1355 + Hello, world 1356 + Hello, world 1357 + Hello, world 1358 + Hello, world 1359 + Hello, world 1360 + Hello, world 1361 + Hello, world 1362 + Hello, world 1363 + Hello, world 1364 + Hello, world 1365 + Hello, world 1366 + Hello, world 1367 + Hello, world 1368 + Hello, world 1369 + Hello, world 1370 + Hello, world 1371 + Hello, world 1372 + Hello, world 1373 + Hello, world 1374 + Hello, world 1375 + Hello, world 1376 + Hello, world 1377 + Hello, world 1378 + Hello, world 1379 + Hello, world 1380 + Hello, world 1381 + Hello, world 1382 + Hello, world 1383 + Hello, world 1384 + Hello, world 1385 + Hello, world 1386 + Hello, world 1387 + Hello, world 1388 + Hello, world 1389 + Hello, world 1390 + Hello, world 1391 + Hello, world 1392 + Hello, world 1393 + Hello, world 1394 + Hello, world 1395 + Hello, world 1396 + Hello, world 1397 + Hello, world 1398 + Hello, world 1399 + Hello, world 1400 + Hello, world 1401 + Hello, world 1402 + Hello, world 1403 + Hello, world 1404 + Hello, world 1405 + Hello, world 1406 + Hello, world 1407 + Hello, world 1408 + Hello, world 1409 + Hello, world 1410 + Hello, world 1411 + Hello, world 1412 + Hello, world 1413 + Hello, world 1414 + Hello, world 1415 + Hello, world 1416 + Hello, world 1417 + Hello, world 1418 + Hello, world 1419 + Hello, world 1420 + Hello, world 1421 + Hello, world 1422 + Hello, world 1423 + Hello, world 1424 + Hello, world 1425 + Hello, world 1426 + Hello, world 1427 + Hello, world 1428 + Hello, world 1429 + Hello, world 1430 + Hello, world 1431 + Hello, world 1432 + Hello, world 1433 + Hello, world 1434 + Hello, world 1435 + Hello, world 1436 + Hello, world 1437 + Hello, world 1438 + Hello, world 1439 + Hello, world 1440 + Hello, world 1441 + Hello, world 1442 + Hello, world 1443 + Hello, world 1444 + Hello, world 1445 + Hello, world 1446 + Hello, world 1447 + Hello, world 1448 + Hello, world 1449 + Hello, world 1450 + Hello, world 1451 + Hello, world 1452 + Hello, world 1453 + Hello, world 1454 + Hello, world 1455 + Hello, world 1456 + Hello, world 1457 + Hello, world 1458 + Hello, world 1459 + Hello, world 1460 + Hello, world 1461 + Hello, world 1462 + Hello, world 1463 + Hello, world 1464 + Hello, world 1465 + Hello, world 1466 + Hello, world 1467 + Hello, world 1468 + Hello, world 1469 + Hello, world 1470 + Hello, world 1471 + Hello, world 1472 + Hello, world 1473 + Hello, world 1474 + Hello, world 1475 + Hello, world 1476 + Hello, world 1477 + Hello, world 1478 + Hello, world 1479 + Hello, world 1480 + Hello, world 1481 + Hello, world 1482 + Hello, world 1483 + Hello, world 1484 + Hello, world 1485 + Hello, world 1486 + Hello, world 1487 + Hello, world 1488 + Hello, world 1489 + Hello, world 1490 + Hello, world 1491 + Hello, world 1492 + Hello, world 1493 + Hello, world 1494 + Hello, world 1495 + Hello, world 1496 + Hello, world 1497 + Hello, world 1498 + Hello, world 1499 + Hello, world 1500 + Hello, world 1501 + Hello, world 1502 + Hello, world 1503 + Hello, world 1504 + Hello, world 1505 + Hello, world 1506 + Hello, world 1507 + Hello, world 1508 + Hello, world 1509 + Hello, world 1510 + Hello, world 1511 + Hello, world 1512 + Hello, world 1513 + Hello, world 1514 + Hello, world 1515 + Hello, world 1516 + Hello, world 1517 + Hello, world 1518 + Hello, world 1519 + Hello, world 1520 + Hello, world 1521 + Hello, world 1522 + Hello, world 1523 + Hello, world 1524 + Hello, world 1525 + Hello, world 1526 + Hello, world 1527 + Hello, world 1528 + Hello, world 1529 + Hello, world 1530 + Hello, world 1531 + Hello, world 1532 + Hello, world 1533 + Hello, world 1534 + Hello, world 1535 + Hello, world 1536 + Hello, world 1537 + Hello, world 1538 + Hello, world 1539 + Hello, world 1540 + Hello, world 1541 + Hello, world 1542 + Hello, world 1543 + Hello, world 1544 + Hello, world 1545 + Hello, world 1546 + Hello, world 1547 + Hello, world 1548 + Hello, world 1549 + Hello, world 1550 + Hello, world 1551 + Hello, world 1552 + Hello, world 1553 + Hello, world 1554 + Hello, world 1555 + Hello, world 1556 + Hello, world 1557 + Hello, world 1558 + Hello, world 1559 + Hello, world 1560 + Hello, world 1561 + Hello, world 1562 + Hello, world 1563 + Hello, world 1564 + Hello, world 1565 + Hello, world 1566 + Hello, world 1567 + Hello, world 1568 + Hello, world 1569 + Hello, world 1570 + Hello, world 1571 + Hello, world 1572 + Hello, world 1573 + Hello, world 1574 + Hello, world 1575 + Hello, world 1576 + Hello, world 1577 + Hello, world 1578 + Hello, world 1579 + Hello, world 1580 + Hello, world 1581 + Hello, world 1582 + Hello, world 1583 + Hello, world 1584 + Hello, world 1585 + Hello, world 1586 + Hello, world 1587 + Hello, world 1588 + Hello, world 1589 + Hello, world 1590 + Hello, world 1591 + Hello, world 1592 + Hello, world 1593 + Hello, world 1594 + Hello, world 1595 + Hello, world 1596 + Hello, world 1597 + Hello, world 1598 + Hello, world 1599 + Hello, world 1600 + Hello, world 1601 + Hello, world 1602 + Hello, world 1603 + Hello, world 1604 + Hello, world 1605 + Hello, world 1606 + Hello, world 1607 + Hello, world 1608 + Hello, world 1609 + Hello, world 1610 + Hello, world 1611 + Hello, world 1612 + Hello, world 1613 + Hello, world 1614 + Hello, world 1615 + Hello, world 1616 + Hello, world 1617 + Hello, world 1618 + Hello, world 1619 + Hello, world 1620 + Hello, world 1621 + Hello, world 1622 + Hello, world 1623 + Hello, world 1624 + Hello, world 1625 + Hello, world 1626 + Hello, world 1627 + Hello, world 1628 + Hello, world 1629 + Hello, world 1630 + Hello, world 1631 + Hello, world 1632 + Hello, world 1633 + Hello, world 1634 + Hello, world 1635 + Hello, world 1636 + Hello, world 1637 + Hello, world 1638 + Hello, world 1639 + Hello, world 1640 + Hello, world 1641 + Hello, world 1642 + Hello, world 1643 + Hello, world 1644 + Hello, world 1645 + Hello, world 1646 + Hello, world 1647 + Hello, world 1648 + Hello, world 1649 + Hello, world 1650 + Hello, world 1651 + Hello, world 1652 + Hello, world 1653 + Hello, world 1654 + Hello, world 1655 + Hello, world 1656 + Hello, world 1657 + Hello, world 1658 + Hello, world 1659 + Hello, world 1660 + Hello, world 1661 + Hello, world 1662 + Hello, world 1663 + Hello, world 1664 + Hello, world 1665 + Hello, world 1666 + Hello, world 1667 + Hello, world 1668 + Hello, world 1669 + Hello, world 1670 + Hello, world 1671 + Hello, world 1672 + Hello, world 1673 + Hello, world 1674 + Hello, world 1675 + Hello, world 1676 + Hello, world 1677 + Hello, world 1678 + Hello, world 1679 + Hello, world 1680 + Hello, world 1681 + Hello, world 1682 + Hello, world 1683 + Hello, world 1684 + Hello, world 1685 + Hello, world 1686 + Hello, world 1687 + Hello, world 1688 + Hello, world 1689 + Hello, world 1690 + Hello, world 1691 + Hello, world 1692 + Hello, world 1693 + Hello, world 1694 + Hello, world 1695 + Hello, world 1696 + Hello, world 1697 + Hello, world 1698 + Hello, world 1699 + Hello, world 1700 + Hello, world 1701 + Hello, world 1702 + Hello, world 1703 + Hello, world 1704 + Hello, world 1705 + Hello, world 1706 + Hello, world 1707 + Hello, world 1708 + Hello, world 1709 + Hello, world 1710 + Hello, world 1711 + Hello, world 1712 + Hello, world 1713 + Hello, world 1714 + Hello, world 1715 + Hello, world 1716 + Hello, world 1717 + Hello, world 1718 + Hello, world 1719 + Hello, world 1720 + Hello, world 1721 + Hello, world 1722 + Hello, world 1723 + Hello, world 1724 + Hello, world 1725 + Hello, world 1726 + Hello, world 1727 + Hello, world 1728 + Hello, world 1729 + Hello, world 1730 + Hello, world 1731 + Hello, world 1732 + Hello, world 1733 + Hello, world 1734 + Hello, world 1735 + Hello, world 1736 + Hello, world 1737 + Hello, world 1738 + Hello, world 1739 + Hello, world 1740 + Hello, world 1741 + Hello, world 1742 + Hello, world 1743 + Hello, world 1744 + Hello, world 1745 + Hello, world 1746 + Hello, world 1747 + Hello, world 1748 + Hello, world 1749 + Hello, world 1750 + Hello, world 1751 + Hello, world 1752 + Hello, world 1753 + Hello, world 1754 + Hello, world 1755 + Hello, world 1756 + Hello, world 1757 + Hello, world 1758 + Hello, world 1759 + Hello, world 1760 + Hello, world 1761 + Hello, world 1762 + Hello, world 1763 + Hello, world 1764 + Hello, world 1765 + Hello, world 1766 + Hello, world 1767 + Hello, world 1768 + Hello, world 1769 + Hello, world 1770 + Hello, world 1771 + Hello, world 1772 + Hello, world 1773 + Hello, world 1774 + Hello, world 1775 + Hello, world 1776 + Hello, world 1777 + Hello, world 1778 + Hello, world 1779 + Hello, world 1780 + Hello, world 1781 + Hello, world 1782 + Hello, world 1783 + Hello, world 1784 + Hello, world 1785 + Hello, world 1786 + Hello, world 1787 + Hello, world 1788 + Hello, world 1789 + Hello, world 1790 + Hello, world 1791 + Hello, world 1792 + Hello, world 1793 + Hello, world 1794 + Hello, world 1795 + Hello, world 1796 + Hello, world 1797 + Hello, world 1798 + Hello, world 1799 + Hello, world 1800 + Hello, world 1801 + Hello, world 1802 + Hello, world 1803 + Hello, world 1804 + Hello, world 1805 + Hello, world 1806 + Hello, world 1807 + Hello, world 1808 + Hello, world 1809 + Hello, world 1810 + Hello, world 1811 + Hello, world 1812 + Hello, world 1813 + Hello, world 1814 + Hello, world 1815 + Hello, world 1816 + Hello, world 1817 + Hello, world 1818 + Hello, world 1819 + Hello, world 1820 + Hello, world 1821 + Hello, world 1822 + Hello, world 1823 + Hello, world 1824 + Hello, world 1825 + Hello, world 1826 + Hello, world 1827 + Hello, world 1828 + Hello, world 1829 + Hello, world 1830 + Hello, world 1831 + Hello, world 1832 + Hello, world 1833 + Hello, world 1834 + Hello, world 1835 + Hello, world 1836 + Hello, world 1837 + Hello, world 1838 + Hello, world 1839 + Hello, world 1840 + Hello, world 1841 + Hello, world 1842 + Hello, world 1843 + Hello, world 1844 + Hello, world 1845 + Hello, world 1846 + Hello, world 1847 + Hello, world 1848 + Hello, world 1849 + Hello, world 1850 + Hello, world 1851 + Hello, world 1852 + Hello, world 1853 + Hello, world 1854 + Hello, world 1855 + Hello, world 1856 + Hello, world 1857 + Hello, world 1858 + Hello, world 1859 + Hello, world 1860 + Hello, world 1861 + Hello, world 1862 + Hello, world 1863 + Hello, world 1864 + Hello, world 1865 + Hello, world 1866 + Hello, world 1867 + Hello, world 1868 + Hello, world 1869 + Hello, world 1870 + Hello, world 1871 + Hello, world 1872 + Hello, world 1873 + Hello, world 1874 + Hello, world 1875 + Hello, world 1876 + Hello, world 1877 + Hello, world 1878 + Hello, world 1879 + Hello, world 1880 + Hello, world 1881 + Hello, world 1882 + Hello, world 1883 + Hello, world 1884 + Hello, world 1885 + Hello, world 1886 + Hello, world 1887 + Hello, world 1888 + Hello, world 1889 + Hello, world 1890 + Hello, world 1891 + Hello, world 1892 + Hello, world 1893 + Hello, world 1894 + Hello, world 1895 + Hello, world 1896 + Hello, world 1897 + Hello, world 1898 + Hello, world 1899 + Hello, world 1900 + Hello, world 1901 + Hello, world 1902 + Hello, world 1903 + Hello, world 1904 + Hello, world 1905 + Hello, world 1906 + Hello, world 1907 + Hello, world 1908 + Hello, world 1909 + Hello, world 1910 + Hello, world 1911 + Hello, world 1912 + Hello, world 1913 + Hello, world 1914 + Hello, world 1915 + Hello, world 1916 + Hello, world 1917 + Hello, world 1918 + Hello, world 1919 + Hello, world 1920 + Hello, world 1921 + Hello, world 1922 + Hello, world 1923 + Hello, world 1924 + Hello, world 1925 + Hello, world 1926 + Hello, world 1927 + Hello, world 1928 + Hello, world 1929 + Hello, world 1930 + Hello, world 1931 + Hello, world 1932 + Hello, world 1933 + Hello, world 1934 + Hello, world 1935 + Hello, world 1936 + Hello, world 1937 + Hello, world 1938 + Hello, world 1939 + Hello, world 1940 + Hello, world 1941 + Hello, world 1942 + Hello, world 1943 + Hello, world 1944 + Hello, world 1945 + Hello, world 1946 + Hello, world 1947 + Hello, world 1948 + Hello, world 1949 + Hello, world 1950 + Hello, world 1951 + Hello, world 1952 + Hello, world 1953 + Hello, world 1954 + Hello, world 1955 + Hello, world 1956 + Hello, world 1957 + Hello, world 1958 + Hello, world 1959 + Hello, world 1960 + Hello, world 1961 + Hello, world 1962 + Hello, world 1963 + Hello, world 1964 + Hello, world 1965 + Hello, world 1966 + Hello, world 1967 + Hello, world 1968 + Hello, world 1969 + Hello, world 1970 + Hello, world 1971 + Hello, world 1972 + Hello, world 1973 + Hello, world 1974 + Hello, world 1975 + Hello, world 1976 + Hello, world 1977 + Hello, world 1978 + Hello, world 1979 + Hello, world 1980 + Hello, world 1981 + Hello, world 1982 + Hello, world 1983 + Hello, world 1984 + Hello, world 1985 + Hello, world 1986 + Hello, world 1987 + Hello, world 1988 + Hello, world 1989 + Hello, world 1990 + Hello, world 1991 + Hello, world 1992 + Hello, world 1993 + Hello, world 1994 + Hello, world 1995 + Hello, world 1996 + Hello, world 1997 + Hello, world 1998 + Hello, world 1999 + Hello, world 2000 + Hello, world 2001 + Hello, world 2002 + Hello, world 2003 + Hello, world 2004 + Hello, world 2005 + Hello, world 2006 + Hello, world 2007 + Hello, world 2008 + Hello, world 2009 + Hello, world 2010 + Hello, world 2011 + Hello, world 2012 + Hello, world 2013 + Hello, world 2014 + Hello, world 2015 + Hello, world 2016 + Hello, world 2017 + Hello, world 2018 + Hello, world 2019 + Hello, world 2020 + Hello, world 2021 + Hello, world 2022 + Hello, world 2023 + Hello, world 2024 + Hello, world 2025 + Hello, world 2026 + Hello, world 2027 + Hello, world 2028 + Hello, world 2029 + Hello, world 2030 + Hello, world 2031 + Hello, world 2032 + Hello, world 2033 + Hello, world 2034 + Hello, world 2035 + Hello, world 2036 + Hello, world 2037 + Hello, world 2038 + Hello, world 2039 + Hello, world 2040 + Hello, world 2041 + Hello, world 2042 + Hello, world 2043 + Hello, world 2044 + Hello, world 2045 + Hello, world 2046 + Hello, world 2047 + Hello, world 2048 + Hello, world 2049 + Hello, world 2050 + Hello, world 2051 + Hello, world 2052 + Hello, world 2053 + Hello, world 2054 + Hello, world 2055 + Hello, world 2056 + Hello, world 2057 + Hello, world 2058 + Hello, world 2059 + Hello, world 2060 + Hello, world 2061 + Hello, world 2062 + Hello, world 2063 + Hello, world 2064 + Hello, world 2065 + Hello, world 2066 + Hello, world 2067 + Hello, world 2068 + Hello, world 2069 + Hello, world 2070 + Hello, world 2071 + Hello, world 2072 + Hello, world 2073 + Hello, world 2074 + Hello, world 2075 + Hello, world 2076 + Hello, world 2077 + Hello, world 2078 + Hello, world 2079 + Hello, world 2080 + Hello, world 2081 + Hello, world 2082 + Hello, world 2083 + Hello, world 2084 + Hello, world 2085 + Hello, world 2086 + Hello, world 2087 + Hello, world 2088 + Hello, world 2089 + Hello, world 2090 + Hello, world 2091 + Hello, world 2092 + Hello, world 2093 + Hello, world 2094 + Hello, world 2095 + Hello, world 2096 + Hello, world 2097 + Hello, world 2098 + Hello, world 2099 + Hello, world 2100 + Hello, world 2101 + Hello, world 2102 + Hello, world 2103 + Hello, world 2104 + Hello, world 2105 + Hello, world 2106 + Hello, world 2107 + Hello, world 2108 + Hello, world 2109 + Hello, world 2110 + Hello, world 2111 + Hello, world 2112 + Hello, world 2113 + Hello, world 2114 + Hello, world 2115 + Hello, world 2116 + Hello, world 2117 + Hello, world 2118 + Hello, world 2119 + Hello, world 2120 + Hello, world 2121 + Hello, world 2122 + Hello, world 2123 + Hello, world 2124 + Hello, world 2125 + Hello, world 2126 + Hello, world 2127 + Hello, world 2128 + Hello, world 2129 + Hello, world 2130 + Hello, world 2131 + Hello, world 2132 + Hello, world 2133 + Hello, world 2134 + Hello, world 2135 + Hello, world 2136 + Hello, world 2137 + Hello, world 2138 + Hello, world 2139 + Hello, world 2140 + Hello, world 2141 + Hello, world 2142 + Hello, world 2143 + Hello, world 2144 + Hello, world 2145 + Hello, world 2146 + Hello, world 2147 + Hello, world 2148 + Hello, world 2149 + Hello, world 2150 + Hello, world 2151 + Hello, world 2152 + Hello, world 2153 + Hello, world 2154 + Hello, world 2155 + Hello, world 2156 + Hello, world 2157 + Hello, world 2158 + Hello, world 2159 + Hello, world 2160 + Hello, world 2161 + Hello, world 2162 + Hello, world 2163 + Hello, world 2164 + Hello, world 2165 + Hello, world 2166 + Hello, world 2167 + Hello, world 2168 + Hello, world 2169 + Hello, world 2170 + Hello, world 2171 + Hello, world 2172 + Hello, world 2173 + Hello, world 2174 + Hello, world 2175 + Hello, world 2176 + Hello, world 2177 + Hello, world 2178 + Hello, world 2179 + Hello, world 2180 + Hello, world 2181 + Hello, world 2182 + Hello, world 2183 + Hello, world 2184 + Hello, world 2185 + Hello, world 2186 + Hello, world 2187 + Hello, world 2188 + Hello, world 2189 + Hello, world 2190 + Hello, world 2191 + Hello, world 2192 + Hello, world 2193 + Hello, world 2194 + Hello, world 2195 + Hello, world 2196 + Hello, world 2197 + Hello, world 2198 + Hello, world 2199 + Hello, world 2200 + Hello, world 2201 + Hello, world 2202 + Hello, world 2203 + Hello, world 2204 + Hello, world 2205 + Hello, world 2206 + Hello, world 2207 + Hello, world 2208 + Hello, world 2209 + Hello, world 2210 + Hello, world 2211 + Hello, world 2212 + Hello, world 2213 + Hello, world 2214 + Hello, world 2215 + Hello, world 2216 + Hello, world 2217 + Hello, world 2218 + Hello, world 2219 + Hello, world 2220 + Hello, world 2221 + Hello, world 2222 + Hello, world 2223 + Hello, world 2224 + Hello, world 2225 + Hello, world 2226 + Hello, world 2227 + Hello, world 2228 + Hello, world 2229 + Hello, world 2230 + Hello, world 2231 + Hello, world 2232 + Hello, world 2233 + Hello, world 2234 + Hello, world 2235 + Hello, world 2236 + Hello, world 2237 + Hello, world 2238 + Hello, world 2239 + Hello, world 2240 + Hello, world 2241 + Hello, world 2242 + Hello, world 2243 + Hello, world 2244 + Hello, world 2245 + Hello, world 2246 + Hello, world 2247 + Hello, world 2248 + Hello, world 2249 + Hello, world 2250 + Hello, world 2251 + Hello, world 2252 + Hello, world 2253 + Hello, world 2254 + Hello, world 2255 + Hello, world 2256 + Hello, world 2257 + Hello, world 2258 + Hello, world 2259 + Hello, world 2260 + Hello, world 2261 + Hello, world 2262 + Hello, world 2263 + Hello, world 2264 + Hello, world 2265 + Hello, world 2266 + Hello, world 2267 + Hello, world 2268 + Hello, world 2269 + Hello, world 2270 + Hello, world 2271 + Hello, world 2272 + Hello, world 2273 + Hello, world 2274 + Hello, world 2275 + Hello, world 2276 + Hello, world 2277 + Hello, world 2278 + Hello, world 2279 + Hello, world 2280 + Hello, world 2281 + Hello, world 2282 + Hello, world 2283 + Hello, world 2284 + Hello, world 2285 + Hello, world 2286 + Hello, world 2287 + Hello, world 2288 + Hello, world 2289 + Hello, world 2290 + Hello, world 2291 + Hello, world 2292 + Hello, world 2293 + Hello, world 2294 + Hello, world 2295 + Hello, world 2296 + Hello, world 2297 + Hello, world 2298 + Hello, world 2299 + Hello, world 2300 + Hello, world 2301 + Hello, world 2302 + Hello, world 2303 + Hello, world 2304 + Hello, world 2305 + Hello, world 2306 + Hello, world 2307 + Hello, world 2308 + Hello, world 2309 + Hello, world 2310 + Hello, world 2311 + Hello, world 2312 + Hello, world 2313 + Hello, world 2314 + Hello, world 2315 + Hello, world 2316 + Hello, world 2317 + Hello, world 2318 + Hello, world 2319 + Hello, world 2320 + Hello, world 2321 + Hello, world 2322 + Hello, world 2323 + Hello, world 2324 + Hello, world 2325 + Hello, world 2326 + Hello, world 2327 + Hello, world 2328 + Hello, world 2329 + Hello, world 2330 + Hello, world 2331 + Hello, world 2332 + Hello, world 2333 + Hello, world 2334 + Hello, world 2335 + Hello, world 2336 + Hello, world 2337 + Hello, world 2338 + Hello, world 2339 + Hello, world 2340 + Hello, world 2341 + Hello, world 2342 + Hello, world 2343 + Hello, world 2344 + Hello, world 2345 + Hello, world 2346 + Hello, world 2347 + Hello, world 2348 + Hello, world 2349 + Hello, world 2350 + Hello, world 2351 + Hello, world 2352 + Hello, world 2353 + Hello, world 2354 + Hello, world 2355 + Hello, world 2356 + Hello, world 2357 + Hello, world 2358 + Hello, world 2359 + Hello, world 2360 + Hello, world 2361 + Hello, world 2362 + Hello, world 2363 + Hello, world 2364 + Hello, world 2365 + Hello, world 2366 + Hello, world 2367 + Hello, world 2368 + Hello, world 2369 + Hello, world 2370 + Hello, world 2371 + Hello, world 2372 + Hello, world 2373 + Hello, world 2374 + Hello, world 2375 + Hello, world 2376 + Hello, world 2377 + Hello, world 2378 + Hello, world 2379 + Hello, world 2380 + Hello, world 2381 + Hello, world 2382 + Hello, world 2383 + Hello, world 2384 + Hello, world 2385 + Hello, world 2386 + Hello, world 2387 + Hello, world 2388 + Hello, world 2389 + Hello, world 2390 + Hello, world 2391 + Hello, world 2392 + Hello, world 2393 + Hello, world 2394 + Hello, world 2395 + Hello, world 2396 + Hello, world 2397 + Hello, world 2398 + Hello, world 2399 + Hello, world 2400 + Hello, world 2401 + Hello, world 2402 + Hello, world 2403 + Hello, world 2404 + Hello, world 2405 + Hello, world 2406 + Hello, world 2407 + Hello, world 2408 + Hello, world 2409 + Hello, world 2410 + Hello, world 2411 + Hello, world 2412 + Hello, world 2413 + Hello, world 2414 + Hello, world 2415 + Hello, world 2416 + Hello, world 2417 + Hello, world 2418 + Hello, world 2419 + Hello, world 2420 + Hello, world 2421 + Hello, world 2422 + Hello, world 2423 + Hello, world 2424 + Hello, world 2425 + Hello, world 2426 + Hello, world 2427 + Hello, world 2428 + Hello, world 2429 + Hello, world 2430 + Hello, world 2431 + Hello, world 2432 + Hello, world 2433 + Hello, world 2434 + Hello, world 2435 + Hello, world 2436 + Hello, world 2437 + Hello, world 2438 + Hello, world 2439 + Hello, world 2440 + Hello, world 2441 + Hello, world 2442 + Hello, world 2443 + Hello, world 2444 + Hello, world 2445 + Hello, world 2446 + Hello, world 2447 + Hello, world 2448 + Hello, world 2449 + Hello, world 2450 + Hello, world 2451 + Hello, world 2452 + Hello, world 2453 + Hello, world 2454 + Hello, world 2455 + Hello, world 2456 + Hello, world 2457 + Hello, world 2458 + Hello, world 2459 + Hello, world 2460 + Hello, world 2461 + Hello, world 2462 + Hello, world 2463 + Hello, world 2464 + Hello, world 2465 + Hello, world 2466 + Hello, world 2467 + Hello, world 2468 + Hello, world 2469 + Hello, world 2470 + Hello, world 2471 + Hello, world 2472 + Hello, world 2473 + Hello, world 2474 + Hello, world 2475 + Hello, world 2476 + Hello, world 2477 + Hello, world 2478 + Hello, world 2479 + Hello, world 2480 + Hello, world 2481 + Hello, world 2482 + Hello, world 2483 + Hello, world 2484 + Hello, world 2485 + Hello, world 2486 + Hello, world 2487 + Hello, world 2488 + Hello, world 2489 + Hello, world 2490 + Hello, world 2491 + Hello, world 2492 + Hello, world 2493 + Hello, world 2494 + Hello, world 2495 + Hello, world 2496 + Hello, world 2497 + Hello, world 2498 + Hello, world 2499 + Hello, world 2500 + Hello, world 2501 + Hello, world 2502 + Hello, world 2503 + Hello, world 2504 + Hello, world 2505 + Hello, world 2506 + Hello, world 2507 + Hello, world 2508 + Hello, world 2509 + Hello, world 2510 + Hello, world 2511 + Hello, world 2512 + Hello, world 2513 + Hello, world 2514 + Hello, world 2515 + Hello, world 2516 + Hello, world 2517 + Hello, world 2518 + Hello, world 2519 + Hello, world 2520 + Hello, world 2521 + Hello, world 2522 + Hello, world 2523 + Hello, world 2524 + Hello, world 2525 + Hello, world 2526 + Hello, world 2527 + Hello, world 2528 + Hello, world 2529 + Hello, world 2530 + Hello, world 2531 + Hello, world 2532 + Hello, world 2533 + Hello, world 2534 + Hello, world 2535 + Hello, world 2536 + Hello, world 2537 + Hello, world 2538 + Hello, world 2539 + Hello, world 2540 + Hello, world 2541 + Hello, world 2542 + Hello, world 2543 + Hello, world 2544 + Hello, world 2545 + Hello, world 2546 + Hello, world 2547 + Hello, world 2548 + Hello, world 2549 + Hello, world 2550 + Hello, world 2551 + Hello, world 2552 + Hello, world 2553 + Hello, world 2554 + Hello, world 2555 + Hello, world 2556 + Hello, world 2557 + Hello, world 2558 + Hello, world 2559 + Hello, world 2560 + Hello, world 2561 + Hello, world 2562 + Hello, world 2563 + Hello, world 2564 + Hello, world 2565 + Hello, world 2566 + Hello, world 2567 + Hello, world 2568 + Hello, world 2569 + Hello, world 2570 + Hello, world 2571 + Hello, world 2572 + Hello, world 2573 + Hello, world 2574 + Hello, world 2575 + Hello, world 2576 + Hello, world 2577 + Hello, world 2578 + Hello, world 2579 + Hello, world 2580 + Hello, world 2581 + Hello, world 2582 + Hello, world 2583 + Hello, world 2584 + Hello, world 2585 + Hello, world 2586 + Hello, world 2587 + Hello, world 2588 + Hello, world 2589 + Hello, world 2590 + Hello, world 2591 + Hello, world 2592 + Hello, world 2593 + Hello, world 2594 + Hello, world 2595 + Hello, world 2596 + Hello, world 2597 + Hello, world 2598 + Hello, world 2599 + Hello, world 2600 + Hello, world 2601 + Hello, world 2602 + Hello, world 2603 + Hello, world 2604 + Hello, world 2605 + Hello, world 2606 + Hello, world 2607 + Hello, world 2608 + Hello, world 2609 + Hello, world 2610 + Hello, world 2611 + Hello, world 2612 + Hello, world 2613 + Hello, world 2614 + Hello, world 2615 + Hello, world 2616 + Hello, world 2617 + Hello, world 2618 + Hello, world 2619 + Hello, world 2620 + Hello, world 2621 + Hello, world 2622 + Hello, world 2623 + Hello, world 2624 + Hello, world 2625 + Hello, world 2626 + Hello, world 2627 + Hello, world 2628 + Hello, world 2629 + Hello, world 2630 + Hello, world 2631 + Hello, world 2632 + Hello, world 2633 + Hello, world 2634 + Hello, world 2635 + Hello, world 2636 + Hello, world 2637 + Hello, world 2638 + Hello, world 2639 + Hello, world 2640 + Hello, world 2641 + Hello, world 2642 + Hello, world 2643 + Hello, world 2644 + Hello, world 2645 + Hello, world 2646 + Hello, world 2647 + Hello, world 2648 + Hello, world 2649 + Hello, world 2650 + Hello, world 2651 + Hello, world 2652 + Hello, world 2653 + Hello, world 2654 + Hello, world 2655 + Hello, world 2656 + Hello, world 2657 + Hello, world 2658 + Hello, world 2659 + Hello, world 2660 + Hello, world 2661 + Hello, world 2662 + Hello, world 2663 + Hello, world 2664 + Hello, world 2665 + Hello, world 2666 + Hello, world 2667 + Hello, world 2668 + Hello, world 2669 + Hello, world 2670 + Hello, world 2671 + Hello, world 2672 + Hello, world 2673 + Hello, world 2674 + Hello, world 2675 + Hello, world 2676 + Hello, world 2677 + Hello, world 2678 + Hello, world 2679 + Hello, world 2680 + Hello, world 2681 + Hello, world 2682 + Hello, world 2683 + Hello, world 2684 + Hello, world 2685 + Hello, world 2686 + Hello, world 2687 + Hello, world 2688 + Hello, world 2689 + Hello, world 2690 + Hello, world 2691 + Hello, world 2692 + Hello, world 2693 + Hello, world 2694 + Hello, world 2695 + Hello, world 2696 + Hello, world 2697 + Hello, world 2698 + Hello, world 2699 + Hello, world 2700 + Hello, world 2701 + Hello, world 2702 + Hello, world 2703 + Hello, world 2704 + Hello, world 2705 + Hello, world 2706 + Hello, world 2707 + Hello, world 2708 + Hello, world 2709 + Hello, world 2710 + Hello, world 2711 + Hello, world 2712 + Hello, world 2713 + Hello, world 2714 + Hello, world 2715 + Hello, world 2716 + Hello, world 2717 + Hello, world 2718 + Hello, world 2719 + Hello, world 2720 + Hello, world 2721 + Hello, world 2722 + Hello, world 2723 + Hello, world 2724 + Hello, world 2725 + Hello, world 2726 + Hello, world 2727 + Hello, world 2728 + Hello, world 2729 + Hello, world 2730 + Hello, world 2731 + Hello, world 2732 + Hello, world 2733 + Hello, world 2734 + Hello, world 2735 + Hello, world 2736 + Hello, world 2737 + Hello, world 2738 + Hello, world 2739 + Hello, world 2740 + Hello, world 2741 + Hello, world 2742 + Hello, world 2743 + Hello, world 2744 + Hello, world 2745 + Hello, world 2746 + Hello, world 2747 + Hello, world 2748 + Hello, world 2749 + Hello, world 2750 + Hello, world 2751 + Hello, world 2752 + Hello, world 2753 + Hello, world 2754 + Hello, world 2755 + Hello, world 2756 + Hello, world 2757 + Hello, world 2758 + Hello, world 2759 + Hello, world 2760 + Hello, world 2761 + Hello, world 2762 + Hello, world 2763 + Hello, world 2764 + Hello, world 2765 + Hello, world 2766 + Hello, world 2767 + Hello, world 2768 + Hello, world 2769 + Hello, world 2770 + Hello, world 2771 + Hello, world 2772 + Hello, world 2773 + Hello, world 2774 + Hello, world 2775 + Hello, world 2776 + Hello, world 2777 + Hello, world 2778 + Hello, world 2779 + Hello, world 2780 + Hello, world 2781 + Hello, world 2782 + Hello, world 2783 + Hello, world 2784 + Hello, world 2785 + Hello, world 2786 + Hello, world 2787 + Hello, world 2788 + Hello, world 2789 + Hello, world 2790 + Hello, world 2791 + Hello, world 2792 + Hello, world 2793 + Hello, world 2794 + Hello, world 2795 + Hello, world 2796 + Hello, world 2797 + Hello, world 2798 + Hello, world 2799 + Hello, world 2800 + Hello, world 2801 + Hello, world 2802 + Hello, world 2803 + Hello, world 2804 + Hello, world 2805 + Hello, world 2806 + Hello, world 2807 + Hello, world 2808 + Hello, world 2809 + Hello, world 2810 + Hello, world 2811 + Hello, world 2812 + Hello, world 2813 + Hello, world 2814 + Hello, world 2815 + Hello, world 2816 + Hello, world 2817 + Hello, world 2818 + Hello, world 2819 + Hello, world 2820 + Hello, world 2821 + Hello, world 2822 + Hello, world 2823 + Hello, world 2824 + Hello, world 2825 + Hello, world 2826 + Hello, world 2827 + Hello, world 2828 + Hello, world 2829 + Hello, world 2830 + Hello, world 2831 + Hello, world 2832 + Hello, world 2833 + Hello, world 2834 + Hello, world 2835 + Hello, world 2836 + Hello, world 2837 + Hello, world 2838 + Hello, world 2839 + Hello, world 2840 + Hello, world 2841 + Hello, world 2842 + Hello, world 2843 + Hello, world 2844 + Hello, world 2845 + Hello, world 2846 + Hello, world 2847 + Hello, world 2848 + Hello, world 2849 + Hello, world 2850 + Hello, world 2851 + Hello, world 2852 + Hello, world 2853 + Hello, world 2854 + Hello, world 2855 + Hello, world 2856 + Hello, world 2857 + Hello, world 2858 + Hello, world 2859 + Hello, world 2860 + Hello, world 2861 + Hello, world 2862 + Hello, world 2863 + Hello, world 2864 + Hello, world 2865 + Hello, world 2866 + Hello, world 2867 + Hello, world 2868 + Hello, world 2869 + Hello, world 2870 + Hello, world 2871 + Hello, world 2872 + Hello, world 2873 + Hello, world 2874 + Hello, world 2875 + Hello, world 2876 + Hello, world 2877 + Hello, world 2878 + Hello, world 2879 + Hello, world 2880 + Hello, world 2881 + Hello, world 2882 + Hello, world 2883 + Hello, world 2884 + Hello, world 2885 + Hello, world 2886 + Hello, world 2887 + Hello, world 2888 + Hello, world 2889 + Hello, world 2890 + Hello, world 2891 + Hello, world 2892 + Hello, world 2893 + Hello, world 2894 + Hello, world 2895 + Hello, world 2896 + Hello, world 2897 + Hello, world 2898 + Hello, world 2899 + Hello, world 2900 + Hello, world 2901 + Hello, world 2902 + Hello, world 2903 + Hello, world 2904 + Hello, world 2905 + Hello, world 2906 + Hello, world 2907 + Hello, world 2908 + Hello, world 2909 + Hello, world 2910 + Hello, world 2911 + Hello, world 2912 + Hello, world 2913 + Hello, world 2914 + Hello, world 2915 + Hello, world 2916 + Hello, world 2917 + Hello, world 2918 + Hello, world 2919 + Hello, world 2920 + Hello, world 2921 + Hello, world 2922 + Hello, world 2923 + Hello, world 2924 + Hello, world 2925 + Hello, world 2926 + Hello, world 2927 + Hello, world 2928 + Hello, world 2929 + Hello, world 2930 + Hello, world 2931 + Hello, world 2932 + Hello, world 2933 + Hello, world 2934 + Hello, world 2935 + Hello, world 2936 + Hello, world 2937 + Hello, world 2938 + Hello, world 2939 + Hello, world 2940 + Hello, world 2941 + Hello, world 2942 + Hello, world 2943 + Hello, world 2944 + Hello, world 2945 + Hello, world 2946 + Hello, world 2947 + Hello, world 2948 + Hello, world 2949 + Hello, world 2950 + Hello, world 2951 + Hello, world 2952 + Hello, world 2953 + Hello, world 2954 + Hello, world 2955 + Hello, world 2956 + Hello, world 2957 + Hello, world 2958 + Hello, world 2959 + Hello, world 2960 + Hello, world 2961 + Hello, world 2962 + Hello, world 2963 + Hello, world 2964 + Hello, world 2965 + Hello, world 2966 + Hello, world 2967 + Hello, world 2968 + Hello, world 2969 + Hello, world 2970 + Hello, world 2971 + Hello, world 2972 + Hello, world 2973 + Hello, world 2974 + Hello, world 2975 + Hello, world 2976 + Hello, world 2977 + Hello, world 2978 + Hello, world 2979 + Hello, world 2980 + Hello, world 2981 + Hello, world 2982 + Hello, world 2983 + Hello, world 2984 + Hello, world 2985 + Hello, world 2986 + Hello, world 2987 + Hello, world 2988 + Hello, world 2989 + Hello, world 2990 + Hello, world 2991 + Hello, world 2992 + Hello, world 2993 + Hello, world 2994 + Hello, world 2995 + Hello, world 2996 + Hello, world 2997 + Hello, world 2998 + Hello, world 2999 + Hello, world 3000 + \ No newline at end of file diff --git a/plugins/android/testData/dom/layout/resourceHighlightingPerformance.xml b/plugins/android/testData/dom/layout/resourceHighlightingPerformance.xml new file mode 100644 index 000000000000..0575d22724e7 --- /dev/null +++ b/plugins/android/testData/dom/layout/resourceHighlightingPerformance.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/android/testData/dom/layout/resourceNavigationPerformance.xml b/plugins/android/testData/dom/layout/resourceNavigationPerformance.xml new file mode 100644 index 000000000000..a71cac2ede0a --- /dev/null +++ b/plugins/android/testData/dom/layout/resourceNavigationPerformance.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java index 87f9b214b213..5c4513f6cedf 100644 --- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java @@ -12,6 +12,9 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; import org.jetbrains.android.inspections.CreateFileResourceQuickFix; import org.jetbrains.android.inspections.CreateValueResourceQuickFix; @@ -405,26 +408,67 @@ public class AndroidLayoutDomTest extends AndroidDomTest { toTestCompletion(getTestName(true) + ".xml", getTestName(true) + "_after.xml"); } - /*public void testCustomAttrsPerformance() throws Throwable { + public void testCustomAttrsPerformance() throws Throwable { myFixture.copyFileToProject("dom/resources/bigfile.xml", "res/values/bigfile.xml"); myFixture.copyFileToProject("dom/resources/bigattrs.xml", "res/values/bigattrs.xml"); myFixture.copyFileToProject("dom/resources/bigattrs.xml", "res/values/bigattrs1.xml"); myFixture.copyFileToProject("dom/resources/bigattrs.xml", "res/values/bigattrs2.xml"); myFixture.copyFileToProject("dom/resources/bigattrs.xml", "res/values/bigattrs3.xml"); - String path = copyFileToProject("bigfile.xml"); - VirtualFile f = myFixture.findFileInTempDir(path); + VirtualFile f = copyFileToProject("bigfile.xml"); myFixture.configureFromExistingVirtualFile(f); - IdeaTestUtil.assertTiming("", 800, new Runnable() { + + PlatformTestUtil.startPerformanceTest("android custom attrs highlighting is slow", 800, new ThrowableRunnable() { @Override - public void run() { - try { - myFixture.doHighlighting(); - } - catch (Exception e) { + public void run() throws Throwable { + myFixture.doHighlighting(); + } + }).attempts(2).cpuBound().usesAllCPUCores().assertTiming(); + } + + public void testResourceHighlightingPerformance() throws Throwable { + doCopyManyStrings(); + final VirtualFile f = copyFileToProject(getTestName(true) + ".xml"); + myFixture.configureFromExistingVirtualFile(f); + PlatformTestUtil.startPerformanceTest("android highlighting is slow", 400, new ThrowableRunnable() { + @Override + public void run() throws Throwable { + myFixture.doHighlighting(); + } + }).attempts(2).cpuBound().usesAllCPUCores().assertTiming(); + } + + public void testResourceNavigationPerformance() throws Throwable { + doCopyManyStrings(); + final VirtualFile f = copyFileToProject(getTestName(true) + ".xml"); + myFixture.configureFromExistingVirtualFile(f); + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + final List navElements = new ArrayList(); + + // warm + myFixture.doHighlighting(); + + PlatformTestUtil.startPerformanceTest("android highlighting is slow", 7000, new ThrowableRunnable() { + @SuppressWarnings("ConstantConditions") + @Override + public void run() throws Throwable { + final PsiReference reference = TargetElementUtilBase.findReference(myFixture.getEditor(), myFixture.getCaretOffset()); + final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false); + for (ResolveResult result : results) { + final PsiElement navElement = result.getElement().getNavigationElement(); + assertInstanceOf(navElement, XmlAttributeValue.class); + navElements.add(navElement); } } - }); - }*/ + }).attempts(1).cpuBound().usesAllCPUCores().assertTiming(); + assertEquals(31, navElements.size()); + } + + private void doCopyManyStrings() { + myFixture.copyFileToProject(testFolder + "/many_strings.xml", "res/values/strings.xml"); + for (int i = 0; i < 30; i++) { + myFixture.copyFileToProject(testFolder + "/many_strings.xml", "res/values-" + Integer.toString(i) + "/strings.xml"); + } + } public void testViewClassReference() throws Throwable { VirtualFile file = myFixture.copyFileToProject(testFolder + "/vcr.xml", getPathToCopy("vcr.xml")); diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java index 0e118ae028ca..662ba9615541 100644 --- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java @@ -30,9 +30,9 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; -import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.refactoring.actions.InlineAction; import com.intellij.refactoring.util.CommonRefactoringUtil; +import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper; import org.jetbrains.android.inspections.CreateValueResourceQuickFix; import java.util.ArrayList; @@ -252,7 +252,8 @@ public class AndroidValueResourcesTest extends AndroidDomTest { PsiReference rootReference = psiFile.findReferenceAt(rootOffset); assertNotNull(rootReference); PsiElement element = rootReference.resolve(); - assertTrue("Must be PsiClass reference", element instanceof XmlAttributeValue); + assertInstanceOf(element, LazyValueResourceElementWrapper.class); + assertNotNull(((LazyValueResourceElementWrapper)element).computeElement()); } // see getPathToCopy() From 53d419be420757cf31857cd4c977cc6d756df1c2 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 27 Jul 2012 18:46:53 +0400 Subject: [PATCH 14/16] AndroidResourceReference#computeTargetElements --- .../converters/AndroidResourceReference.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReference.java b/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReference.java index 0b8fabf89d36..d70177c627ce 100644 --- a/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReference.java +++ b/plugins/android/src/org/jetbrains/android/dom/converters/AndroidResourceReference.java @@ -29,6 +29,7 @@ import org.jetbrains.android.dom.AndroidDomUtil; import org.jetbrains.android.dom.resources.ResourceValue; import org.jetbrains.android.dom.wrappers.FileResourceElementWrapper; import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper; +import org.jetbrains.android.dom.wrappers.ResourceElementWrapper; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.resourceManagers.ResourceManager; import org.jetbrains.android.resourceManagers.ValueResourceInfo; @@ -103,6 +104,29 @@ public class AndroidResourceReference extends PsiReferenceBase.Poly return null; } + @NotNull + public PsiElement[] computeTargetElements() { + final ResolveResult[] resolveResults = multiResolve(false); + final List results = new ArrayList(); + + for (ResolveResult result : resolveResults) { + PsiElement element = result.getElement(); + + if (element instanceof LazyValueResourceElementWrapper) { + element = ((LazyValueResourceElementWrapper)element).computeElement(); + } + + if (element instanceof ResourceElementWrapper) { + element = ((ResourceElementWrapper)element).getWrappee(); + } + + if (element != null) { + results.add(element); + } + } + return results.toArray(new PsiElement[results.size()]); + } + @NotNull @Override public ResolveResult[] multiResolve(boolean incompleteCode) { @@ -132,9 +156,6 @@ public class AndroidResourceReference extends PsiReferenceBase.Poly } for (PsiElement target : elements) { - /*final PsiElement e = target instanceof NavigationItem && target instanceof XmlAttributeValue - ? new ValueResourceElementWrapper((XmlAttributeValue)target) - : target;*/ result.add(new PsiElementResolveResult(target)); } return result.toArray(new ResolveResult[result.size()]); From 06c77e01c6b8c133c0bc65554235eb514a7ea9e7 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 27 Jul 2012 16:55:03 +0200 Subject: [PATCH 15/16] Tree fixes for GTK+ --- .../com/intellij/ui/treeStructure/Tree.java | 2 +- .../intellij/ide/ui/laf/LafManagerImpl.java | 4 ++- .../util/src/com/intellij/util/ui/UIUtil.java | 2 +- .../util/ui/tree/WideSelectionTreeUI.java | 33 +++++++++---------- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 679df971801a..eacc8688fae9 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -96,7 +96,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith public void setUI(final TreeUI ui) { TreeUI actualUI = ui; if (!isCustomUI()) { - if (!(ui instanceof WideSelectionTreeUI) && isWideSelection()) { + if (!(ui instanceof WideSelectionTreeUI) && isWideSelection() && !UIUtil.isUnderGTKLookAndFeel()) { actualUI = new WideSelectionTreeUI(isWideSelection(), !SystemInfo.isMac); } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index ba747981a289..c4b9bfeb032a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -487,7 +487,9 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo uiDefaults.put("TextField.selectionBackground", bg); uiDefaults.put("RadioButtonMenuItem.selectionBackground", bg); uiDefaults.put("CheckBoxMenuItem.selectionBackground", bg); - } if (UIUtil.isUnderMetalLookAndFeel()) { + } + + if (UIUtil.isUnderMetalLookAndFeel()) { uiDefaults.put("Tree.hash", new ColorUIResource(117, 117, 117)); } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 0ee3eafc737f..7ca0122625a4 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -947,7 +947,7 @@ public class UIUtil { } public static boolean isFullRowSelectionLAF() { - return isUnderQuaquaLookAndFeel(); + return isUnderGTKLookAndFeel() || isUnderQuaquaLookAndFeel(); } public static boolean isUnderNativeMacLookAndFeel() { diff --git a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java index 30e58d5e1039..54ee6e81a4b1 100644 --- a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java +++ b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java @@ -40,17 +40,19 @@ public class WideSelectionTreeUI extends BasicTreeUI { @NonNls public static final String SOURCE_LIST_CLIENT_PROPERTY = "mac.ui.source.list"; @NonNls public static final String STRIPED_CLIENT_PROPERTY = "mac.ui.striped"; - private static final Icon TREE_COLLAPSED_ICON = UIUtil.getTreeCollapsedIcon(); - private static final Icon TREE_EXPANDED_ICON = UIUtil.getTreeExpandedIcon(); - private static final Icon TREE_SELECTED_COLLAPSED_ICON = UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel() - ? AllIcons.Mac.Tree_white_right_arrow : TREE_COLLAPSED_ICON; - private static final Icon TREE_SELECTED_EXPANDED_ICON = UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel() - ? AllIcons.Mac.Tree_white_down_arrow : TREE_EXPANDED_ICON; + private static Icon getTreeSelectedCollapsedIcon() { + return UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel() || UIUtil.isUnderGTKLookAndFeel() + ? AllIcons.Mac.Tree_white_right_arrow : UIUtil.getTreeCollapsedIcon(); + } - private static final Border LIST_BACKGROUND_PAINTER = (Border)UIManager.get("List.sourceListBackgroundPainter"); - private static final Border LIST_SELECTION_BACKGROUND_PAINTER = (Border)UIManager.get("List.sourceListSelectionBackgroundPainter"); - private static final Border LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER = - (Border)UIManager.get("List.sourceListFocusedSelectionBackgroundPainter"); + private static Icon getTreeSelectedExpandedIcon() { + return UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel() || UIUtil.isUnderGTKLookAndFeel() + ? AllIcons.Mac.Tree_white_down_arrow : UIUtil.getTreeExpandedIcon(); + } + + private static final Border LIST_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListBackgroundPainter"); + private static final Border LIST_SELECTION_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListSelectionBackgroundPainter"); + private static final Border LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER = UIManager.getBorder("List.sourceListFocusedSelectionBackgroundPainter"); private boolean myWideSelection; private boolean myAlwaysPaintRowBackground; @@ -106,9 +108,6 @@ public class WideSelectionTreeUI extends BasicTreeUI { tree.setShowsRootHandles(true); tree.addMouseListener(mySelectionListener); - - //final InputMap inputMap = tree.getInputMap(JComponent.WHEN_FOCUSED); - //inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "clearSelection"); } @Override @@ -407,10 +406,10 @@ public class WideSelectionTreeUI extends BasicTreeUI { boolean isPathSelected = tree.getSelectionModel().isPathSelected(path); boolean dark = UIUtil.isUnderDarcula(); - Icon expandIcon = (isPathSelected && tree.hasFocus()) || dark ? TREE_SELECTED_EXPANDED_ICON - : TREE_EXPANDED_ICON; - Icon collapseIcon = (isPathSelected && tree.hasFocus()) || dark? TREE_SELECTED_COLLAPSED_ICON - : TREE_COLLAPSED_ICON; + Icon expandIcon = (isPathSelected && tree.hasFocus()) || dark ? getTreeSelectedExpandedIcon() + : UIUtil.getTreeExpandedIcon(); + Icon collapseIcon = (isPathSelected && tree.hasFocus()) || dark? getTreeSelectedCollapsedIcon() + : UIUtil.getTreeCollapsedIcon(); if (!isLeaf(row)) { From 56565a180297cc9a3b8fdd6fe45cd450cb961a48 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 27 Jul 2012 17:04:16 +0200 Subject: [PATCH 16/16] when there are camel humps, match only them with word starts --- .../completion/normal/NoForceBraces.java | 4 +++- .../com/intellij/psi/util/NameUtilTest.java | 12 ++++++++--- .../psi/codeStyle/MinusculeMatcher.java | 21 ++++++++++++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/java/java-tests/testData/codeInsight/completion/normal/NoForceBraces.java b/java/java-tests/testData/codeInsight/completion/normal/NoForceBraces.java index a967eee64cf0..79a7d549a5d6 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/NoForceBraces.java +++ b/java/java-tests/testData/codeInsight/completion/normal/NoForceBraces.java @@ -1,6 +1,8 @@ +import java.io.File; + public class Foo { void foo(boolean flag) { - if ('\\' == File.separach) + if ('\\' == File.separaCh) System.out.println(); } } diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java index f4a13533c64b..5fc411f7df22 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java @@ -226,6 +226,12 @@ public class NameUtilTest extends UsefulTestCase { assertMatches("text*:sh", "textField:shouldChangeCharactersInRange:replacementString:"); } + public void testFileStructure() { + assertMatches("hint", "height:int"); + assertDoesntMatch("Hint", "Height:int"); + assertMatches("getColor", "getBackground():Color"); + } + public void testMiddleMatchingMinimumTwoConsecutiveLettersInWordMiddle() { assertMatches("*fo", "reformat"); assertMatches("*f", "reFormat"); @@ -254,7 +260,7 @@ public class NameUtilTest extends UsefulTestCase { assertMatches("*Git", "BlaGitBla"); assertFalse(firstLetterMatcher("*Git").matches("BlagitBla")); assertMatches("*git", "BlagitBla"); - assertMatches("*Git*", "AtpGenerationItem"); + assertDoesntMatch("*Git*", "AtpGenerationItem"); assertMatches("Collec*Util*", "CollectionUtils"); assertMatches("Collec*Util*", "CollectionUtilsTest"); assertTrue(caseInsensitiveMatcher("*us").matches("usage")); @@ -307,7 +313,7 @@ public class NameUtilTest extends UsefulTestCase { assertMatches("foo", "fxOo"); assertMatches("foo", "fXOo"); assertMatches("fOo", "foo"); - assertMatches("fOo", "FaOaOaXXXX"); + assertDoesntMatch("fOo", "FaOaOaXXXX"); assertMatches("ncdfoe", "NoClassDefFoundException"); assertMatches("fob", "FOO_BAR"); assertMatches("fo_b", "FOO_BAR"); @@ -330,7 +336,7 @@ public class NameUtilTest extends UsefulTestCase { public void testFinalSpace() { assertMatches("GrDebT ", "GroovyDebuggerTest"); - assertMatches("grdebT ", "GroovyDebuggerTest"); + assertDoesntMatch("grdebT ", "GroovyDebuggerTest"); assertDoesntMatch("grdebt ", "GroovyDebuggerTest"); assertMatches("Foo ", "Foo"); assertDoesntMatch("Foo ", "FooBar"); diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java index 8f15d1bd3d13..d6a3fbd2b20a 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java +++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java @@ -33,10 +33,19 @@ import static com.intellij.psi.codeStyle.NameUtil.MatchingCaseSensitivity.*; public class MinusculeMatcher implements Matcher { private final char[] myPattern; private final NameUtil.MatchingCaseSensitivity myOptions; + private final boolean myHasHumps; public MinusculeMatcher(String pattern, NameUtil.MatchingCaseSensitivity options) { myOptions = options; myPattern = StringUtil.trimEnd(pattern, "* ").toCharArray(); + for (int i = 0; i < myPattern.length; i++) { + char c = myPattern[i]; + if (Character.isUpperCase(c)) { + myHasHumps = true; + return; + } + } + myHasHumps = false; } private static FList prependRange(FList ranges, int from, int length) { @@ -159,7 +168,7 @@ public class MinusculeMatcher implements Matcher { char p = myPattern[patternIndex]; while (true) { - nameIndex = space ? indexOfWordStart(name, p, nameIndex) : StringUtil.indexOfIgnoreCase(name, p, nameIndex + 1); + nameIndex = space ? indexOfWordStart(name, patternIndex, nameIndex) : StringUtil.indexOfIgnoreCase(name, p, nameIndex + 1); if (nameIndex < 0) { return null; } @@ -188,7 +197,7 @@ public class MinusculeMatcher implements Matcher { return null; } if (myPattern[patternIndex + i] != name.charAt(nameIndex + i)) { - int nextWordStart = indexOfWordStart(name, myPattern[patternIndex + i], nameIndex + i); + int nextWordStart = indexOfWordStart(name, patternIndex + i, nameIndex + i); FList ranges = matchWildcards(name, patternIndex + i, nextWordStart); if (ranges != null) { return prependRange(ranges, nameIndex, i); @@ -202,7 +211,7 @@ public class MinusculeMatcher implements Matcher { return i >= minFragment ? FList.emptyList().prepend(TextRange.from(nameIndex, i)) : null; } while (i >= minFragment) { - int nextWordStart = isWildcard(patternIndex + i) ? nameIndex + i : indexOfWordStart(name, myPattern[patternIndex + i], nameIndex + i); + int nextWordStart = isWildcard(patternIndex + i) ? nameIndex + i : indexOfWordStart(name, patternIndex + i, nameIndex + i); FList ranges = matchWildcards(name, patternIndex + i, nextWordStart); if (ranges != null) { return prependRange(ranges, nameIndex, i); @@ -225,11 +234,13 @@ public class MinusculeMatcher implements Matcher { return myPattern[patternIndex] == c; } - private static int indexOfWordStart(String name, char p, int startFrom) { + private int indexOfWordStart(String name, int patternIndex, int startFrom) { + char p = myPattern[patternIndex]; if (p == '.' || NameUtil.isWordSeparator(p)) { return StringUtil.indexOfIgnoreCase(name, p, startFrom + 1); } - if (startFrom >= name.length()) { + if (startFrom >= name.length() || + myHasHumps && Character.isLowerCase(p) && !(patternIndex > 0 && NameUtil.isWordSeparator(myPattern[patternIndex - 1]))) { return -1; } int nextWordStart = startFrom;