diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index 2367ce3deb11..81cb9b5e1185 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -193,14 +193,14 @@ public class AllClassesGetter { private static String getPackagePrefix(final PsiElement context, final int offset) { - final String fileText = context.getContainingFile().getText(); + final CharSequence fileText = context.getContainingFile().getViewProvider().getContents(); int i = offset - 1; while (i >= 0) { final char c = fileText.charAt(i); if (!Character.isJavaIdentifierPart(c) && c != '.') break; i--; } - String prefix = fileText.substring(i + 1, offset); + String prefix = fileText.subSequence(i + 1, offset).toString(); final int j = prefix.lastIndexOf('.'); return j > 0 ? prefix.substring(0, j) : ""; } diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java index ffdd14fc0aa8..dd38725d739f 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java @@ -49,13 +49,14 @@ import java.util.regex.Pattern; public class FileHeaderChecker { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defaultFileTemplateUsage.FileHeaderChecker"); + // abcdfghdjsjd kfkdjekr dfhakdjfk dkfkjgk dfjgjfkg ekfk fkgkvv ggkk eefkgjkdd jfkkkssl dfghgk gkhller hhksl lfflgl static ProblemDescriptor checkFileHeader(@NotNull final PsiFile file, final InspectionManager manager, boolean onTheFly) { TIntObjectHashMap offsetToProperty = new TIntObjectHashMap(); Pattern pattern = getTemplatePattern(FileTemplateManager.getInstance() .getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME), file.getProject(), offsetToProperty ); - Matcher matcher = pattern.matcher(file.getText()); + Matcher matcher = pattern.matcher(file.getViewProvider().getContents()); if (matcher.matches()) { final int startOffset = matcher.start(1); final int endOffset = matcher.end(1); diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java index fe8804c617ef..712bbad96583 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java @@ -150,7 +150,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem } public static boolean hasErrorElementsNearby(final PsiFile file, int startOffset, int endOffset) { - endOffset = CharArrayUtil.shiftForward(file.getText(), endOffset, " \t\n"); + endOffset = CharArrayUtil.shiftForward(file.getViewProvider().getContents(), endOffset, " \t\n"); for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffset)) { if (element instanceof PsiErrorElement) { return true; diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java index 27e4b34253a2..aa2cd7e42cdb 100644 --- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java +++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java @@ -43,16 +43,21 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { } // skip inners & anonymous + if (isInnerClass(vFile)) return null; + + return new ClsFileImpl(PsiManager.getInstance(project), this); + } + + public static boolean isInnerClass(VirtualFile vFile) { String name = vFile.getNameWithoutExtension(); int index = name.lastIndexOf('$', name.length()); if (index > 0 && index < name.length() - 1) { String supposedParentName = name.substring(0, index) + ".class"; if (vFile.getParent().findChild(supposedParentName) != null) { - return null; + return true; } } - - return new ClsFileImpl(PsiManager.getInstance(project), this); + return false; } @NotNull diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java index ccde0ccb3c12..3294e8f43199 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java @@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.ClassFileViewProvider; import com.intellij.psi.impl.source.JavaFileElementType; import com.intellij.psi.stubs.BinaryFileStubBuilder; import com.intellij.psi.stubs.PsiFileStub; @@ -39,7 +40,7 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder { @Override public boolean acceptsFile(final VirtualFile file) { - return true; + return !ClassFileViewProvider.isInnerClass(file); } @Override diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java index 7173a2318d5a..0a8a30bc0829 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java @@ -489,8 +489,8 @@ public class DirectoryIndexTest extends IdeaTestCase { checkInfoNull(module2TestOutput); assertFalse(myIndex.isProjectExcludeRoot(excluded)); - assertTrue(myIndex.isProjectExcludeRoot(projectOutput)); - assertTrue(myIndex.isProjectExcludeRoot(module2Output)); + assertFalse(myIndex.isProjectExcludeRoot(projectOutput)); + assertFalse(myIndex.isProjectExcludeRoot(module2Output)); assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput)); excluded.delete(this); @@ -508,12 +508,10 @@ public class DirectoryIndexTest extends IdeaTestCase { String fileName = e.getFileName(); if (fileName.equals("projectOutput")) { - //todo fix and uncomment -// assertTrue(myIndex.isProjectExcludeRoot(file)); + assertFalse(myIndex.isProjectExcludeRoot(file)); } if (fileName.equals("module2Output")) { - //todo fix and uncomment -// assertTrue(myIndex.isProjectExcludeRoot(file)); + assertFalse(myIndex.isProjectExcludeRoot(file)); } if (fileName.equals("module2TestOutput")) { assertFalse(myIndex.isProjectExcludeRoot(file)); @@ -526,10 +524,10 @@ public class DirectoryIndexTest extends IdeaTestCase { assertFalse(myIndex.isProjectExcludeRoot(excluded)); projectOutput = myModule1Dir.createChildDirectory(this, projectOutput.getName()); - assertTrue(myIndex.isProjectExcludeRoot(projectOutput)); + assertFalse(myIndex.isProjectExcludeRoot(projectOutput)); module2Output = myModule1Dir.createChildDirectory(this, module2Output.getName()); - assertTrue(myIndex.isProjectExcludeRoot(module2Output)); + assertFalse(myIndex.isProjectExcludeRoot(module2Output)); module2TestOutput = myModule2Dir.createChildDirectory(this, module2TestOutput.getName()); assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput)); @@ -542,8 +540,8 @@ public class DirectoryIndexTest extends IdeaTestCase { assertEquals(created.toString(), 4, created.size()); assertFalse(myIndex.isProjectExcludeRoot(excluded)); - assertTrue(myIndex.isProjectExcludeRoot(projectOutput)); - assertTrue(myIndex.isProjectExcludeRoot(module2Output)); + assertFalse(myIndex.isProjectExcludeRoot(projectOutput)); + assertFalse(myIndex.isProjectExcludeRoot(module2Output)); assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput)); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java index 5253ea835137..6b103542d115 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java @@ -49,7 +49,7 @@ public class CharTableImpl implements CharTable { @NotNull public CharSequence doIntern(@NotNull CharSequence text) { - CharSequence interned = getStaticInterned(text.toString()); + CharSequence interned = getStaticInterned(text); if (interned != null) { return interned; } @@ -85,7 +85,7 @@ public class CharTableImpl implements CharTable { } @Nullable - public static CharSequence getStaticInterned(@NotNull String text) { + public static CharSequence getStaticInterned(@NotNull CharSequence text) { return STATIC_ENTRIES.get(text); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java index 4d1eea7f4133..76ca0b57c8f5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java @@ -145,8 +145,9 @@ class CompletionAssertions { } final TextRange range = insertedElement.getTextRange(); - String fileCopyText = fileCopy.getText(); - if ((range.getEndOffset() > fileCopyText.length()) || !range.substring(fileCopyText).equals(insertedElement.getText())) { + CharSequence fileCopyText = fileCopy.getViewProvider().getContents(); + if ((range.getEndOffset() > fileCopyText.length()) || + !fileCopyText.subSequence(range.getStartOffset(), range.getEndOffset()).toString().equals(insertedElement.getText())) { throw new LogEventException("Inconsistent completion tree", "range=" + range + "\n" + DebugUtil.currentStackTrace(), createFileTextAttachment(fileCopy, originalFile), createAstAttachment(fileCopy, originalFile), new Attachment("Element at caret.txt", insertedElement.getText())); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 4efaf7f78efc..1565d9e50671 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -84,7 +84,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull final CompletionContributor contributor) { final PsiElement position = parameters.getPosition(); final String prefix = CompletionData.findPrefixStatic(position, parameters.getOffset()); - final String textBeforePosition = parameters.getPosition().getContainingFile().getText().substring(0, parameters.getOffset()); + final int lengthOfTextBeforePosition = parameters.getOffset(); ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (!(indicator instanceof CompletionProgressIndicator)) { throw new AssertionError("createResultSet may be invoked only from completion thread: " + indicator + "!=" + getCurrentCompletion() + "; phase set at " + ourPhaseTrace); @@ -92,7 +92,7 @@ public class CompletionServiceImpl extends CompletionService{ CompletionProgressIndicator process = (CompletionProgressIndicator)indicator; CamelHumpMatcher matcher = new CamelHumpMatcher(prefix); CompletionSorterImpl sorter = defaultSorter(parameters, matcher); - return new CompletionResultSetImpl(consumer, textBeforePosition, matcher, contributor,parameters, sorter, process, null); + return new CompletionResultSetImpl(consumer, lengthOfTextBeforePosition, matcher, contributor,parameters, sorter, process, null); } @Override @@ -105,13 +105,13 @@ public class CompletionServiceImpl extends CompletionService{ } private static class CompletionResultSetImpl extends CompletionResultSet { - private final String myTextBeforePosition; + private final int myLengthOfTextBeforePosition; private final CompletionParameters myParameters; private final CompletionSorterImpl mySorter; private final CompletionProgressIndicator myProcess; @Nullable private final CompletionResultSetImpl myOriginal; - public CompletionResultSetImpl(final Consumer consumer, final String textBeforePosition, + public CompletionResultSetImpl(final Consumer consumer, final int lengthOfTextBeforePosition, final PrefixMatcher prefixMatcher, CompletionContributor contributor, CompletionParameters parameters, @@ -119,7 +119,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull CompletionProgressIndicator process, @Nullable CompletionResultSetImpl original) { super(prefixMatcher, consumer, contributor); - myTextBeforePosition = textBeforePosition; + myLengthOfTextBeforePosition = lengthOfTextBeforePosition; myParameters = parameters; mySorter = sorter; myProcess = process; @@ -142,7 +142,7 @@ public class CompletionServiceImpl extends CompletionService{ @Override @NotNull public CompletionResultSet withPrefixMatcher(@NotNull final PrefixMatcher matcher) { - return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, myParameters, mySorter, myProcess, this); + return new CompletionResultSetImpl(getConsumer(), myLengthOfTextBeforePosition, matcher, myContributor, myParameters, mySorter, myProcess, this); } @Override @@ -165,7 +165,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull @Override public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) { - return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl)sorter, myProcess, this); + return new CompletionResultSetImpl(getConsumer(), myLengthOfTextBeforePosition, getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl)sorter, myProcess, this); } @Override @@ -183,7 +183,7 @@ public class CompletionServiceImpl extends CompletionService{ public void restartCompletionOnPrefixChange(ElementPattern prefixCondition) { final CompletionProgressIndicator indicator = getCompletionService().getCurrentCompletion(); if (indicator != null) { - indicator.addWatchedPrefix(myTextBeforePosition.length() - getPrefixMatcher().getPrefix().length(), prefixCondition); + indicator.addWatchedPrefix(myLengthOfTextBeforePosition - getPrefixMatcher().getPrefix().length(), prefixCondition); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java index 3a5c3ecf355d..c56f397cc1f1 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java @@ -109,7 +109,9 @@ public class ProjectJdkTableImpl extends ProjectJdkTable implements PersistentSt @Override @Nullable public Sdk findJdk(String name) { - for (Sdk jdk : mySdks) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0, len = mySdks.size(); i < len; ++i) { // avoid foreach, it instantiates ArrayList$Itr, this traversal happens very often + final Sdk jdk = mySdks.get(i); if (Comparing.strEqual(name, jdk.getName())) { return jdk; } diff --git a/platform/platform-api/src/com/intellij/ui/TextFieldWithHistory.java b/platform/platform-api/src/com/intellij/ui/TextFieldWithHistory.java index 18fe61600378..94ce40cb8f18 100644 --- a/platform/platform-api/src/com/intellij/ui/TextFieldWithHistory.java +++ b/platform/platform-api/src/com/intellij/ui/TextFieldWithHistory.java @@ -16,7 +16,7 @@ package com.intellij.ui; import com.intellij.openapi.fileChooser.FileTextField; -import com.intellij.openapi.ui.ComboBoxWithWidePopup; +import com.intellij.openapi.ui.ComboBox; import javax.swing.*; import javax.swing.event.DocumentListener; @@ -25,7 +25,7 @@ import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; -public class TextFieldWithHistory extends ComboBoxWithWidePopup { +public class TextFieldWithHistory extends ComboBox { private int myHistorySize = 5; private final MyModel myModel; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index 1a9343f82a67..148405d35bdf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -148,7 +148,8 @@ public class ComplementaryFontsRegistry { boolean tryDefaultFont = true; List fontFamilies = preferences.getEffectiveFontFamilies(); FontInfo result; - for (String fontFamily : fontFamilies) { + for (int i = 0, len = fontFamilies.size(); i < len; ++i) { + final String fontFamily = fontFamilies.get(i); result = doGetFontAbleToDisplay(c, preferences.getSize(fontFamily), style, fontFamily); if (result != null) { return result; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java index d1169db10e98..b50cacb01160 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.ex.*; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.util.Comparing; +import com.intellij.util.ArrayUtilRt; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -86,14 +87,14 @@ public final class IterationState { private int myEndOffset; private final int myEnd; - private final int mySelectionStart; + private final int[] mySelectionStarts; + private final int[] mySelectionEnds; + private int myCurrentSelectionIndex = 0; - private final int mySelectionEnd; private final List myCurrentHighlighters = new ArrayList(); private final FoldingModelEx myFoldingModel; - private final boolean hasSelection; private FoldRegion myCurrentFold = null; private final TextAttributes myFoldTextAttributes; private final TextAttributes mySelectionAttributes; @@ -121,9 +122,9 @@ public final class IterationState { LOG.assertTrue(myStartOffset <= myEnd); myHighlighterIterator = editor.getHighlighter().createIterator(start); - hasSelection = useCaretAndSelection && editor.getSelectionModel().hasSelection(); - mySelectionStart = hasSelection ? editor.getSelectionModel().getSelectionStart() : -1; - mySelectionEnd = hasSelection ? editor.getSelectionModel().getSelectionEnd() : -1; + boolean hasSelection = useCaretAndSelection && (editor.getSelectionModel().hasSelection() || editor.getSelectionModel().hasBlockSelection()); + mySelectionStarts = hasSelection ? editor.getSelectionModel().getBlockSelectionStarts() : ArrayUtilRt.EMPTY_INT_ARRAY; + mySelectionEnds = hasSelection ? editor.getSelectionModel().getBlockSelectionEnds() : ArrayUtilRt.EMPTY_INT_ARRAY; myFoldingModel = editor.getFoldingModel(); myFoldTextAttributes = myFoldingModel.getPlaceholderAttributes(); @@ -235,13 +236,14 @@ public final class IterationState { public void advance() { myStartOffset = myEndOffset; advanceSegmentHighlighters(); + advanceCurrentSelectionIndex(); myCurrentFold = myFoldingModel.fetchOutermost(myStartOffset); if (myCurrentFold != null) { myEndOffset = myCurrentFold.getEndOffset(); } else { - myEndOffset = Math.min(getHighlighterEnd(myStartOffset), getSelectionEnd(myStartOffset)); + myEndOffset = Math.min(getHighlighterEnd(myStartOffset), getSelectionEnd()); myEndOffset = Math.min(myEndOffset, getMinSegmentHighlightersEnd()); myEndOffset = Math.min(myEndOffset, getFoldRangesEnd(myStartOffset)); myEndOffset = Math.min(myEndOffset, getCaretEnd(myStartOffset)); @@ -290,17 +292,26 @@ public final class IterationState { return min; } - private int getSelectionEnd(int start) { - if (!hasSelection) { + private void advanceCurrentSelectionIndex() { + while (myCurrentSelectionIndex < mySelectionEnds.length && myStartOffset >= mySelectionEnds[myCurrentSelectionIndex]) { + myCurrentSelectionIndex++; + } + } + + private int getSelectionEnd() { + if (myCurrentSelectionIndex >= mySelectionStarts.length) { return myEnd; } - if (mySelectionStart > start) { - return mySelectionStart; + if (myStartOffset < mySelectionStarts[myCurrentSelectionIndex]) { + return mySelectionStarts[myCurrentSelectionIndex]; } - if (mySelectionEnd > start) { - return mySelectionEnd; + else { + return mySelectionEnds[myCurrentSelectionIndex]; } - return myEnd; + } + + private boolean isInSelection() { + return myCurrentSelectionIndex < mySelectionStarts.length && myStartOffset >= mySelectionStarts[myCurrentSelectionIndex]; } private void advanceSegmentHighlighters() { @@ -362,7 +373,7 @@ public final class IterationState { return; } - boolean isInSelection = hasSelection && myStartOffset >= mySelectionStart && myStartOffset < mySelectionEnd; + boolean isInSelection = isInSelection(); boolean isInCaretRow = myStartOffset >= myCaretRowStart && myStartOffset < myCaretRowEnd; boolean isInGuardedBlock = myDocument.getOffsetGuard(myStartOffset) != null; diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index fcd1e2687a5e..0c172ec2e2f6 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -256,7 +256,7 @@ dump.threads.on.empty.lookup.description=Whether IDEA should issue a thread dump file.structure.tree.mode=true -directory.index.use.root.index=false +directory.index.use.root.index=true directory.index.use.root.index.description=Requires restart directory.index.compare.implementations=false directory.index.compare.implementations.description=Will make the IDE slow. Requires restart diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java new file mode 100644 index 000000000000..d9d925ea835b --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl; + +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase { + + public void testBlockSelection() { + verifySplitting("aa,bb\ncc,dd", + new Segment(0, 3, Color.BLACK), + new Segment(3, 4, Color.WHITE), + new Segment(4, 5, Color.BLACK), + new Segment(5, 6, Color.BLACK), + new Segment(6, 9, Color.BLACK), + new Segment(9, 10, Color.WHITE), + new Segment(10, 11, Color.BLACK)); + } + + private void verifySplitting(String text, Segment... expectedSegments) { + myFixture.configureByText(PlainTextFileType.INSTANCE, text); + EditorEx editor = (EditorEx)myFixture.getEditor(); + IterationState iterationState = new IterationState(editor, 0, editor.getDocument().getTextLength(), true); + try { + List actualSegments = new ArrayList(); + do { + actualSegments.add(new Segment(iterationState.getStartOffset(), + iterationState.getEndOffset(), + iterationState.getMergedAttributes().getForegroundColor())); + iterationState.advance(); + } + while (!iterationState.atEnd()); + + Assert.assertArrayEquals(expectedSegments, actualSegments.toArray()); + } + finally { + iterationState.dispose(); + } + } + + private static class Segment { + private final int start; + private final int end; + private final Color fgColor; + + private Segment(int start, int end, @NotNull Color fgColor) { + this.start = start; + this.end = end; + this.fgColor = fgColor; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Segment segment = (Segment)o; + + if (end != segment.end) return false; + if (start != segment.start) return false; + if (!fgColor.equals(segment.fgColor)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = start; + result = 31 * result + end; + result = 31 * result + fgColor.hashCode(); + return result; + } + + @Override + public String toString() { + return "Segment{" + + "start=" + start + + ", end=" + end + + ", color=" + fgColor + + '}'; + } + } +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java index a09136ae3234..c82f1247234e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java @@ -92,7 +92,6 @@ public class VcsLogUI { public void run() { myMainFrame.getGraphTable().setPreferredColumnWidths(); myMainFrame.getGraphTable().repaint(); - myMainFrame.refresh(); } }); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 70dad0732dba..44f58ddc67ae 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -1,6 +1,7 @@ package com.intellij.vcs.log.ui.frame; import com.google.common.collect.Ordering; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.vfs.VirtualFile; @@ -75,6 +76,14 @@ public class BranchesPanel extends JPanel { } } }); + + Project project = dataHolder.getProject(); + project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new Runnable() { + @Override + public void run() { + rebuild(); + } + }); } @Nullable diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index c58abbb17ff4..8c6fd2f2486a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -199,10 +199,6 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { return this; } - public void refresh() { - myBranchesPanel.rebuild(); - } - public void setBranchesPanelVisible(boolean visible) { myBranchesPanel.setVisible(visible); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java index 0752ce3ebdbc..cdec1d772f4a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java @@ -51,16 +51,16 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender { @Override protected int getLeftPadding(JTable table, @Nullable Object value) { GraphCommitCell cell = (GraphCommitCell)value; - if (cell == null) { return 0; } + return calcPaddingBeforeText(cell, (Graphics2D)table.getGraphics()); + } - int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), (Graphics2D)table.getGraphics()); - + private int calcPaddingBeforeText(GraphCommitCell cell, Graphics2D g) { + int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), g); int countCells = cell.getPrintCell().countCell(); int graphPadding = countCells * WIDTH_NODE; - return refPadding + graphPadding; } @@ -82,7 +82,8 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender { return; } - BufferedImage image = UIUtil.createImage(1000, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB); + int width = calcPaddingBeforeText(cell, (Graphics2D)g); + BufferedImage image = UIUtil.createImage(width, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); g2.setBackground(new Color(0, 0, 0, 0)); diff --git a/plugins/git4idea/src/git4idea/log/GitRefManager.java b/plugins/git4idea/src/git4idea/log/GitRefManager.java index 867b8258df97..5b60076f68e7 100644 --- a/plugins/git4idea/src/git4idea/log/GitRefManager.java +++ b/plugins/git4idea/src/git4idea/log/GitRefManager.java @@ -3,7 +3,9 @@ package git4idea.log; import com.intellij.dvcs.repo.RepositoryManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.RefGroup; @@ -12,14 +14,11 @@ import com.intellij.vcs.log.VcsRef; import com.intellij.vcs.log.VcsRefType; import com.intellij.vcs.log.impl.SingletonRefGroup; import git4idea.GitBranch; -import git4idea.GitLocalBranch; import git4idea.GitRemoteBranch; -import git4idea.branch.GitBranchesCollection; import git4idea.repo.GitBranchTrackInfo; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.*; @@ -136,36 +135,39 @@ public class GitRefManager implements VcsLogRefManager { List trackedBranches = ContainerUtil.newArrayList(); MultiMap remoteRefGroups = MultiMap.create(); - for (VcsRef ref : refs) { - if (ref.getType() == HEAD) { - simpleGroups.add(new SingletonRefGroup(ref)); + MultiMap refsByRoot = groupRefsByRoot(refs); + for (Map.Entry> entry : refsByRoot.entrySet()) { + VirtualFile root = entry.getKey(); + Collection refsInRoot = entry.getValue(); + + GitRepository repository = myRepositoryManager.getRepositoryForRoot(root); + if (repository == null) { + LOG.warn("No repository for root: " + root); + continue; } - else { - GitRepository repository = myRepositoryManager.getRepositoryForRoot(ref.getRoot()); - if (repository == null) { - LOG.warn("No repository for root: " + ref.getRoot()); + + Set locals = getLocalBranches(repository); + Set tracked = getTrackedRemoteBranches(repository); + Map nonTracked = getNonTrackedRemoteBranches(repository); + + for (VcsRef ref : refsInRoot) { + if (ref.getType() == HEAD) { + simpleGroups.add(new SingletonRefGroup(ref)); continue; } - Collection trackInfos = repository.getBranchTrackInfos(); - GitBranchesCollection branches = repository.getBranches(); - GitLocalBranch localBranch = findBranchByName(ref, branches.getLocalBranches()); - if (localBranch != null) { + String refName = ref.getName(); + if (locals.contains(refName)) { localBranches.add(ref); } + else if (tracked.contains(refName)) { + trackedBranches.add(ref); + } + else if (nonTracked.containsKey(refName)) { + remoteRefGroups.putValue(nonTracked.get(refName), ref); + } else { - GitRemoteBranch remoteBranch = findBranchByName(ref, branches.getRemoteBranches()); - if (remoteBranch != null) { - if (isTracked(trackInfos, remoteBranch)) { - trackedBranches.add(ref); - } - else { - remoteRefGroups.putValue(remoteBranch.getRemote(), ref); - } - } - else { - LOG.warn("Didn't find ref neither in local nor in remote branches: " + ref); - } + LOG.warn("Didn't find ref neither in local nor in remote branches: " + ref); } } } @@ -182,23 +184,57 @@ public class GitRefManager implements VcsLogRefManager { return result; } - @Nullable - private static T findBranchByName(final VcsRef ref, Collection branches) { - return ContainerUtil.find(branches, new Condition() { + private static Set getLocalBranches(GitRepository repository) { + return ContainerUtil.map2Set(repository.getBranches().getLocalBranches(), new Function() { @Override - public boolean value(T branch) { - return branch.getName().equals(ref.getName()); + public String fun(GitBranch branch) { + return branch.getName(); } }); } - private static boolean isTracked(Collection trackInfos, final GitRemoteBranch remoteBranch) { - return ContainerUtil.find(trackInfos, new Condition() { - @Override - public boolean value(GitBranchTrackInfo info) { - return info.getRemoteBranch().equals(remoteBranch); + @NotNull + private static Set getTrackedRemoteBranches(@NotNull GitRepository repository) { + Set all = new HashSet(repository.getBranches().getRemoteBranches()); + Set tracked = new HashSet(); + for (GitBranchTrackInfo info : repository.getBranchTrackInfos()) { + GitRemoteBranch trackedRemoteBranch = info.getRemoteBranch(); + if (all.contains(trackedRemoteBranch)) { // check that this branch really exists, not just written in .git/config + tracked.add(trackedRemoteBranch.getName()); } - }) != null; + } + return tracked; + } + + @NotNull + private static Map getNonTrackedRemoteBranches(@NotNull GitRepository repository) { + Set all = new HashSet(repository.getBranches().getRemoteBranches()); + Set tracked = getTrackedRemoteBranchesFromConfig(repository); + Map nonTracked = ContainerUtil.newHashMap(); + for (GitRemoteBranch remoteBranch : all) { + if (!tracked.contains(remoteBranch.getName())) { + nonTracked.put(remoteBranch.getName(), remoteBranch.getRemote()); + } + } + return nonTracked; + } + + private static Set getTrackedRemoteBranchesFromConfig(GitRepository repository) { + return ContainerUtil.map2Set(repository.getBranchTrackInfos(), new Function() { + @Override + public String fun(GitBranchTrackInfo trackInfo) { + return trackInfo.getRemoteBranch().getName(); + } + }); + } + + @NotNull + private static MultiMap groupRefsByRoot(@NotNull Iterable refs) { + MultiMap grouped = MultiMap.create(); + for (VcsRef ref : refs) { + grouped.putValue(ref.getRoot(), ref); + } + return grouped; } private static class SimpleRefType implements VcsRefType { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java index bc96a546b9e1..e5291d7dc51e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java @@ -37,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; -import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrBlockImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrClosableBlockImpl; @@ -308,29 +307,7 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy GroovyElementType ANNOTATION_ARGUMENTS = new GroovyElementType("annotation arguments"); GroovyElementType ANNOTATION_MEMBER_VALUE_PAIR = new GroovyElementType("annotation member value pair"); - GrStubElementType ANNOTATION = new GrStubElementType("annotation") { - - @Override - public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) { - return new GrAnnotationImpl(stub); - } - - @Override - public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) { - return new GrAnnotationStub(parentStub, psi); - } - - @Override - public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { - dataStream.writeName(stub.getAnnotationName()); - } - - @NotNull - @Override - public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { - return new GrAnnotationStub(parentStub, dataStream.readName()); - } - }; + GrStubElementType ANNOTATION = new GrAnnotationElementType("annotation"); //parameters EmptyStubElementType PARAMETERS_LIST = new EmptyStubElementType("parameters list", GroovyFileType.GROOVY_LANGUAGE) { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index d60892b42b32..047fe23213cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -523,7 +523,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { @NotNull @Override public GrAnnotation createAnnotationFromText(@NotNull @NonNls String annotationText, @Nullable PsiElement context) throws IncorrectOperationException { - return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getAnnotations()[0]; + return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getRawAnnotations()[0]; } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java index 674bfe6d66c1..f82b8a08cd81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java @@ -82,20 +82,34 @@ public class GrAnnotationImpl extends GrStubElementBase implem @NotNull public GrAnnotationArgumentList getParameterList() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getParameterList(); + } return findNotNullChildByClass(GrAnnotationArgumentList.class); } @Nullable @NonNls public String getQualifiedName() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getQualifiedName(); + } + final GrCodeReferenceElement nameRef = getClassReference(); final PsiElement resolved = nameRef.resolve(); - if (resolved instanceof PsiClass) return ((PsiClass) resolved).getQualifiedName(); + if (resolved instanceof PsiClass) return ((PsiClass)resolved).getQualifiedName(); return null; } @Nullable public PsiJavaCodeReferenceElement getNameReferenceElement() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getNameReferenceElement(); + } + final GroovyResolveResult resolveResult = getClassReference().advancedResolve(); final PsiElement resolved = resolveResult.getElement(); @@ -107,6 +121,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem } } + @Nullable public PsiAnnotationMemberValue findAttributeValue(@Nullable String attributeName) { return PsiImplUtil.findAttributeValue(this, attributeName); } @@ -116,7 +131,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem return PsiImplUtil.findDeclaredAttributeValue(this, attributeName); } - public T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) { + public T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) { return (T)PsiImplUtil.setDeclaredAttributeValue(this, attributeName, value, ANNOTATION_CREATOR); } @@ -127,6 +142,11 @@ public class GrAnnotationImpl extends GrStubElementBase implem @NotNull public GrCodeReferenceElement getClassReference() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getClassReference(); + } + return findNotNullChildByClass(GrCodeReferenceElement.class); } @@ -134,13 +154,15 @@ public class GrAnnotationImpl extends GrStubElementBase implem public String getShortName() { final GrAnnotationStub stub = getStub(); if (stub != null) { - return stub.getAnnotationName(); - } - else { - return getClassReference().getReferenceName(); + return stub.getPsiElement().getShortName(); } + + final String referenceName = getClassReference().getReferenceName(); + assert referenceName != null; + return referenceName; } + @Nullable public PsiAnnotationOwner getOwner() { return (PsiAnnotationOwner)getParent(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java index 1ab1a1a26f81..990876dea044 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java @@ -42,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -85,7 +86,7 @@ public class GrVariableDeclarationImpl extends GrStubElementBase impl @NotNull public GrModifierList getModifierList() { - return (GrModifierList)findNotNullChildByType(GroovyElementTypes.MODIFIERS); + return getRequiredStubOrPsiChild(GroovyElementTypes.MODIFIERS); } @Override @@ -192,7 +193,7 @@ public class GrVariableDeclarationImpl extends GrStubElementBase impl @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { - if (lastParent != null && lastParent == getTupleInitializer()) { + if (lastParent != null && !(getParent() instanceof GrTypeDefinitionBody) && lastParent == getTupleInitializer()) { return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java index f78b7f34844c..c319fbd08adf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java @@ -1,28 +1,67 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.jetbrains.plugins.groovy.lang.psi.stubs; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; -import com.intellij.util.io.StringRef; +import com.intellij.reference.SoftReference; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; /** * @author peter */ public class GrAnnotationStub extends StubBase { - private final StringRef myReference; + private static final Logger LOG = Logger.getInstance(GrAnnotationStub.class); - public GrAnnotationStub(StubElement parent, StringRef reference) { + private final String myText; + private SoftReference myPsiRef; + + public GrAnnotationStub(StubElement parent, String text) { super(parent, GroovyElementTypes.ANNOTATION); - myReference = reference; + myText = text; } public GrAnnotationStub(StubElement parent, GrAnnotation from) { super(parent, GroovyElementTypes.ANNOTATION); - myReference = StringRef.fromString(from.getClassReference().getReferenceName()); + myText = from.getText(); } - public String getAnnotationName() { - return myReference.getString(); + public GrAnnotation getPsiElement() { + if (myPsiRef != null) { + final GrAnnotation annotation = myPsiRef.get(); + if (annotation != null) { + return annotation; + } + } + try { + GrAnnotation annotation = GroovyPsiElementFactory.getInstance(getProject()).createAnnotationFromText(myText, getPsi()); + myPsiRef = new SoftReference(annotation); + return annotation; + } + catch (IncorrectOperationException e) { + LOG.error("Bad annotation in repository!", e); + return null; + } + } + + public String getText() { + return myText; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java new file mode 100644 index 000000000000..9dc51c8eb3af --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.psi.stubs.elements; + +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubInputStream; +import com.intellij.psi.stubs.StubOutputStream; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; +import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationStub; + +import java.io.IOException; + +/** + * Created by Max Medvedev on 12/6/13 + */ +public class GrAnnotationElementType extends GrStubElementType { + public GrAnnotationElementType(@NotNull String name) { + super(name); + } + + @Override + public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) { + return new GrAnnotationImpl(stub); + } + + @Override + public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) { + return new GrAnnotationStub(parentStub, psi); + } + + @Override + public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { + dataStream.writeUTFFast(stub.getText()); + } + + @NotNull + @Override + public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { + return new GrAnnotationStub(parentStub, dataStream.readUTFFast()); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java index 10e803e33880..c54cc965ecc8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java @@ -55,7 +55,7 @@ public class GrStubFileElementType extends IStubFileElementType { @Override public int getStubVersion() { - return super.getStubVersion() + 19; + return super.getStubVersion() + 20; } @NotNull diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy index 30030f20dfdf..6a7d0f864b9f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy @@ -15,14 +15,19 @@ */ package org.jetbrains.plugins.groovy.lang.psi -import com.intellij.psi.PsiClass -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.psi.* +import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl /** * Created by Max Medvedev on 12/4/13 */ -class GrStubAstSwitchTest extends LightCodeInsightFixtureTestCase { +class GrStubAstSwitchTest extends LightGroovyTestCase { + @Override + protected String getBasePath() { + null + } + void testDontLoadContentWhenProcessingImports() { GroovyFileImpl file = (GroovyFileImpl) myFixture.addFileToProject("A.groovy", """ import java.util.concurrent.ConcurrentHashMap @@ -44,4 +49,87 @@ class B extends ConcurrentHashMap { fooMethod.findDeepestSuperMethods() assert !file.contentsLoaded } + + void testDontLoadAstForAnnotation() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B { + @Delegate + A a = new A() +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + PsiField field = clazzB.fields[0] + assert !file.contentsLoaded + + + PsiModifierList modifierList = field.modifierList + assert !file.contentsLoaded + + PsiAnnotation[] annotations = modifierList.annotations + PsiAnnotation annotation = annotations[0] + assert !file.contentsLoaded + + assert annotation.qualifiedName == 'groovy.lang.Delegate' + assert !file.contentsLoaded + } + + void testDontLoadAstForAnnotation2() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B extends A { + @Override + def foo() {} +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + PsiMethod method = clazzB.methods[0] + assert !file.contentsLoaded + + + PsiModifierList modifierList = method.modifierList + assert !file.contentsLoaded + + PsiAnnotation[] annotations = modifierList.annotations + PsiAnnotation annotation = annotations[0] + assert !file.contentsLoaded + + assert annotation.qualifiedName == "java.lang.Override" + assert !file.contentsLoaded + } + + + void testDelegateExists() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B { + @Delegate + A a = new A() +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + assert clazzB.methods.find {it.name =='foo'} + assert !file.contentsLoaded + } } diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index 1283e65c4d4a..fc82b7d5d452 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -3,7 +3,7 @@ group.hg4idea.file.menu.text=Mercurial action.hg4idea.tag.text=Tag Repository... action.hg4idea.tag.description=Create a tag for current revision action.hg4idea.updateTo.text=Update to... -action.hg4idea.updateTo.description=Updating to {0}... +action.hg4idea.updateTo.description=Update the repository's working directory to the specified changeset. action.hg4idea.push.text=Push... action.hg4idea.push.description=Push outgoing commits action.hg4idea.pull.text=Pull... @@ -102,6 +102,7 @@ hg4idea.progress.updatingworkingdir=Updating local working directory hg4idea.progress.integrating=Integrating {0} ... hg4idea.progress.merging=Performing merge... hg4idea.progress.updating=Updating {0} ... +hg4idea.progress.updatingTo=Updating to {0}... hg4idea.progress.countingHeads=Checking number of heads... hg4idea.progress.pull.with.rebase=Rebasing patches hg4idea.progress.pull.with.update=Updating repository diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java index f7a3b8af6987..94ede3f92fbd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java @@ -57,7 +57,7 @@ public class HgUpdateToAction extends HgAbstractGlobalAction { String updateToValue = dialog.isBranchSelected() ? dialog.getBranch().getName() : dialog.isTagSelected() ? dialog.getTag().getName() : dialog.getRevision(); - new Task.Backgroundable(project, HgVcsMessages.message("action.hg4idea.updateTo.description", updateToValue)) { + new Task.Backgroundable(project, HgVcsMessages.message("hg4idea.progress.updatingTo", updateToValue)) { @Override public void run(@NotNull ProgressIndicator indicator) { diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java index 6320a308ff8f..b7d8a7f60b0e 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java @@ -15,6 +15,7 @@ */ package com.intellij.lang.properties.xml; +import com.intellij.ide.highlighter.XmlFileType; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesUtil; import com.intellij.lang.properties.ResourceBundle; @@ -71,7 +72,7 @@ public class XmlPropertiesFile implements PropertiesFile { @Nullable public static PropertiesFile getPropertiesFile(final PsiFile file) { - return file instanceof XmlFile ? getPropertiesFile((XmlFile)file) : null; + return file instanceof XmlFile && file.getFileType() == XmlFileType.INSTANCE ? getPropertiesFile((XmlFile)file) : null; } public static PropertiesFile getPropertiesFile(final XmlFile file) { diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIconProvider.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIconProvider.java index ca8bd0c19e01..713b5112dbda 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIconProvider.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIconProvider.java @@ -1,6 +1,7 @@ package com.intellij.lang.properties.xml; import com.intellij.ide.IconProvider; +import com.intellij.ide.highlighter.XmlFileType; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlFile; import icons.PropertiesIcons; @@ -16,6 +17,8 @@ public class XmlPropertiesIconProvider extends IconProvider { @Override public Icon getIcon(@NotNull PsiElement element, int flags) { - return element instanceof XmlFile && XmlPropertiesFile.getPropertiesFile((XmlFile)element) != null ? PropertiesIcons.XmlProperties : null; + return element instanceof XmlFile && + ((XmlFile)element).getFileType() == XmlFileType.INSTANCE && + XmlPropertiesFile.getPropertiesFile((XmlFile)element) != null ? PropertiesIcons.XmlProperties : null; } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java index ed67161b6773..083546e62288 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java @@ -86,31 +86,26 @@ public final class DomManagerImpl extends DomManager { private final SemService mySemService; private final ConverterManager myConverterManager; private final DomApplicationComponent myApplicationComponent; - private final PsiFileFactory myFileFactory; - private final ProjectFileIndex myFileIndex; private long myModificationCount; private boolean myChanging; public DomManagerImpl(Project project, - final XmlAspect xmlAspect, SemService semService, ConverterManager converterManager, - DomApplicationComponent appComponent, - PsiFileFactory fileFactory, - ProjectFileIndex fileIndex) { + DomApplicationComponent appComponent) { myProject = project; mySemService = semService; myConverterManager = converterManager; myApplicationComponent = appComponent; - myFileFactory = fileFactory; - myFileIndex = fileIndex; - PomModel pomModel = PomManager.getModel(project); + final PomModel pomModel = PomManager.getModel(project); pomModel.addModelListener(new PomModelListener() { public void modelChanged(PomModelEvent event) { - final XmlChangeSet changeSet = (XmlChangeSet)event.getChangeSet(xmlAspect); - if (changeSet != null && !myChanging) { + if (myChanging) return; + + final XmlChangeSet changeSet = (XmlChangeSet)event.getChangeSet(pomModel.getModelAspect(XmlAspect.class)); + if (changeSet != null) { for (XmlFile file : changeSet.getChangedFiles()) { DomFileElementImpl element = getCachedFileElement(file); if (element != null) { @@ -121,7 +116,7 @@ public final class DomManagerImpl extends DomManager { } public boolean isAspectChangeInteresting(PomModelAspect aspect) { - return xmlAspect.equals(aspect); + return aspect instanceof XmlAspect; } }, project); @@ -234,7 +229,7 @@ public final class DomManagerImpl extends DomManager { } private void processFileOrDirectoryChange(final VirtualFile file) { - if (!myFileIndex.isInContent(file)) return; + if (!ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return; if (!file.isDirectory()) { processFileChange(file); } else { @@ -444,7 +439,7 @@ public final class DomManagerImpl extends DomManager { } public final T createMockElement(final Class aClass, final Module module, final boolean physical) { - final XmlFile file = (XmlFile)myFileFactory.createFileFromText("a.xml", StdFileTypes.XML, "", (long)0, physical); + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(myProject).createFileFromText("a.xml", StdFileTypes.XML, "", (long)0, physical); file.putUserData(MOCK_ELEMENT_MODULE, module); file.putUserData(MOCK, new Object()); return getFileElement(file, aClass, "I_sincerely_hope_that_nobody_will_have_such_a_root_tag_name").getRootElement();